我们完成了这项任务,并想知道我们是否忽略了解决方案中的某些内容:
以下代码片段存在问题。它将进行编译,但是存在一个重要的语义问题,这将导致代码的行为与预期不同。确定问题并解决此问题。
int main(void)
{
char * s = malloc(82 * sizeof(char));
if(s==NULL)
{
perror("failed to allocate memory");
return EXIT_FAILURE;
}
fgets(s, sizeof(s), stdin);
if(s[strlen(s)-1] != '\n')
{
fprintf(stderr, "Error: you entered too much input");
free(s);
return EXIT_FAILURE;
}
free(s);
return EXIT_SUCCESS;
}
我们认为错误与fgets
函数有关,因为它将读取包括空终止字符在内的所有内容。因此,我们认为有可能写入一个角色,而不是malloc
'。因此,我们认为行fget(s,sizeof(s)-1, stdin);
将成为解决方案
我们对不对?或者有更多/其他错误?
答案 0 :(得分:3)
sizeof( s )
< => sizeof( char * )
,这不是你想要的。
答案 1 :(得分:2)
sizeof(s)
最有可能是4或8.无论如何,它不会是82。
答案 2 :(得分:2)
这不是一个很长的代码,所以让我们全部解决:
没有包含。你需要:
#include <stdio.h> // perror fgets fprintf
#include <stdlib.h> // malloc free EXIT_FAILURE EXIT_SUCCESS
#include <string.h> // strlen
避免使用魔法常量。如果你需要一些常量,可以在一个地方定义它(带有一个有说服力的名字),然后总是引用它。
#define MY_MAX_STRING_SIZE 82
// Not length, that would be one less due to the terminator
样式点:char
总是只有一个char
。
char * s = malloc(MY_MAX_STRING_SIZE);
fgets
的返回值。失败时,那是NULL
。 sizeof
- 运算符返回其操作数的大小,而不是它可能指向的缓冲区的大小。使用上面的常量:
if(!fgets(s, MY_MAX_STRING_SIZE, stdin)) {
perror("failed to read from stdin");
free(s);
return EXIT_FAILURE;
};
这三行等同于结束main
:
return EXIT_SUCCESS;
return 0;
// C99+
为什么要使用动态分配?自动阵列将更安全,更容易,更高效:
// includes...
int main() {
char s[82];
if(!fgets(s, sizeof(s), stdin)) {
perror("failed to read from stdin");
return EXIT_FAILURE;
};
if(s[strlen(s)-1] != '\n')
{
fprintf(stderr, "Error: you entered too much input");
return EXIT_FAILURE;
}
}