2017-10-12 27 views
3

当我想要存储字符串时,我不知道大小的方式是什么。不知道大小的输入字符串

我这样做:

#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

它是正确的吗?如果是,那么:

有没有更好的办法?

有没有更高效的方法?

+0

'Cout' in C?怎么样? –

+1

'conio.h'是非标准的。 –

+0

存储对我来说不重要。 – Exon

回答

1

它是正确的吗?

的排序。

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

有没有更好的方法?

这主要是基于意见的。

有没有更高效的方法?

关于时间或空间?

如果你问的是空间,没有。

如果你问时间,是的。

你可以动态地分配一个小尺寸的数组的内存,这将持有一段时间的字符串。然后,当数组无法再保存字符串时,您将重新分配该内存并将其大小加倍。等等,直到整个字符串被读取。完成后,您可以再次重新分配内存,并将大小缩小为字符串所需的确切数量。

你看,叫realloc(),在时间上是昂贵的,因为它可能必须移动整个存储块,由于存储器必须是连续的,并且可能没有任何空间留给执行该操作,而无需移动存储相关到字符串。


注:当然,一个固定大小的数组,静态创建将在时间上在内存方面更好,而且更糟糕。一切都是一种折衷,这就是你进入游戏的地方,并决定什么最适合你的应用。

+0

用于存储分配块或链接存储结构的数组可以提供更多空间高效的解决方案,而不是一直重新分配。但我们可能会处理数据而不是简单地存储数据! – SchLx

+0

很明显@SchLx,但我怀疑这是OP的缩进。 – gsamaras

+0

我只想指出,答案''如果你问的是空间,不是完全正确的!' – SchLx

1

回答这个问题的关键在于澄清术语“不知道大小”。

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

一些用例:

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

  • 你会得到连续的数据流,例如。一些传感器或其他设备每秒都会向您发送数据。在这种情况下,您可能会以块的形式处理数据。

  • 你需要让和受过教育的规模的猜测,你会处理,并相应地分配空间。
  • 即时处理数据并释放不再需要的空间。

注意: 这要注意的是,你不能分配的内存大小不受限制。在某些情况下,您必须实现错误处理和/或您需要将数据存储在“磁盘”或其他位置。

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

1

我建议使用缓冲区来避免重复的realloc调用。创建缓冲区或任意大小,例如1024当它填满时,你可以将更多空间重新分配给动态分配的缓冲区,并将缓冲区移入它。

2

它正确吗?

没有

的主要问题是使用realloc。这是错误的。使用realloc时,不要直接分配给指向已分配内存的指针 - 总是使用临时值来获取返回值。像:

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

这样做的原因是,realloc可能在这种情况下,它会返回NULL失败。因此,如果您直接指定strrealloc失败,则您已丢失指向分配的内存(又名字符串)的指针。

除此之外:

1)不要投mallocrealloc

2)的sizeof(char)的是总是 1 - 所以你不需要使用它 - 只是把1

有没有更好的办法? 有没有更高效的方法?

而不是在每个循环中重新分配1 - 这在性能方面非常昂贵 - 在很多情况下更好地分配一个更大的块。

一种策略是在拨打realloc时将分配翻番。所以如果你已经分配了128个字节,下一个分配应该是2 * 128 = 256。另一种策略是让它增长一些比1大得多的固定大小 - 例如,你可以让它每次增长1024。