簡體   English   中英

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

對於具有少量數據選擇的文件(<= 13 個唯一“單詞”,長度 < 100),這可能會意外地“起作用”,方法是用文件中的單詞填充arr1 這將具有向您顯示輸入文件中每個“單詞”的計數的最終效果。


最終,當發生以下情況之一時,您將調用未定義的行為

  • fscanf(in, "%s", temp)讀取溢出temp緩沖區的字符串。
  • count超出了arr1arr2的范圍。
  • strcpy(arr1[count], temp); 復制溢出arr1緩沖區的字符串。
  • 要么fopen失敗。

除了不安全之外, fscanf(in, "%s", temp)會將空格以外的任何內容視為有效字符串的一部分。 這包括尾隨標點符號,這可能是也可能不是問題,具體取決於您要匹配的標記( systems.systems )。 您可能需要更強大的解析。

在任何情況下,要么創建一個由搜索詞和頻率組成的結構數組,要么創建兩個相同長度的 arrays 來表示此數據:

const char *words[6] = { "systems", "programming", "computer", "applications", "language", "machine"};
unsigned freq[6] = { 0 };

無需復制任何內容。 請記住檢查fopen是否失敗,並在讀取時限制%s以免溢出輸入緩沖區。

該程序的 rest 看起來很相似:針對所有搜索詞測試每個輸入“詞”; 如果匹配則增加相應的頻率。

使用結構數組的示例:

#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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM