将字符串与固定大小的数组组合

问题描述

让我们看下面的示例代码,其中我将两个固定大小的数组连接在一起:

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