2016-01-04 18 views
3

我正在学习C编程,我必须实现一个读取未知大小输入字符串的程序。 我写了这个代码:这两种方法在C中获取字符串输入有什么区别?

int main() { 
    char *string; 
    char c; 
    int size = 1; 

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

    if (string == NULL) { 
     printf("Error.\n"); 
     return -1; 
    } 
    printf("Enter a string:"); 
    while ((c = getchar()) != '\n') { 
     *string = c; 
     string = (char*)realloc(string, sizeof(char) * (size + 1)); 
     size++; 
    } 
    string[size - 1] = '\0'; 

    printf("Input string: %s\n", string); 

    free(string); 
    return 0; 
} 

但最后printf没有显示整个字符串,但只有最后一个字符。 所以如果我输入hello, world最后的printf打印d

经过一番研究,我尝试this代码,它的工作原理!但我没有与我的区别。

我希望我自己清楚,谢谢你的关注。

+0

请注意,一次增加字符串大小一个字节可能会导致性能下降。一般来说,你最好把字符串的大小加倍,或者在附近。如果它在结尾处显得太大(例如,你需要2048个字节的字符串,但只能使用1080字节),那么可以使用另一个'realloc()'将其缩小到最小。但这不太可能是一个主要问题。 –

+0

@JonathanLeffler:虽然我同意你的评论,但是'realloc'方案的效率低下是OPs问题中最少的。 – chqrlie

+1

@chqrlie:这就是为什么它是一个评论,而不是一个答案。 –

回答

3

有几个问题与您的代码:

  • 你的所有字符存储到分配的内存
  • 你读字符的第一个字节变成char变量,则无法正确测试EOF
  • 如果标准输入不包含'\n'(例如从空文件重定向),则将运行无限循环,分配所有可用内存并最终崩溃。
  • 不那么重要,您为每个字节的读取重新分配缓冲区,效率低下,但可以稍后进行优化。

这里是一个修正版本:

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    char *string; 
    int c; 
    int len = 0; 

    string = malloc(1); 
    if (string == NULL) { 
     printf("Error.\n"); 
     return -1; 
    } 
    printf("Enter a string:"); 
    while ((c = getchar()) != EOF && c != '\n') { 
     string[len++] = c; 
     string = realloc(string, len + 1); 
     if (string == NULL) { 
      printf("cannot allocate %d bytes\n", len + 1); 
      return -1; 
     } 
    } 
    string[len] = '\0'; 

    printf("Input string: %s\n", string); 
    free(string); 
    return 0; 
} 

关于你提到的有关使用链接的代码的差异问题,它使用相同的方法,少了一个错误,但也多了一个错误:

  • 它将字符存储在str的适当偏移量中。
  • 如果输入文件不包含'\n',则它将与您的输入文件一样运行无限循环。
  • 它调用未定义的行为,因为c未初始化为第一个测试。
5

在你分配的新读取字符,c,以string的代码版本,使用:

*string = c; 

*string点在字符串的开头,所以你跟上替换字符串的第一个字符新读字符。

您链接到该代码执行以下操作:

str[i] = c 

基本上,它被指定的字符字符串的结尾,使用索引i

在您的代码版本中,您可以使用size - 1而不是i

3

尝试改变:

*string = c; 

要:

string[size-1] = c; 

这样,你就不会只是每次覆盖的第一个字符。

1

尝试

*(string + size - 1) = c; 

也许这有助于

+1

为什么用符号代替'string [size-1] = c;'? –

+0

为了表明这里涉及到指针而不是数组。只要OP得知,这个“简短”的答案就很有用。 – Michi

相关问题