fgets() 的异常行为
Anomalous behaviours of fgets()
输入格式
第一行包含两个整数N和M,中间用一个space隔开,其中N代表人数,M代表话题数。接下来是 N 行。
每行包含一个长度为 M 的二进制字符串。如果第 i 行的第 j 个字符为 1,则第 i 个人知道第 j 个主题;否则,他不知道这个话题。
约束条件
2≤N≤500
1≤M≤500
代码
int main()
{
int i,j,k,m,n;
char *str='[=10=]';
//n - no of persons
//m - no of topics
//Read the m and n from console
scanf("%d %d\n",&n,&m);
//Allocate the memory
str=malloc(501);
for(i=0;i<n;i++)
{
fflush(stdin);
if(fgets(str,501,stdin)!=NULL)
{
if(strlen(str)>0 && str[strlen(str)-1]=='\n')
str[strlen(str)-1]='[=10=]';
}
printf("%s\n",str);
}
//Free used variables
free(str);
return 0;
}
示例输入 1 -
4 5
10101
11100
11010
00101
示例输出 1 -
10101
11100
11010
00101
结果:预期输出与打印输出匹配。
示例输入 2 -
4 500
11100110111100111011001010001110110100111111100111110111100111000110110011111111001001010111111111011011110000111001101011110101011100111011001011110100011011001110110111110010111010100001111011111110110111010101101001111100010111011110011111100110011101110111100110010110111111011010110110011101001011110101110100110011010101111011101111010100011101110110101110101101010110101010111111111001100001110100011010110101110110111111111111111001100101110111110110011010011101110100010111110000000110110110
10101010101001110011110110011101111001011001110101011101111110101011011110010100110011110111111010100001111111111010101111110110111101110101111111100010011011101010111011111010111001111110101110111011100010110101001001001101110111110111011111111101110010100110110011111100101010100001111111111010011001111101010011111110111011001001110111010111111111011011010011101101000010101010011110100111111110101011110011110001110111111011101100011100101100101111111110011101001110101011111001111100111110010001
11111101101110110110111101101111111111110001110100111001010111011011011111011111111010010101111011000101001101110100111111111001110111111101000011110100010001010111101010111111111010111011011110000111010111101011110111100110010000001111111101101110110010010111010111100010100000010011111001100101101011101111000101110110011111110110111111111011010011001000111101101001011101011010010111100001111011001111111001110110011011111011101001001011001111111001011111011111010111010011111010100110110111111100
11111000011111101111111101001100011011111110011110110111011111111100110100011100011111011111011111001010010110110111111000100110111101111000111101100001110000101010011001101101100011000001111010001111101011000110001111110100101001011011111010001101101110011110101001011100111100011111011110001110100100111111111110100110111011101111000011001101111000101011111001101010111100110011101100100010011111111111011110011100011111111011011110011011101110111110011111011111111101111011110111001111010001111001
示例输出 - 2
11100110111100111011001010001110110100111111100111110111100111000110110011111111001001010111111111011011110000111001101011110101011100111011001011110100011011001110110111110010111010100001111011111110110111010101101001111100010111011110011111100110011101110111100110010110111111011010110110011101001011110101110100110011010101111011101111010100011101110110101110101101010110101010111111111001100001110100011010110101110110111111111111111001100101110111110110011010011101110100010111110000000110110110
10101010101001110011110110011101111001011001110101011101111110101011011110010100110011110111111010100001111111111010101111110110111101110101111111100010011011101010111011111010111001111110101110111011100010110101001001001101110111110111011111111101110010100110110011111100101010100001111111111010011001111101010011111110111011001001110111010111111111011011010011101101000010101010011110100111111110101011110011110001110111111011101100011100101100101111111110011101001110101011111001111100111110010001
预期输出 2 - 它应该包含 4 行文本而不是输出中的 2 行。
1) 用 fflush(stdin);
清理输入缓冲区是一种不好的做法(它在任何系统中都不起作用)。如果你真的需要清理 stdin
;
,最好使用像 while(getchar()!='\n');
这样的循环
2) 如果您的行中没有 '[=14=]'
字符,则使用 strlen(str)
获取字符串大小可能会失败,因此表达式 str[strlen(str)-1]='[=15=]';
可能会导致意外结果(据我了解,您想要如果输入很大以放置在 str
中,则设置字符串结尾 - 最好使用 str[500]='[=17=]';
而不要使用 strlen()
... 如果输入短于 500 fgets
放置 '[= 14=]'
最后);
3) 在 malloc(size)
之后你应该在使用分配的内存之前检查返回值。
从 scanf("%d %d\n",&n,&m);
中删除 '\n'
。 '\n'
使输入复杂化。 Any whitespace 作为 scanf()
指令,如 '\n'
、' '
、'\t'
等匹配 任意个白-space。所以 scanf()
不会 return 直到 non-white-space 在 2 个数字之后输入。
不要将 scanf()
与 fgets()
混用。而是使用 fgets()
并限定输入:
char buf[50];
fgets(buf, sizeof buf, stdin); // Should also check `fgets() results
if (2 != sscanf(buf, "%d%d", &n, &m) || n < 2 || n > 500 || [more tests]) {
puts("Bad input");
return 1;
}
移除fflush(stdin);
.
将 printf("%s\n",str);
放在前面的 if(fgets...
块中。
分配 502,而不是 501。+1 用于 '\n'
,+1 用于 '[=27=]'
。这就是您上一个测试用例失败的原因。代码试图读取包含 500 char
和 '\n'
的行,即 501 char
。传递给 fgets()
的 501 为 500 char
和终止空字符 '[=27=]'
.
分配了空间
char *str='[=34=]';
很奇怪。建议 char *str = NULL;
建议循环
str = malloc(502);
for(i=0;i<n;i++) {
if(fgets(str,502,stdin)!=NULL) {
if (strlen(str)>0 && str[strlen(str)-1] == '\n')
str[strlen(str)-1] = '[=11=]';
}
printf("%s\n",str);
}
您需要空间容纳 500 个字符 和 用于终止 \n
和 终止 0
.您只有 500 个字符加上终止零的空间,因此 fgets
不会读取最后的硬 return。由于它保留在输入缓冲区中,因此它会在 \n
的下一次迭代中被读取(并且它应该显示在您的输出中)。
将缓冲区大小增加到 502 以修复。更好的选择是读取第一行并根据该点的字符数分配行缓冲区大小。
输入格式
第一行包含两个整数N和M,中间用一个space隔开,其中N代表人数,M代表话题数。接下来是 N 行。 每行包含一个长度为 M 的二进制字符串。如果第 i 行的第 j 个字符为 1,则第 i 个人知道第 j 个主题;否则,他不知道这个话题。
约束条件
2≤N≤500 1≤M≤500
代码
int main()
{
int i,j,k,m,n;
char *str='[=10=]';
//n - no of persons
//m - no of topics
//Read the m and n from console
scanf("%d %d\n",&n,&m);
//Allocate the memory
str=malloc(501);
for(i=0;i<n;i++)
{
fflush(stdin);
if(fgets(str,501,stdin)!=NULL)
{
if(strlen(str)>0 && str[strlen(str)-1]=='\n')
str[strlen(str)-1]='[=10=]';
}
printf("%s\n",str);
}
//Free used variables
free(str);
return 0;
}
示例输入 1 -
4 5
10101
11100
11010
00101
示例输出 1 -
10101
11100
11010
00101
结果:预期输出与打印输出匹配。
示例输入 2 -
4 500
11100110111100111011001010001110110100111111100111110111100111000110110011111111001001010111111111011011110000111001101011110101011100111011001011110100011011001110110111110010111010100001111011111110110111010101101001111100010111011110011111100110011101110111100110010110111111011010110110011101001011110101110100110011010101111011101111010100011101110110101110101101010110101010111111111001100001110100011010110101110110111111111111111001100101110111110110011010011101110100010111110000000110110110
10101010101001110011110110011101111001011001110101011101111110101011011110010100110011110111111010100001111111111010101111110110111101110101111111100010011011101010111011111010111001111110101110111011100010110101001001001101110111110111011111111101110010100110110011111100101010100001111111111010011001111101010011111110111011001001110111010111111111011011010011101101000010101010011110100111111110101011110011110001110111111011101100011100101100101111111110011101001110101011111001111100111110010001
11111101101110110110111101101111111111110001110100111001010111011011011111011111111010010101111011000101001101110100111111111001110111111101000011110100010001010111101010111111111010111011011110000111010111101011110111100110010000001111111101101110110010010111010111100010100000010011111001100101101011101111000101110110011111110110111111111011010011001000111101101001011101011010010111100001111011001111111001110110011011111011101001001011001111111001011111011111010111010011111010100110110111111100
11111000011111101111111101001100011011111110011110110111011111111100110100011100011111011111011111001010010110110111111000100110111101111000111101100001110000101010011001101101100011000001111010001111101011000110001111110100101001011011111010001101101110011110101001011100111100011111011110001110100100111111111110100110111011101111000011001101111000101011111001101010111100110011101100100010011111111111011110011100011111111011011110011011101110111110011111011111111101111011110111001111010001111001
示例输出 - 2
11100110111100111011001010001110110100111111100111110111100111000110110011111111001001010111111111011011110000111001101011110101011100111011001011110100011011001110110111110010111010100001111011111110110111010101101001111100010111011110011111100110011101110111100110010110111111011010110110011101001011110101110100110011010101111011101111010100011101110110101110101101010110101010111111111001100001110100011010110101110110111111111111111001100101110111110110011010011101110100010111110000000110110110
10101010101001110011110110011101111001011001110101011101111110101011011110010100110011110111111010100001111111111010101111110110111101110101111111100010011011101010111011111010111001111110101110111011100010110101001001001101110111110111011111111101110010100110110011111100101010100001111111111010011001111101010011111110111011001001110111010111111111011011010011101101000010101010011110100111111110101011110011110001110111111011101100011100101100101111111110011101001110101011111001111100111110010001
预期输出 2 - 它应该包含 4 行文本而不是输出中的 2 行。
1) 用 fflush(stdin);
清理输入缓冲区是一种不好的做法(它在任何系统中都不起作用)。如果你真的需要清理 stdin
;
while(getchar()!='\n');
这样的循环
2) 如果您的行中没有 '[=14=]'
字符,则使用 strlen(str)
获取字符串大小可能会失败,因此表达式 str[strlen(str)-1]='[=15=]';
可能会导致意外结果(据我了解,您想要如果输入很大以放置在 str
中,则设置字符串结尾 - 最好使用 str[500]='[=17=]';
而不要使用 strlen()
... 如果输入短于 500 fgets
放置 '[= 14=]'
最后);
3) 在 malloc(size)
之后你应该在使用分配的内存之前检查返回值。
从
scanf("%d %d\n",&n,&m);
中删除'\n'
。'\n'
使输入复杂化。 Any whitespace 作为scanf()
指令,如'\n'
、' '
、'\t'
等匹配 任意个白-space。所以scanf()
不会 return 直到 non-white-space 在 2 个数字之后输入。不要将
scanf()
与fgets()
混用。而是使用fgets()
并限定输入:char buf[50]; fgets(buf, sizeof buf, stdin); // Should also check `fgets() results if (2 != sscanf(buf, "%d%d", &n, &m) || n < 2 || n > 500 || [more tests]) { puts("Bad input"); return 1; }
移除
fflush(stdin);
.将
printf("%s\n",str);
放在前面的if(fgets...
块中。分配 502,而不是 501。+1 用于
'\n'
,+1 用于'[=27=]'
。这就是您上一个测试用例失败的原因。代码试图读取包含 500char
和'\n'
的行,即 501char
。传递给fgets()
的 501 为 500char
和终止空字符'[=27=]'
. 分配了空间
char *str='[=34=]';
很奇怪。建议char *str = NULL;
建议循环
str = malloc(502); for(i=0;i<n;i++) { if(fgets(str,502,stdin)!=NULL) { if (strlen(str)>0 && str[strlen(str)-1] == '\n') str[strlen(str)-1] = '[=11=]'; } printf("%s\n",str); }
您需要空间容纳 500 个字符 和 用于终止 \n
和 终止 0
.您只有 500 个字符加上终止零的空间,因此 fgets
不会读取最后的硬 return。由于它保留在输入缓冲区中,因此它会在 \n
的下一次迭代中被读取(并且它应该显示在您的输出中)。
将缓冲区大小增加到 502 以修复。更好的选择是读取第一行并根据该点的字符数分配行缓冲区大小。