c程序读取文件并计算数组中指定的单词
c program to read file and count words specified in array
我正在尝试读取一个包含段落的文件,计算特定单词出现的次数(我指定并存储在数组中的单词),然后将该结果打印到另一个看起来像,
systems, 2
computer, 3
programming, 6
等等。目前,这段代码所做的只是吐出段落中的每个单词及其各自的计数。任何帮助将不胜感激。
#include <stdio.h>
#include <string.h>
int main()
{
FILE* in;
FILE* out;
char arr1[13][100] = { "systems", "programming", "computer", "applications", "language", "machine"};
int arr2[180] = {0};
int count = 0;
char temp[150];
in = fopen("out2.dat", "r");
out = fopen("out3.dat", "w");
while (fscanf(in, "%s", temp) != EOF)
{
int i, check = 8;
for (i = 0;i < count;i++)
{
if (strcmp(temp, arr1[i]) == 0)
{
arr2[i]++;
check = 1;
break;
}
}
if (check == 1) continue;
strcpy(arr1[count], temp);
arr2[count++] = 1;
}
int i;
for (i = 0; i < count; i++)
fprintf(out, "%s, %d\n", arr1[i], arr2[i]);
return 0;
}
在整个程序中使用 count
没有多大意义。
声明为int count = 0;
,然后作为本次循环的上界
for (i = 0; i < count; i++)
限制使用哪些搜索词。这也意味着这个循环不会在周围 while
循环的第一次迭代时进入。
因此,check != 1
,所以此后count
用作arr1
中的索引,当前读取的“单词”将被复制到
中
strcpy(arr1[count], temp);
这完全没有意义。为什么要覆盖您正在搜索的数据?
然后count
被用来设置arr2
的第一个元素为1
后增加到1
。
在 while
循环的第二次迭代中,for
循环将 运行 进行一次迭代,比较新读取的“单词” (temp
)针对 arr1
的第一个元素(现在是读取的最后一个“单词”)。
如果匹配:arr2
中的第一个元素从 1
递增到 2
,跳过字符串复制,并且 count
不递增。
如果不匹配,则将新的“单词”复制到arr1
的第二个元素中,arr2
的第二个元素设置为1
,count
增加到 2
.
从这里开始失控。
鉴于上面显示的输入,当 count
达到 13
时,这将访问 arr1
out-of-bounds。
对于数据选择较少的文件(<= 13 个唯一“单词”,长度 < 100),这可能会意外地“起作用”,方法是用文件中的单词填充 arr1
。这将具有向您显示输入文件中每个“单词”的计数的最终效果。
最终,当发生以下情况之一时,您将调用 Undefined Behavior:
fscanf(in, "%s", temp)
读取溢出 temp
缓冲区的字符串。
count
超出了 arr1
或 arr2
的界限。
strcpy(arr1[count], temp);
在 arr1
. 中复制溢出缓冲区的字符串
- 要么
fopen
失败。
除了不安全之外,fscanf(in, "%s", temp)
会将空格以外的任何内容视为有效字符串的一部分。这包括尾随标点符号,这可能是也可能不是问题,具体取决于您要匹配的标记(systems.
与 systems
)。您可能需要更强大的解析。
无论如何,要么创建一个由搜索词和频率组成的结构数组,要么创建两个长度相同的数组来表示此数据:
const char *words[6] = { "systems", "programming", "computer", "applications", "language", "machine"};
unsigned freq[6] = { 0 };
不需要复制任何东西。记得检查 fopen
是否失败,并在读取时限制 %s
以免溢出输入缓冲区。
程序的其余部分看起来很相似:针对所有搜索词测试每个输入“词”;如果匹配则增加相应的频率。
使用结构数组的示例:
#include <stdio.h>
#include <string.h>
int main(void) {
struct {
const char *word;
unsigned freq;
} search_words[] = {
{ "systems", 0 },
{ "programming", 0 },
{ "computer", 0 },
{ "applications", 0 },
{ "language", 0 },
{ "machine", 0 }
};
size_t length = sizeof search_words / sizeof *search_words;
FILE *input_file = fopen("out2.dat", "r");
FILE *output_file = fopen("out3.dat", "w");
if (!input_file || !output_file) {
fclose(input_file);
fclose(output_file);
fprintf(stderr, "Could not access files.\n");
return 1;
}
char word[256];
while (1 == fscanf(input_file, "%255s", word))
for (size_t i = 0; i < length; i++)
if (0 == strcmp(word, search_words[i].word))
search_words[i].freq++;
fclose(input_file);
for (size_t i = 0; i < length; i++)
fprintf(output_file, "%s, %u\n",
search_words[i].word,
search_words[i].freq);
fclose(output_file);
}
cat out3.dat
:
systems, 1
programming, 1
computer, 2
applications, 2
language, 1
machine, 1
我正在尝试读取一个包含段落的文件,计算特定单词出现的次数(我指定并存储在数组中的单词),然后将该结果打印到另一个看起来像,
systems, 2
computer, 3
programming, 6
等等。目前,这段代码所做的只是吐出段落中的每个单词及其各自的计数。任何帮助将不胜感激。
#include <stdio.h>
#include <string.h>
int main()
{
FILE* in;
FILE* out;
char arr1[13][100] = { "systems", "programming", "computer", "applications", "language", "machine"};
int arr2[180] = {0};
int count = 0;
char temp[150];
in = fopen("out2.dat", "r");
out = fopen("out3.dat", "w");
while (fscanf(in, "%s", temp) != EOF)
{
int i, check = 8;
for (i = 0;i < count;i++)
{
if (strcmp(temp, arr1[i]) == 0)
{
arr2[i]++;
check = 1;
break;
}
}
if (check == 1) continue;
strcpy(arr1[count], temp);
arr2[count++] = 1;
}
int i;
for (i = 0; i < count; i++)
fprintf(out, "%s, %d\n", arr1[i], arr2[i]);
return 0;
}
在整个程序中使用 count
没有多大意义。
声明为int count = 0;
,然后作为本次循环的上界
for (i = 0; i < count; i++)
限制使用哪些搜索词。这也意味着这个循环不会在周围 while
循环的第一次迭代时进入。
因此,check != 1
,所以此后count
用作arr1
中的索引,当前读取的“单词”将被复制到
strcpy(arr1[count], temp);
这完全没有意义。为什么要覆盖您正在搜索的数据?
然后count
被用来设置arr2
的第一个元素为1
后增加到1
。
在 while
循环的第二次迭代中,for
循环将 运行 进行一次迭代,比较新读取的“单词” (temp
)针对 arr1
的第一个元素(现在是读取的最后一个“单词”)。
如果匹配:arr2
中的第一个元素从 1
递增到 2
,跳过字符串复制,并且 count
不递增。
如果不匹配,则将新的“单词”复制到arr1
的第二个元素中,arr2
的第二个元素设置为1
,count
增加到 2
.
从这里开始失控。
鉴于上面显示的输入,当 count
达到 13
时,这将访问 arr1
out-of-bounds。
对于数据选择较少的文件(<= 13 个唯一“单词”,长度 < 100),这可能会意外地“起作用”,方法是用文件中的单词填充 arr1
。这将具有向您显示输入文件中每个“单词”的计数的最终效果。
最终,当发生以下情况之一时,您将调用 Undefined Behavior:
fscanf(in, "%s", temp)
读取溢出temp
缓冲区的字符串。count
超出了arr1
或arr2
的界限。strcpy(arr1[count], temp);
在arr1
. 中复制溢出缓冲区的字符串
- 要么
fopen
失败。
除了不安全之外,fscanf(in, "%s", temp)
会将空格以外的任何内容视为有效字符串的一部分。这包括尾随标点符号,这可能是也可能不是问题,具体取决于您要匹配的标记(systems.
与 systems
)。您可能需要更强大的解析。
无论如何,要么创建一个由搜索词和频率组成的结构数组,要么创建两个长度相同的数组来表示此数据:
const char *words[6] = { "systems", "programming", "computer", "applications", "language", "machine"};
unsigned freq[6] = { 0 };
不需要复制任何东西。记得检查 fopen
是否失败,并在读取时限制 %s
以免溢出输入缓冲区。
程序的其余部分看起来很相似:针对所有搜索词测试每个输入“词”;如果匹配则增加相应的频率。
使用结构数组的示例:
#include <stdio.h>
#include <string.h>
int main(void) {
struct {
const char *word;
unsigned freq;
} search_words[] = {
{ "systems", 0 },
{ "programming", 0 },
{ "computer", 0 },
{ "applications", 0 },
{ "language", 0 },
{ "machine", 0 }
};
size_t length = sizeof search_words / sizeof *search_words;
FILE *input_file = fopen("out2.dat", "r");
FILE *output_file = fopen("out3.dat", "w");
if (!input_file || !output_file) {
fclose(input_file);
fclose(output_file);
fprintf(stderr, "Could not access files.\n");
return 1;
}
char word[256];
while (1 == fscanf(input_file, "%255s", word))
for (size_t i = 0; i < length; i++)
if (0 == strcmp(word, search_words[i].word))
search_words[i].freq++;
fclose(input_file);
for (size_t i = 0; i < length; i++)
fprintf(output_file, "%s, %u\n",
search_words[i].word,
search_words[i].freq);
fclose(output_file);
}
cat out3.dat
:
systems, 1
programming, 1
computer, 2
applications, 2
language, 1
machine, 1