奇怪的输出char *与getchar到printf

时间:2014-01-18 20:12:00

标签: c printf getchar cc

我正在为即将到来的课程消除我的C技能,在使用printf构建字符串后,我使用getchar遇到了这个奇怪的输出。具体来说,我尝试输出的任何字符串都会获得与每个字母相同的字符序列。 foo变为"f?8@{?o?8@{?o?8@{?"cc进行编译,f¿:¿o¿:¿0¿:¿Apple LLVM 5.0进行编译(Xcode)。以下是说明问题的示例代码:

char * input_buffer = malloc( sizeof( char ) );

char c;
while ( ( c = getchar() ) != '\n' ) {
    strcat(input_buffer, &c);
}

// problem output
printf( "\n%s\n", input_buffer );
// foo -> f¿:¿o¿:¿0¿:¿

// weird side effect is the 4 is required to get a proper len
printf("\ncharacters: %lu\n", strlen( input_buffer ) / 4 );

我到处搜索,但我在其他任何地方都没有看到这个,但这看起来有点像边缘情况。这是一种我没有考虑的编码问题吗?

3 个答案:

答案 0 :(得分:3)

您无法拨打strcat(input_buffer, &c);

传递给strcat的每个参数必须是有效的以空字符结尾的字符串。

&c为0后的下一个字节的可能性非常小。

input_buffer指向的第一个字节为0的可能性也不是很高。

换句话说,strcat读取“垃圾”,直到遇到0个字符,两个参数中的

更改:

while ( ( c = getchar() ) != '\n' ) {
    strcat(input_buffer, &c);
}

for (int i=0; 1; i++)
{
    c = getchar();
    if (c == '\r' || c == '\n')
    {
        input_buffer[i] = 0;
        break;
    }
    input_buffer[i] = c;
}

答案 1 :(得分:2)

  • 您只为一个input_buffer分配空间char
  • strcat(input_buffer, &c);错了。您使用字符串连接字符(它不是以空值终止)。
  • getchar会返回int类型,但您宣布c的类型为char

答案 2 :(得分:1)

char * input_buffer = malloc( sizeof( char ) );
根据定义,

sizeof (char)为1。这为单个字符分配空间,并使input_buffer指向它。

您也没有检查分配是否成功。 malloc在失败时返回空指针;你应该经常检查一下。

char指向的已分配input_buffer对象包含垃圾。

char c;
while ( ( c = getchar() ) != '\n' ) {
    strcat(input_buffer, &c);
}

getchar()会返回int,而非char。您可以将结果分配给char对象,但这样做会导致您无法检测到文件结束或错误情况。当没有更多字符要读时,getchar()会返回EOF;你应该总是检查一下,这样做需要将结果存储在int中。 (EOF是一个与任何有效字符不相等的整数值。)

    strcat(input_buffer, &c);

input_buffer指向一个未初始化的char。您可以将其视为由单个char元素组成的数组。 strcat的第一个参数必须已经包含一个有效的以空字符结尾的字符串,并且它必须有足够的空间来容纳该字符串以及您要附加的字符串。

c是一个char对象,包含您刚刚阅读的任何字符getchar(). The second argument to strcat is a char * , so you've got the right type -- but that char *`必须指向有效的以null结尾的字符串。

strcat将首先扫描input_buffer指向的数组以找到终止'\0'字符,以便它知道从哪里开始追加 - 并且它可能会扫描到不属于的内存中您声明或分配的任何对象,可能会导致程序崩溃。如果它没有爆炸,它将复制从c开始的字符,并将其传递到您不拥有的内存中。您有多种形式的未定义行为。

您不需要使用strcat将单个字符附加到字符串;你可以分配它。

这是一个简单的例子:

char input_buffer[100];
int i = 0; /* index into input_buffer */
int c;
while ((c = getchar()) != '\n' && c != EOF) {
    input_buffer[i] = c;
    i ++;
}
input_buffer[i] = '\0'; /* ensure that it's properly null-terminated */

为了简单起见,我分配了一个固定大小的缓冲区,而不是使用malloc

同样为了简单起见,我省略了输入未超过输入缓冲区末尾的任何检查。如果确实如此,如果你很幸运,程序可能会崩溃;如果你不幸运,它可能只是在破坏不属于你的记忆时起作用。如果输入行不太长,它将正常工作。在任何真实世界的程序中,您都需要检查这个。

顺便说一句,使用fgets()可以更轻松地完成这里所做的事情 - 但是了解事情如何在稍低的水平上运作是很好的。