[英]Reading from Text files in C
确实是一个小问题。 最好读取一个包含X个单词的文本文件,并将每个单词一个接一个地添加到链接列表中。 即青蛙是老。
因此,The,Frog,Is和Old将分别放入一个ListNode中,所有这些都是从文件中读取的。
真的想知道与fscanf一起使用的最佳功能,如果fscanf甚至是最佳选择。 所有建议都很棒!
干杯。
编辑:我的查询是真的,如果我想解析一个大的文本文件,是否最好将一个单词fscanf逐个地放入数组,添加到列表,自由数组,然后重复? 还是有更有效的方法
“%s”转换说明符将匹配非空格字符。
#define QUOTE(s) #s
#define STR(s) QUOTE(s)
#ifndef BUFSIZE
# define BUFSIZE 255
#endif
char buf[BUFSIZE+1];
while (fscanf(fin, "%" STR(BUFSIZE) "s", buf)) {
/* buf holds next word. Todo:
+ allocate space for word
+ copy word to newly allocated space
+ add to linked list
*/
}
另外, strtok
可用于使用指定的一组字符(作为字符数组)将字符串标记化(分解)为子字符串。 您的系统可能还具有strsep
,旨在取代strtok
。 strtok
和strsep
修改您传入的数组,因此请注意,这不会导致访问数据的代码其他部分出现问题。 strsep
不是线程安全的; 如果您有多个线程访问要解析的字符串,请使用strsep
或strtok_r
。
#ifndef BUFSIZE
# define BUFSIZE 256
#endif
const char separators[] = "\t\n\v\r\f !\"#$%&'()*+,-./:;<=>?@[\\]^`{|}~";
char buf[BUFSIZE], *line, *word, *rest;
while (fgets(buf, BUFSIZE+1, fin)) {
rest = line = buf;
while ((word = strtok_r(line, separators, &rest))) {
/* Todo:
+ allocate space for word
+ copy word to newly allocated space
+ add to linked list
*/
line=rest;
}
}
由于第二个示例一次从文件中读取一行以供strtok_r
处理,因此如果文件中的任何一行的长度超过BUFSIZE-1 个字符,并且一行中的BUFSIZE-1 st和BUFSIZE th字符均为字母,则第二个示例将单词分成两部分。 一种解决方案是创建一个缓冲的字符串流,以便在到达缓冲区的末尾时,缓冲区中剩余的所有内容都移到最前面,而缓冲区的其余部分则充满了文件中的更多数据(只是请注意字长比缓冲区长;在生产代码中,这是一个潜在的安全漏洞,可能导致拒绝服务攻击。
上述所有功能的问题是它们不能处理输入中的空字符。 如果您想解析可能包含空字符的数据,则需要使用非标准函数,其中包括编写自己的函数。
至于效率,您使用的任何算法都需要从文件中读取(复杂度为O(n),并且需要I / O,从而降低程序速度)并分配内存来存储字。 无论您使用fscanf
, strtok
还是其他方法,时间和空间的复杂性变化都不大。 关于唯一可能的事情是分配了多少个中间缓冲区。 找到最有效的实施方案的最佳选择是尝试一对夫妇并进行介绍。
除非您拥有“效率不够的方法”,否则您不应该在寻找“更有效的方法”。
但是类似strtok
东西可能不需要大量malloc
可以满足您的需求。 它使您可以将琴弦切成适当的位置 。 (请谨慎使用!)
如果您追求高速,请在现代台式计算机上...您可以使用多线程。
这个想法是等待I / O时进程不会休眠。 如果您有很多CPU内核,则要提高速度,就是将文件切成大块,然后一个内核处理一个块。 复杂代码和错误的机会很多,但是,速度并不便宜...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.