将带有getchar的char*输出到printf
我正在为即将到来的一堂课扫除我的C技能,在使用将带有getchar的char*输出到printf,c,printf,getchar,cc,C,Printf,Getchar,Cc,我正在为即将到来的一堂课扫除我的C技能,在使用getchar构建字符串之后,我在printf中遇到了这个奇怪的输出。具体来说,我试图输出的任何字符串都会在每个字母后面附加相同的字符序列foo使用cc编译,使用Apple LLVM 5.0(Xcode>)编译,变成“f?8{o?8{o?8}?”。下面是说明问题的示例代码: char * input_buffer = malloc( sizeof( char ) ); char c; while ( ( c = getchar() ) != '\n
getchar
构建字符串之后,我在printf
中遇到了这个奇怪的输出。具体来说,我试图输出的任何字符串都会在每个字母后面附加相同的字符序列foo
使用cc
编译,使用Apple LLVM 5.0
(Xcode>)编译,变成“f?8{o?8{o?8}?”
。下面是说明问题的示例代码:
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 );
我到处都搜索过,但在其他任何地方都看不到,但这似乎有点像边缘情况。这是我没有考虑的某种编码问题吗?- 您只为一个
分配空间给char
input\u buffer
错误。您正在将字符(不是以null结尾的)与字符串连接起来strcat(input_buffer,&c);
返回getchar
类型,但您声明int
属于c
类型char
- 您只为一个
分配空间给char
input\u buffer
错误。您正在将字符(不是以null结尾的)与字符串连接起来strcat(input_buffer,&c);
返回getchar
类型,但您声明int
属于c
类型char
strcat(输入缓冲区,&c);
传递给strcat的每个参数必须是一个有效的以null结尾的字符串
&c
之后的下一个字节为0的可能性非常小
input\u 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;
}
至:
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;
}
不能调用strcat(输入缓冲区,&c) 传递给strcat的每个参数必须是一个有效的以null结尾的字符串
&c
之后的下一个字节为0的可能性非常小
input\u 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;
}
至:
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;
}
sizeof(char)
定义为1。这为单个字符分配空间,并使input\u buffer
指向它
您也没有检查分配是否成功。malloc
在失败时返回空指针;您应该始终检查该指针
分配的char
对象input\u buffer
指向包含垃圾的对象
char c;
while ( ( c = getchar() ) != '\n' ) {
strcat(input_buffer, &c);
}
getchar()
返回一个int
,而不是char
。您可以将结果分配给char
对象,但这样做会使您失去检测和结束文件或错误条件的能力。getchar()
在没有更多字符可读取时返回EOF
;您应该始终检查该值,这样做需要将结果存储在int
中(EOF
是一个不等于任何有效字符的整数值。)
input\u buffer
指向一个未初始化的char
。您可以将其视为一个由单个char
元素组成的数组。strcat的第一个参数必须已经包含一个有效的以null结尾的字符串,并且它必须有足够的空间容纳该字符串以及附加到它的任何内容
c
是一个单独的char
对象,包含您刚刚使用getchar()读取的任何字符。
strcat的第二个参数是一个char*,因此您得到了正确的类型,但该char*`必须指向一个有效的以null结尾的字符串
strcat
将首先扫描input\u 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()
sizeof(char)
定义为1。这为单个字符分配空间,并使input\u buffer
指向它
您也没有检查分配是否成功。malloc
在失败时返回空指针;您应该始终检查该指针
分配的char
对象input\u buffer
指向包含垃圾的对象
char c;
while ( ( c = getchar() ) != '\n' ) {
strcat(input_buffer, &c);
}
getchar()
返回一个int
,而不是char
。您可以将结果分配给char
对象,但这样做会失去检测和结束文件或错误的能力