strcat表现不尽如人意

时间:2017-03-11 02:47:11

标签: c undefined-behavior fgets strcat

我试图编写一个程序,将用户输入两次,然后连接结果,但我遇到了问题。

我的预期输出是:

What would you like your message to be? input
message received: input

What would you like your message to be? words
message received: words

new message: inputwords

相反,我收到了一个乱码。

收到输出:

What would you like your message to be? input
message received: input

What would you like your second message to be? words
message received: words

new message: ??s?inputwords

第一个问题:

如何正确连接这两个字符串?

此外:

由于我只接受每条消息的5个字符输入,我如何在这些fgets调用之间清除缓冲区中的剩余元素,而不将余数读入"垃圾"阵列

以下是我使用的代码:

#include <stdio.h>
#include <string.h>


int main() {

    char message[6];
    char garbage[9999];
    char message2[6];

    printf("\nWhat would you like your message to be? ");
    fgets(message, 6, stdin);

    printf("message received: %s\n", message);

    fgets(garbage, 9999, stdin); //this is gross

    printf("\nWhat would you like your second message to be? ");
    fgets(message2, 6, stdin);

    printf("message received: %s\n", message2);

    fgets(garbage, 9999, stdin); //still gross

    char newString[25];
    strcat(newString, message);
    strcat(newString, message2);

    printf("new message: %s\n", newString);
    return 0;

}

注意:我知道我应该抓住fgets的返回值,为了简洁,我把它留了下来。

2 个答案:

答案 0 :(得分:1)

strcat需要以空字符结尾的字符串,而您的缓冲区未初始化。将第一个来电替换为strcat,呼叫strcpy

char newString[25];
strcpy(newString, message);
strcat(newString, message2);

或者,您可以使用sprintf

char newString[25];
sprintf(newString, "%s%s", message, message2);

答案 1 :(得分:1)

你的问题是

char newString[25];
strcat(newString, message);
strcat(newString, message2);

strcat()假设第一个参数已使用以空字符结尾的字符串进行初始化。第一个调用提供未初始化的数组,因此具有未定义的行为。要解决此问题,只需将第一次调用更改为strcpy()即可将message复制到newString,而无需依赖newString进行初始化。

要刷新一行输入(即读取到文件末尾,读取错误或遇到换行符),常用技术

int c; 
while ((c = fgetc(stdin)) != '\n' && c != EOF) { }

但是,将面向字符的输入(如fgets())与面向字符的输入(如fgetc())混合起来通常不是一个好主意,因为这两者输入的方式与换行符不同。

使用fgets()的替代方案是

char buffer[2];
while (fgets(buffer, sizeof buffer, stdin) != NULL && buffer[0] != '\n') {}

必须使用缓冲区(第一种形式的整数c和第二种形式的buffer)。这两个选项最小化了所需缓冲区的大小(使用sizeof intfgetc()2使用fgets()

有些人建议使用fflush(stdin)。这是一个坏主意 - 根据C标准,fflush()在输入流上给出了未定义的行为。