问题描述
我有一个文件,每行都包含单词及其同义词。 我正在编写这段代码,它应该逐行读取文件,然后从作为同义词的第二个单词开始显示它。 我在第一个循环中使用了变量 count 以便能够计算每个单词的同义词数量,因为同义词数量各不相同。此外,我使用了条件同义词[i]==',',因为每个同义词都用逗号分隔。 我编写这样的代码的目的是将它们放在二叉搜索树中以获得完整的字典。 该代码不包含任何错误,但它不起作用。 我已经尝试过每个循环,但也没有用。
来自文件的示例输入:
abruptly - dead,short,suddenly
acquittance - release
adder - common,vipera
示例预期输出:
dead short suddenly
acquittance realse
common vipera
代码如下:
void LoadFile(FILE *fp){
int count;
int i;
char synonyms[50];
char word[50];
while(fgets(synonyms,50,fp)!=NULL){
for (i=0;i<strlen(synonyms);i++)
if (synonyms[i]==',' || synonyms[i]=='\n')
count++;
}
while(fscanf(fp,"%s",word)==1){
for(i=1;i<strlen(synonyms);i++){
( fscanf(fp,synonyms)==1);
printf("%s",synonyms);
}
}
}
int main(){
char fn[]="C:/Users/CLICK ONCE/Desktop/Semester 4/i2206/Project/Synonyms.txt";
FILE *fp;
fp=fopen(fn,"rt");
if (fp==NULL){
printf("Cannot open this file");
}
else{
LoadFile(fp);
}
return 0;
}
解决方法
我认为代码中表现出的最大的概念误解是未能理解 fgets
和 fscanf
的工作原理。
考虑以下代码行:
while(fgets(synonyms,50,fp)!=NULL){
...
while(fscanf(fp,"%49s",word)==1){
for(i=1;i<strlen(synonyms);i++){
fscanf(fp,synonyms);
printf("%s",synonyms);
}
}
}
fgets
读取输入的一行。 (除非输入行的长度超过 49 个字符(48 + 换行符),在这种情况下 fgets
将只读取前 49 个字符。代码应该检查该条件并处理它。) next fscanf
然后从输入的 next 行读取一个单词。第一行实际上被丢弃了!如果输入的格式符合预期,第二个 scanf
会将单个 -
读入 synonyms
。这使得 strlen(synonyms)
评估为 1,因此 for
循环终止。然后 while scanf
循环读取另一个单词,并且由于 synonyms
仍然包含长度为 1 的字符串,因此永远不会进入 for
循环。 while scanf
然后继续读取文件的其余部分。对 fgets
的下一次调用返回 NULL(因为 fscanf
循环已读取到文件末尾),因此 while/fgets
循环在 1 次迭代后终止。
我相信目的是让 scanfs
中的 while/fgets
对 fgets
读取的行进行操作。为此,应将所有 fscanf
调用替换为 sscanf
。
这是我的解决方案。为了便于阅读,我已将工作拆分为多个函数。实际的解析在 parse
函数中完成。该函数考虑了带连字符的复合词,例如 72。该词和他的同义词必须用连字符分隔,前面至少有一个空格。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Trim leading and trailing space characters.
// Warning: string is modified
char* trim(char* s) {
char* p = s;
int l = strlen(p);
while (isspace(p[l - 1])) p[--l] = 0;
while (*p && isspace(*p)) ++p,--l;
memmove(s,p,l + 1);
return s;
}
// Warning: string is modified
int parse(char* line)
{
char* token;
char* p;
char* word;
if (line == NULL) {
printf("Missing input line\n");
return 0;
}
// first find the word delimiter: an hyphen preceded by a space
p = line;
while (1) {
p = strchr(p,'-');
if (p == NULL) {
printf("Missing hypen\n");
return 0;
}
if ((p > line) && (p[-1] == ' ')) {
// We found an hyphen preceded by a space
*p = 0; // Replace by nul character (end of string)
break;
}
p++; // Skip hyphen inside hypheneted word
}
word = trim(line);
printf("%s ",word);
// Next find synonyms delimited by a coma
char delim[] = ",";
token = strtok(p + 1,delim);
while (token != NULL) {
printf("%s ",token);
token = strtok(NULL,delim);
}
printf("\n");
return 1;
}
int LoadFile(FILE* fp)
{
if (fp == NULL) {
printf("File not open\n");
return 0;
}
int ret = 1;
char str[1024]; // Longest allowed line
while (fgets(str,sizeof(str),fp) != NULL) {
str[strcspn(str,"\r\n")] = 0; // Remove ending \n
ret &= parse(str);
}
return ret;
}
int main(int argc,char *argv[])
{
FILE* fp;
char* fn = "Synonyms.txt";
fp = fopen(fn,"rt");
if (fp == NULL) {
perror(fn);
return 1;
}
int ret = LoadFile(fp);
fclose(fp);
return ret;
}