【发布时间】:2016-06-20 02:42:23
【问题描述】:
如何扫描文本文件中的单词并在每次扫描时增加计数?
我的程序 main 使用两个关键字和一些文件作为命令行参数。在命令行上作为参数传递的每个文件都将包含最多 160 个字符的消息列表。 比如:
$ ./main Hello Bye data1.txt data2.txt
会输出
3 messages containing Hello and 1 messages containing Bye
2 messages containing Hello and 2 messages containing Bye
在 main.c 中的 do_file 方法中,stats_add_data() 在调用时不起作用,我不知道为什么。我检查了指针,它们似乎是正确的。
void do_file(char *filename, char *key1, char *key2) {
stats *newstats;
newstats = stats_create(key1, key2);
FILE *f = fopen(filename, "r");
char *keyword1 = newstats->key1;
char *keyword2 = newstats->key2;
int line_num = 1;
int find_result1 = 0;
int find_result2 = 0;
char temp[160];
const char delimter[1] = " ";
char onewordtoken[160];
// Get a line, up to 160 chars from file
while(fgets(temp, 160, f) != NULL) {
if((strstr(temp, key1)) != NULL) {
printf("A match found on line: %d\n", line_num);
printf("\n%s\n", temp);
find_result1++;
stats_add_data(newstats, temp);
stats_print(newstats);
printf("\n\n");
}
if((strstr(temp, key2)) != NULL) {
printf("A match found on line: %d\n", line_num);
printf("\n%s\n", temp);
find_result2++;
stats_add_data(newstats, temp);
stats_print(newstats);
printf("\n\n");
}
line_num++;
}
if((find_result1 == 0) && (find_result2 == 0)) {
printf("\nSorry, couldn't find a match.\n");
}
}
参考代码:
stats.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stats.h"
// The stats_create function should allocate and return a new stats structure, storing key1 and key2 in the structâs string fields and setting the two integers to 0.
stats *stats_create(char *key1, char *key2) {
stats *new = malloc(sizeof *new);
new->key1 = key1;
new->key2 = key2;
new->int1 = 0;
new->int2 = 0;
return new;
}
// The stats_add_data function should update the structure pointed to by s against the value val. That is, if val contains the first keyword, the integer containing the count of the number of messages containing that keyword should be updated. Similarly for the second keyword.
void stats_add_data(struct stats *s, char *val) {
int count1 = 0;
int count2 = 0;
char* key1 = s->key1;
char* key2 = s->key2;
if (strcmp(s->key1, val) == 0) {
count1++;
}
if (strcmp(s->key2, val) == 0) {
count2++;
}
count1 = s->int1;
count2 = s->int2;
}
// The stats_print function should print on one line the number of messages containing the first keyword, and the number of keywords containing the second keyword. E.g. 2 messages containing Homeland and 2 messages containing Elementary.
void stats_print(struct stats *s) {
int count1 = s->int1;
int count2 = s->int2;
char* key1 = s->key1;
char* key2 = s->key2;
printf("%d", count1);
printf(" messages containing ");
printf("%s", key1);
printf(" and ");
printf("%d", count2);
printf(" messages containing ");
printf("%s", key2);
}
// The stats_free function should free the given stats structure and any memory that might have been allocated for it.
void stats_free(struct stats *s) {
if(s) {
free(s);
}
}
main.c
#include <stdio.h>
#include <string.h>
#include "stats.h"
// A function void do_file(char *filename, char *key1, char*key2) that takes a file name and two keywords as its arguments. It should create a statistics struct that will be used to accumulate the statistics about the data in the file.
//Open the given filename, and iterate over each line of the file, reading in the data value and updating the statistics struct. Once the file has been read, close it and display the results.
void do_file(char *filename, char *key1, char *key2) {
stats *newstats;
newstats = stats_create(key1, key2);
FILE *f = fopen(filename, "r");
char *keyword1 = newstats->key1;
char *keyword2 = newstats->key2;
//char keyword1 = *key1;
//char keyword2 = *key2;
int line_num = 1;
int find_result1 = 0;
int find_result2 = 0;
char temp[160];
if((f = fopen(filename, "r")) == NULL) {
printf("File does not exist!\n");
}
const char delimter[1] = " ";
char onewordtoken[160];
// Get a line, up to 160 chars from file
while(fgets(temp, 160, f) != NULL) {
if((strstr(temp, key1)) != NULL) {
printf("A match found on line: %d\n", line_num);
printf("\n%s\n", temp);
find_result1++;
stats_add_data(newstats, temp);
stats_print(newstats);
printf("\n\n");
}
if((strstr(temp, key2)) != NULL) {
printf("A match found on line: %d\n", line_num);
printf("\n%s\n", temp);
find_result2++;
stats_add_data(newstats, temp);
stats_print(newstats);
printf("\n\n");
}
line_num++;
}
stats_free(newstats);
if((find_result1 == 0) && (find_result2 == 0)) {
printf("\nSorry, couldn't find a match.\n");
}
// Close the file if still open
if(f) {
fclose(f);
}
}
// A main function that iterates over each file argument, except the first, and runs do_file on it. After the 0th argument, the first two command line arguments will be the keywords to process. The remaining arguments will be the file arguments.
int main(int argc, char **argv) {
if(argc > 2) {
//printf("The argument supplied is %s\n", argv[1]);
//stats_add_data();
do_file("data.txt", argv[1], argv[2]);
printf("\n\n");
//stats_free(s);
} else {
printf("Too few arguments supplied.\n");
//stats_free(s);
}
}
【问题讨论】:
-
你介意创建一个MCVE吗?
-
count1 = s->int1;这出现在添加数据函数的末尾。您可能希望参数的顺序颠倒。 -
问题/弱点:1)
if (strcmp(s->key1, val)仅在key1和val相同时有效,如果key1包含在val中则无效。 2)代码设置为计算行数,而不是出现次数。考虑关键字可能会在一行中多次出现。 3) 不处理key="aba"在line = "ababa"中出现2x 4) 假设key 不会跨越行边界key = "a\nb"。 5)“line, up to 160 chars from file”需要一个至少宽1个的缓冲区。 -
仍然无法执行。
stats.h的内容不发布。 -
编译时,启用所有警告,然后修复这些警告。 (对于
gcc,至少使用:-Wall -Wextra -pedantic我也使用-Wconversion -std-gnu99)
标签: c file text word-count