不知道大小的输入字符串

时间:2017-10-12 09:31:53

标签: c string performance pointers memory-management

当我想要存储我不知道尺寸的字符串时,我的方式是什么。

我喜欢这个:

#include <stdio.h>    
#include <conio.h>

int main () {
    char * str;
    str = (char *)malloc(sizeof(char) + 1);
    str[1] = '\0';
    int i = 0;
    int c = '\0';

    do {
        c = getche();
        if(c != '\r'){
            str[i] = c;
            str[i + 1] = '\0';
            i++;
            str = (char *)realloc(str, sizeof(char) + i + 2);
        }
    } while(c != '\r');

    printf("\n%s\n", str);

    free(str);
    return 0;
}

我找到这个页面: Dynamically prompt for string without knowing string size

这是对的吗?如果是,那么:

还有更好的方法吗?

有更有效的方法吗?

5 个答案:

答案 0 :(得分:2)

  

这是对的吗?

主要问题是使用realloc。这是错的。使用realloc时永远不会直接分配指向已分配内存的指针 - 始终使用临时值来获取返回值。像:

char * temp;
temp = realloc(str, 1 + i + 2);
if (temp == NULL)
{
     // out of memory
     .. add error handling
}
str = temp;

原因是realloc可能会失败,在这种情况下它将返回NULL。因此,如果直接分配给str并且realloc失败,则表示您已丢失指向已分配内存(也称为字符串)的指针。

除此之外:

1)不要投射mallocrealloc

2)sizeof(char)始终 1 - 因此您不需要使用它 - 只需输入1

  

还有更好的方法吗?   有更有效的方法吗?

而不是在每个循环中重新分配1 - 这是相当昂贵的性能 - 在许多情况下,(重新)分配更大的块更好。

一种策略是在调用realloc时将分配加倍。因此,如果您已分配128个字节,则下一个分配应为2 * 128 = 256。另一个策略是让它以一些明显大于1的固定大小增长 - 例如你可以让它每次增长1024个。

答案 1 :(得分:1)

Is it correct?

Sort of.

We don't cast the result of malloc() in C.

Is there any better way?

That's primarily opinion-based.

Is there more efficient way?

With regards to time or space?

If you are asking about space, no.

If you are asking about time, yes.

You could dynamically allocate memory for an array with a small size, that would hold the string for a while. Then, when the array would not be able to hold the string any longer, you would reallocate that memory and double its size. And so on, until the whole string is read. When you are done, you could reallocate the memory again, and shrink the size to be the exact number you need for your string.

You see, calling realloc(), is costly in time, since it may have to move a whole memory block, since the memory must be contiguous, and there might not be any space left to perform that operation without moving the memory related to the string.


Note: Of course, a fixed sized array, statically created would be better in terms of time, but worse in terms of memory. Everything is a trade off, that's where you come into play and decide what best suits your application.

答案 2 :(得分:1)

回答这个问题的关键是澄清“不知道大小”一词。

你可能不知道你得到的大小,但你可能知道你会用它做什么。

一些用例:

  • 您对所需数据有限制,例如。一个人的姓名,地址,书名。我猜你有1k或最大16k的空间。

  • 您可以获得连续的数据流,例如。某些传感器或其他设备每秒向您发送数据。在这种情况下,您可以处理数据块。

<强>答案

  • 你需要对大小进行猜测和教育,然后进行处理,并相应地分配空间。
  • 动态处理数据并释放不再需要的空间。

注意: 需要注意的是,您无法分配无限大小的内存。在某些方面,您必须实现错误处理和/或您需要将数据存储在“磁盘”或其他地方。

注意II : 如果您需要更节省空间的解决方案,则不能使用realloc,因为它可能会复制分配的大小(如果系统不能简单地增加分配的空间,它将首先分配新的内存块,并复制当前内容) 。您需要创建自己的存储结构。但它远远超出范围,我期待你真正需要的东西。

答案 3 :(得分:1)

我建议使用缓冲区来避免重复的realloc调用。创建缓冲区或仲裁大小,例如1024填满后,您可以为动态分配的缓冲区重新分配更多空间,并将缓冲区存入其中。

答案 4 :(得分:0)

这个怎么样?

char *string_name;
asprintf(&string_name, "Hello World, my name is %s & I'm %d years old!", "James Bond", 27);
printf("string is %s", string_name);
free(string_name);