2010-11-22 71 views
3

我需要一个任务做的是:龟etc():读取和存储未知长度的字符串

  • 打开一个文件(使用fopen()函数)
  • 读学生的姓名(使用龟etc())
  • 店,在一个结构

我的问题的某些部分名称是我需要读取任意长度的字符串转换成的名字,我不知道如何来存储字符串而不浪费内存(或写入未分配的内存Y)。

编辑

我的第一个想法就是分配1个字节(char)的内存块,然后调用realloc的()如果需要更多的字节,但是这似乎并没有非常有效的。或者,如果数组已满,然后在最后将字符复制到新的确切大小的内存块中,也许我可以将数组翻倍。

+3

你的编辑建议realloc加倍的大小对我来说似乎很好。你可以从一个可能足够大的数组开始(因为你知道它是一个学生的名字),并且大部分时间避免重新分配数据。 Supercalifragilisticsuuralralidoscious Antidisestablishmentarianism先生没有去你的学校。 – 2010-11-22 21:19:31

+0

@保罗 - 你确信他没有? – DMan 2010-11-22 23:58:24

回答

5

不要担心浪费100或1000个字节,这对于所有名字来说可能足够长。 我可能只是把你正在读取的缓冲区放入堆栈。

担心写在缓冲区的末尾。即缓冲区溢出。防止这个计划!

当您将名称存储到结构中时,您可以使用malloc缓冲区来存储所需的确切长度的名称(不要忘记为空终止符添加一个额外的字节)。

但是,如果你真的必须存储任何长度的名字,那么你可以用realloc来完成。 即分配一个大小为50字节的malloc的缓冲区。

然后当你需要更多的空间时,使用realloc来增加它的长度。增加长度为50个字节的块,并跟踪一个int的大小,以便知道何时需要再次增长。在某些时候,你将不得不决定缓冲区将会变多长,因为它不能无限增长。

2

您可以逐字符读取字符串,直到找到结尾,然后回退到开头,分配合适大小的缓冲区,然后重新读入该缓冲区,但除非您处于小型嵌入式系统中,否则可能是愚蠢的。首先,fgetc,fread等函数无论如何都会在O/S中创建缓冲区。

您可以分配一个足够大的临时缓冲区,使用长度有限的读取(为了安全),然后分配一个精确大小的缓冲区以将其复制到。除非您认为它可能会超出可用堆栈空间,否则您可能希望在堆栈上而不是通过malloc分配临时缓冲区。

如果您正在为一个小型系统编写单线程代码,您可以在启动时或静态分配一个临时缓冲区,并将其用于多种用途 - 但要非常小心,您的用法不能重叠!考虑到大多数系统的实现复杂性,除非你真的研究事情是如何工作的,否则编写内存优化的代码完全可能需要更多的内存而不是简单的方法。变量初始化可能是另一个令人惊讶的浪费。

2

我的建议是要分配足够大小的缓冲区:

char name_buffer [ 80 ]; 

一般来说,大多数的名字(至少常见的英文名)将在尺寸小于80个字符。如果你觉得你可能需要更多的空间,通过一切手段分配更多。

保留一个计数器变量来知道你有多少个字符已经阅读到您的缓冲区:与fgetc()

int chars_read = 0; /* most compilers will init to 0 for you, but always good to be explicit */ 

此时,读取字符的字符,直到你要么打文件标记的结束或阅读80字符(79真的,因为你需要空终止符的空间)。将你读过的每个字符存入你的缓冲区,增加你的计数器变量。

while ((chars_read < 80) && (!feof(stdin))) { 
    name_buffer [ chars_read ] = fgetc (stdin); 
    chars_read++; 
} 
if (chars_read < 80) 
    name_buffer [ chars_read ] = '\0'; /* terminating null character */ 

我在这里假设您正在阅读从stdin。一个更完整的例子还将检查错误,验证从流中读取的字符是否对某个人的姓名有效(例如,没有数字)等。如果尝试读取的数据多于您分配空间的数据,则打印一个错误消息给控制台。

我的理解是希望保持尽可能小的缓冲区,只分配需要的内容,但学习如何编程的一部分就是了解代码/数据大小,效率和代码可读性的权衡。您可以使用mallocrealloc,但它使代码比所需的复杂得多,它引入了可能会出现错误的位置 - NULL指针,数组索引超出范围错误等等。对于大多数实际情况,分配什么应该足够为您的数据要求加上少量的呼吸空间。如果你发现你遇到很多数据超过缓冲区大小的情况,调整你的缓冲区以适应它 - 这就是调试和测试用例的用处。

相关问题