这只是调用得到的错误吗?

时间:2014-10-31 15:12:26

标签: c pointers semantics

我们完成了这项任务,并想知道我们是否忽略了解决方案中的某些内容:

  

以下代码片段存在问题。它将进行编译,但是存在一个重要的语义问题,这将导致代码的行为与预期不同。确定问题并解决此问题。

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);将成为解决方案 我们对不对?或者有更多/其他错误?

3 个答案:

答案 0 :(得分:3)

sizeof( s )< => sizeof( char * ),这不是你想要的。

答案 1 :(得分:2)

sizeof(s)最有可能是4或8.无论如何,它不会是82。

答案 2 :(得分:2)

这不是一个很长的代码,所以让我们全部解决:

  1. 没有包含。你需要:

    #include <stdio.h> // perror fgets fprintf
    #include <stdlib.h> // malloc free EXIT_FAILURE EXIT_SUCCESS
    #include <string.h> // strlen
    
  2. 避免使用魔法常量。如果你需要一些常量,可以在一个地方定义它(带有一个有说服力的名字),然后总是引用它。

    #define MY_MAX_STRING_SIZE 82
    // Not length, that would be one less due to the terminator
    
  3. 样式点:char总是只有一个char

    char * s = malloc(MY_MAX_STRING_SIZE);
    
  4. 始终检查fgets的返回值。失败时,那是NULL
  5. sizeof - 运算符返回其操作数的大小,而不是它可能指向的缓冲区的大小。使用上面的常量:

    if(!fgets(s, MY_MAX_STRING_SIZE, stdin)) {
        perror("failed to read from stdin");
        free(s);
        return EXIT_FAILURE; 
    };
    
  6. 这三行等同于结束main

    return EXIT_SUCCESS;
    return 0;
    // C99+
    
  7. 为什么要使用动态分配?自动阵列将更安全,更容易,更高效:

    // 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; 
        } 
    }