真的是一个小问题。阅读包含X个单词的文本文件,并将每个单词逐个添加到链表中最佳。即青蛙是老的。
因此,The,Frog,Is和Old都会被放入ListNode,所有这些都是从文件中读取的。
我真的想知道与fscanf一起使用的最佳功能,如果fscanf是最好的选择。所有建议都很棒!
干杯。
编辑: 我的查询真的是,如果我想解析一个大文本文件,最好将每个单词逐个fscanf成一个数组,添加到列表,自由数组,并重复?或者是否有更有效的方式
答案 0 :(得分:3)
“%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
还是其他方法,时间和空间复杂度都不会有太大变化;关于唯一可能的事情是分配了多少个中间缓冲区。找到最有效的实现方法的最佳选择是尝试一对并对其进行分析。
答案 1 :(得分:1)
你不应该寻找“一种更有效的方式”,直到你的“方式不够有效”。
但strtok
之类的内容可能会满足您的需求而不需要malloc
。它可以让您在适当的位置划分字符串 。 (小心使用!)
答案 2 :(得分:1)
如果你在现代台式电脑上寻找高速......你可以去多线程。
这个想法是在等待I / O时进程不会休眠。如果您拥有大量CPU核心,那么要获得更高的速度,就是将文件切成大块,一个核心处理一个块。很复杂的代码和错误的机会,但嘿,速度是不便宜...