使用 fgets/strtok 逐行处理输入文件

Processing an Input File Line-By-Line Using fgets/strtok

提问人:Lumi 提问时间:11/1/2023 最后编辑:chqrlieLumi 更新时间:11/1/2023 访问量:49

问:

我正在尝试创建一个 C 程序来处理输入文件并查找字数/解剖学的信息(单词数、最长单词的长度、最常见的单词大小及其频率等)。

我对如何做到这一点有一个粗略的想法,但是当用作循环的条件以逐行处理输入文件时,我的程序甚至从未到达循环的主体,从而产生意想不到的结果。fgets

到目前为止,我有以下代码:

// This program reads all lines of an input file and generates 
// a report including: 
//      Number of words in the file 
//      Which word size occurs the most and how many times 
//      Largest word length and its frequency 
//      All words of the longest word length of the file 
//       (duplicates not reported)

#include <stdio.h> 
#include <ctype.h> 
#include <string.h>

#define MAXW 300    // max total words
#define MAXC 17     // max chars in a word 
#define MAXLINEW 82 // max chars to a line 
#define MAXLINE 30  // max number of lines

const char *clean(char *src); 
int getWords(char (*words)[MAXC], FILE *f);

int main(char **argv) {

    char words[MAXC][MAXW] = {{0}};
    int num_words = 0;
    size_t i;

    FILE *f = fopen("input.txt", "r");

    if (!f) {
        fprintf (stderr, "ERROR: Unable to open file '%s'.\n", argv[1]);
        return 1;
    }

    num_words = getWords(words, f);
    printf("Num words = %d\n", num_words);

    fclose(f);
}

const char *clean(char *src) { 
    char *dst; 
    for (; *src; ++src) { 
        if (!ispunct((unsigned char)*src)) 
            *dst++ = tolower((unsigned char)*src); 
            *dst = 0;
    }
    return dst; 
}

int getWords(char (*words)[MAXC], FILE *f) { 
    int word_cnt = 0; 
    int r; 
    char p = NULL; 
    char lines[MAXLINE][MAXLINEW]; 
    char buf[MAXLINEW]; 
    static const char delims[] = " \n"; 
    r = 0; 
    while (fgets(buf, MAXLINEW, f)) { 
        // find the next word 
        if (p == NULL) { 
            p = strtok(buf, delims); 
            while (p) { 
                const char c = clean(p); 
                strcpy(words[word_cnt], c); 
                word_cnt++; 
                p = strtok(NULL, delims); 
            } 
        } 
    } 
}

我正在尝试使用 拆分输入文件的每一行,然后处理每一行以获取每个单词(由换行符空格分隔)。通过标记的每个单词,我想将其传递给函数,该函数应删除任何标点符号并使所有内容都小写。清理单词后,我想将清理后的单词复制到所有单词的最终数组中,稍后可以使用这些数组来生成该程序的所需结果(计算单词长度/频率等)。fgetsstrtokstrtokclean

正如我之前所说,我的程序甚至从未到达 while 循环的主体,我不确定为什么。getWords

我对 C 没有太多经验,但我确实了解 C++,所以如果我的代码缺少任何明显的东西,我很抱歉。

任何帮助将不胜感激,谢谢!

C fgets strtok

评论

0赞 chux - Reinstate Monica 11/1/2023
--> 启用所有编译器警告: ,但 是 而不是 .strcpy(words[word_cnt], c);ccharchar *
1赞 Oka 11/1/2023
const char c = clean(p);也。最大的问题是:/ - 你认为指向哪里?char *dst;return dst;dst
0赞 chux - Reinstate Monica 11/1/2023
int getWords ()缺少return;
0赞 Ted Lyngmo 11/1/2023
int main (char **argv)....缺少一个参数 - 就像如果这是 C++ 一样

答:

0赞 chqrlie 11/1/2023 #1

明显的错误是您将该单词的清理版本存储在 中,但此指针未初始化。clean*dst

您应该改为就地修改源数组:

char *clean(char *src) { 
    char *result = src; 
    char *dst = src; 
    for (; *src; ++src) { 
        if (!ispunct((unsigned char)*src)) 
            *dst++ = tolower((unsigned char)*src); 
    }
    *dst = '\0';
    return result; 
}

另一个错误:应该是const char c = clean(p);

const char *c = clean(p);

也缺少一个参数。用。int main(char **argv)int main()

但请注意,无需存储单词即可计算请求的统计信息。只需编译数组中的字长并进行简单的数学运算即可产生预期的输出。