c - 为什么我用 C 编写的以下 getString() 函数不起作用?

标签 c c-strings

#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 中的用户输入,并将其存储在一个动态调整大小的数组中。然而,每次我运行这个程序时,它都会崩溃。 我经历了该程序的类似实现,但无法准确找出我的代码出了什么问题

最佳答案

问题就出在这里。

        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的内存。

您想要的是在复制newString的指针之前释放(inputString)旧内存。

        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 不是以 null 结尾的。否则它会从字符串末尾读取垃圾。

strncpy 并不是特别安全,当它停止复制时,它不会以 null 终止,但对于这个特定的实例,您可以在最后以 null 终止,这样就可以了。

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

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

关于c - 为什么我用 C 编写的以下 getString() 函数不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42036516/

相关文章:

c - 我该如何解决这个堆栈溢出错误?

c++ - 使用 char* 存储正确的文件路径

c - 为什么我的 BST 中没有插入任何元素

c - 如何读取像 0x7c00009d 这样的十六进制数字?

c - 将数组作为宏参数传递

c - 使用多个线程分配内存时出现段错误

c++ - 如何使用 strcpy_s() 将多个 char* 字符串复制到一个字符串中?

c - 在字符串上使用指针

arrays - 使用 strcpy() 在 C 中正确为指针赋值

c - C 中 printf() 的格式说明符 %a