为什么我在C中写的下面的getString()函数不起作用?

问题描述:

#include <stdio.h> 

char* getString() 
{ 
    char buffer; 
    int size = 0; 
    int capacity = 1; 

    char* inputString = (char*)malloc(capacity*sizeof(char)); 
    char* newString; 

    while(1) 
    { 
     buffer = getchar(); 
     if(buffer == '\n') 
      break; 
     if((capacity-1) <= size) 
     { 
      capacity *= 2; 
      newString = (char*)malloc(capacity*sizeof(char)); 
      int i; 
      for(i = 0; i < size; i++) 
       newString[i] = inputString[i]; 
      inputString = newString; 
      free(newString); 
     } 
     inputString[size] = buffer; 
     size++; 
    } 
    inputString[size] = '\0'; 
    return inputString; 
} 

int main() 
{ 
    char* str; 
    str = getString(); 
    printf("%s", str); 
} 

我写了这个C程序来获取一个字符串作为C中的用户输入并将其存储在一个可动态调整大小的数组中。但是,每次运行此程序时,它都会崩溃。 我经历了这个程序的类似实现,但不能准确找出我的代码有什么问题为什么我在C中写的下面的getString()函数不起作用?

+1

你使用调试器吗?这是调试这些问题的方法(并且作为最后的手段在*上发布)。 – kaylum

+2

'* buffer = getchar();'查看你的代码来回答:'buffer'指向哪里?试试'char buffer = getchar();' – kaylum

+0

@kalyum试过了,仍然没有用 – Sahil

问题在这里。

 capacity *= 2; 
     newString = (char*)malloc(capacity*sizeof(char)); 
     int i; 
     for(i = 0; i < size; i++) 
      newString[i] = inputString[i]; 
     inputString = newString; 
     free(newString); 

这是试图做的是...

  1. 分配一个更大的字符串。
  2. 将旧字符串复制到新字符串。
  3. 使用新的字符串。
  4. 释放旧的字符串。

但事实并非如此。问题是inputString = newString意味着inputString点在newString的记忆。当你接着free(newString)那也是inputString的记忆。

你想要的是free(inputString),旧存储器,复制newString的指针前。

 capacity *= 2; 
     newString = (char*)malloc(capacity*sizeof(char)); 
     int i; 
     for(i = 0; i < size; i++) 
      newString[i] = inputString[i]; 
     free(inputString); 
     inputString = newString; 

的一些注意事项。

您应该从容量至少为2开始,因为容量为1的字符串只能容纳空字节。

字符串复制可以用strncpy更好地完成。

 capacity *= 2; 
     newString = (char*)malloc(capacity*sizeof(char)); 
     strncpy(newString, inputString, size); 
     free(inputString); 
     inputString = newString; 

即使newString是大到足以容纳的inputString内容,我们仍然需要使用strncpy有限制,因为inputString不是空终止。否则,它会读取字符串末尾的垃圾。

strncpy不是特别安全,它不会在它停止复制时终止,但是对于这个特定的实例,您将在终止时终止它是正常的。

接下来,这是没有必要的。它可以通过realloc完成。这会增大,缩小或重新分配内存,并在必要时进行复制。

 capacity *= 2; 
     inputString = realloc(inputString, capacity * sizeof(char)); 
     if(inputString == NULL) { 
      fprintf(stderr, "Reallocation failed.\n"); 
      exit(1); 
     } 
+0

'inputString'在循环结束之前不是空终止的;使用'strcpy()'是不可靠的。使用'memmove()'或'memcpy()'会更合适。而'oldptr = realloc(oldptr,newsize);'meme是等待中的内存泄漏 - 你应该有'newptr = realloc(oldptr,newsize); if(newptr!= 0)oldptr = newptr;其他{...处理错误...}为了安全。 –

+0

@JonathanLeffler谢谢,我知道我错过了什么。 'memcpy'和'strncpy'在这里有什么优势吗?如果我在'realloc'错误处理上吝啬一点,那么你会原谅我,这是它自己的主题。 – Schwern

+0

这将是微不足道的,但是; 'strncpy()'必须计数并检查空字节(它不会找到),而'memcpy()'只需要计数。 –