问题描述
让我们看下面的示例代码,其中我将两个固定大小的数组连接在一起:
int main(void) {
char first_name[20],last_name[20],full_name[40];
puts("First Name?");
fgets(first_name,20,stdin);
puts("Last Name?");
fgets(last_name,stdin);
strcat(full_name,first_name);
strcat(full_name," ");
strcat(full_name,last_name);
puts(full_name);
}
假设名字/姓氏少于 20 个字符,这将产生如下输出:
Robert Diaz
这是因为 full_name
尚未初始化,还是由于 strcat
的工作原理?有什么更好的方法可以做到这一点?
解决方法
对于初学者来说,程序有未定义的行为,因为数组 full_name
未初始化且不包含字符串。
char first_name[20],last_name[20],full_name[40];
因此您不能使用 strcat
将字符串附加到不存在的字符串。
另一个问题是函数 fgets
可以将换行符 '\n'
附加到读取的字符串中。你应该删除它。
程序可以如下所示
#include <stdio.h>
#include <string.h>
int main(void)
{
enum { N = 20 };
char first_name[N],last_name[N],full_name[2 * N];
puts( "First Name?" );
fgets( first_name,N,stdin );
first_name[ strcspn( first_name,"\n" )] = '\0';
puts( "Last Name?" );
fgets( last_name,stdin );
last_name[ strcspn( last_name,"\n" )] = '\0';
strcpy( full_name,first_name );
strcat( full_name," " );
strcat( full_name,last_name );
puts( full_name );
}
程序输出可能看起来像
First Name?
Robert
Last Name?
Disz
Robert Diaz
,
您必须初始化 full_name[40]
。使用这个初始化:
char full_name[40] = {0};
仍然会得到一个奇怪的输出:
Robert
Diaz
请记住,fgets()
函数在按下 Enter 键后会留下一个换行符。因此,您需要将换行符替换为 \0
,或者只是一个零。
if (fgets(first_name,20,stdin) == NULL) {
// incorrectly executed
return 1;
}
first_name[strlen(first_name) - 1] = 0;
此后,您将不再遇到任何问题。你应该得到类似的输出:
Robert Diaz
,
我认为 sprintf
会在这里提供更好/更清洁的服务。
//strcat(full_name,first_name);
//strcat(full_name," ");
//strcat(full_name,last_name);
snprintf(full_name,sizeof(full_name),"%s %s",first_name,last_name);
如果没有,请查看 man page of sprintf。