c - 程序以错误的方式打印字符串。字符串
问题描述
在我输入姓名和姓氏(例如:姓名:Mario
姓氏:)Rossi
作为输出而不是得到Mario Rossi
我得到ossi Rossi
但我不明白为什么。
int main() {
char space[] = " ";
char name[40], surname[40], space_name[40], space_surname[40];
printf("what's your name");
scanf("%[^\n]", &name);
printf("Whats your surname");
scanf(" %[^\n]", &surname);
strcpy(space_surname, strcat(space, surname));
strcat(name, space_surname);
printf("%s", name);
}
解决方案
在您的代码中,您首先在 with 末尾连接,surname
它具有未定义的行为,因为只有 2 个元素,一个空格和一个空终止符。最后的复制会破坏数组,您会观察到该数组。这种行为是未定义的,它在您的体系结构上以这种方式发生,但未定义的行为可能会产生其他后果,包括没有可见的影响或计算机崩溃。space
strcat(space, surname)
space
surname
name
name
ossi
另请注意以下备注:
- 您应该告诉
scanf()
要存储的最大字符数,name
并surname
避免在输入过长时出现未定义的行为。 - 你应该通过
name
而不是&name
. - 您应该测试 的返回值
scanf()
以避免无效输入的未定义行为,例如在文件意外结束或第一个空行的情况下scanf()
。 - 您可以定义具有始终定义行为的大小的数组。
对于更简洁的方法,您将使用 2 个不同的数组firstname
和surname
用户输入并将名称构造为第三个数组,该数组name
对于所有情况都足够大:
strcpy(name, firstname);
strcat(name, " ");
strcat(name, surname);
或可读性较差:
strcat(strcat(strcpy(name, firstname), " "), surname);
以上两种方法都将不必要地遍历已经复制到name
. 一个更清洁、更安全的解决方案是使用snprinf()
:
snprintf(name, sizeof name, "%s %s", firstname, surname);
这是修改后的版本:
#include <stdio.h>
#include <string.h>
int main() {
char firstname[40]; /* up to 39 characters for the first name */
char surname[40]; /* up to 39 characters for the last name */
char name[80]; /* 39 chars + 1 space + 39 chars + 1 null terminator */
printf("What is your name: ");
if (scanf(" %39[^\n]", name) != 1)
return 1;
printf("What is your surname: ");
if (scanf(" %39[^\n]", surname) != 1)
return 1;
/* simpler solution with `snprintf` */
snprintf(name, sizeof name, "%s %s", firstname, surname);
printf("%s\n", name);
return 0;
}