簡體   English   中英

比較2個文件

[英]Compare 2 files

我有一個問題,我需要制作一個程序來比較兩個文件。 如果在第一個文件中,我有:

Milk
Sugar
Eggs

在第二個文件中

Vanilla
Soda
Sugar

我想顯示出現在兩個文件中的行。

我沒有太多的c經驗,但是我嘗試了一些。 但是我的問題是,如果不在同一行,我將如何顯示Sugar作為輸出?

#include <stdio.h>
#include <stdlib.h>
#include<string.h>
#define MAX 100

void equal (char*lineone,char*linetwo){
    if(strcmp(lineone,linetwo)==0){
        printf("%s",lineone);
    }
}
int main(){
    FILE *fp1,*fp2;
    fp1=fopen("D:/aici/file1.txt","r");
    fp2=fopen("D:/aici/file2.txt","r");
    char buff[MAX],buff1[MAX];
    int i=0;
    while((fgets(buff,MAX,fp1)!=NULL)&&(fgets(buff1,MAX,fp2))!=NULL){
            //i++;
            equal(buff,buff1);
    }
}

您應該做的(出於性能考慮)是將所有單詞保存到兩個緩沖區中,然后進行比較。 但是,您也可以在實現上稍作更改,就可以做到這一點,只需將循環分為一個主循環和一個內部循環,這樣您將獲得以下效果:對於文件1中的每個單詞,它將比較文件2中的所有單詞同樣,比較時非常慢的方法是先保存所有單詞,然后才進行比較。

void equal (char*lione,char*linetwo){
    if(strcmp(lione,linetwo)==0){
        printf("%s",lineone);
    }
}
int main(){
    FILE *fp1,*fp2;
    fp1=fopen("D:/aici/file1.txt","r");
    fp2=fopen("D:/aici/file2.txt","r");
    char buff[MAX],buff1[MAX];
    int i=0;
    while(fgets(buff,MAX,fp1)!=NULL) {
          while(fgets(buff1,MAX,fp2))!=NULL){
           //i++;
            equal(buff,buff1);
          }

         rewind(fp2);
     }

}

從注釋繼續,無論您是繼續使用fgets (推薦),還是認識到也可以使用fscanf而不用擔心從每個單詞中刪除'\\n' ,您需要驗證程序的每個步驟。 雖然一開始看起來fscanf看起來比較容易,但是您可能想man fscanf一下man fscanf並確定如何控制每個文件流中未讀的'\\n'

以下是一個簡短的示例,繼續使用fgets ,展示了如何測試和刪除fgets讀取並包含在buff的每個尾隨'\\n' (以及每個步驟的合理驗證)。 (注意:我假設由於您的輸入是一個單詞,所以256個字符的緩沖區就足夠了-鑒於未刪節字典中的最長單詞是28個字符,但是您還可以驗證fgets是否已完整讀取每行,或者如果還有其他字符未讀)

以下代碼期望將每個文件的文件名作為程序的前兩個參數給出。

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

#define MAXC 256

int main (int argc, char **argv) {

    if (argc < 3) { /* validate 2 arguments given */
        fprintf (stderr, "error: insufficient input.\n"
                        "usage: %s file1 file2\n", argv[0]);
        return 1;
    }

    char buf1[MAXC] = "",               /* declare buf1 */
         buf2[MAXC] = "";               /* declare buf2 */
    FILE *f1 = fopen (argv[1], "r"),    /* open file 1 */
         *f2 = fopen (argv[2], "r");    /* open file 2 */

    if (!f1) {  /* validate file 1 open for reading */
        fprintf (stderr, "file open failed '%s'\n", argv[1]);
        return 1;
    }

    if (!f2) {  /* validate file 2 open for reading */
        fprintf (stderr, "file open failed '%s'\n", argv[2]);
        return 1;
    }

    while (fgets (buf1, MAXC, f1)) {    /* read each word in file 1 */
        size_t len1 = strlen (buf1);    /* get length */

        if (len1 && buf1[len1 - 1] == '\n')
            buf1[--len1] = 0;       /* overwrite '\n' with nul-byte */

        while (fgets (buf2, MAXC, f2)) {    /* read each in file 2 */
            size_t len2 = strlen (buf2);

            if (len2 && buf2[len2 - 1] == '\n')
                buf2[--len2] = 0;   /* overwrite '\n' with nul-byte */

            if (len1 != len2)       /* if lengths differ, not equal */
                continue;           /* get next word from file 2 */

            if (strcmp (buf1, buf2) == 0)   /* compare strings */
                printf ("%s\n", buf1);      /* print if equal */
        }
        rewind (f2);    /* rewind f2, clear EOF */
    }
    fclose (f1);    /* close f1 */
    fclose (f2);    /* close f2 */

    return 0;
}

(注意:長度檢查if (len1 != len2)只是一種效率檢查,除非單詞長度相等,否則將阻止調用strcmp 。對長度的簡單比較(您已經擁有)比完整函數便宜得多每次都調用strcmp (注意,這確實是一筆小數目的節省,您可以根據需要刪除)

輸入文件(故意沒有POSIX-eol)

故意創建了沒有POSIX行尾的數據文件,以證明如果適當地處理了換行符刪除,則對結果沒有影響。

$ cat dat/f1cmp.txt
Milk
Sugar
Eggs

$ cat dat/f2cmp.txt
Vanilla
Soda
Sugar

使用/輸出示例

$ ./bin/fgets_cmp_words dat/f1cmp.txt dat/f2cmp.txt
Sugar

仔細研究一下,然后集中精力進行驗證。 如果您還有其他問題,請告訴我。


顯示單詞的不同之處

要顯示單詞的不同之處,只需要修改內部循環。 通過循環遍歷buf1buf2的字符並在找到第一個差異時停止,可以進行簡單的比較。 您可以繼續上述兩種情況(1)長度不同; 和(2)其中strcmp != 0的返回strcmp != 0 ,或者您可以在strcmp返回非零值后進行一次測試。

下面顯示了對上面的內部循環的修改。 我不知道您要尋找哪種輸出格式,所以我只輸出了不同的單詞,並顯示了單詞開始不同的字符(從零開始的索引):

    while (fgets (buf2, MAXC, f2)) {    /* read each in file 2 */
        size_t len2 = strlen (buf2);
        int i = 0;

        if (len2 && buf2[len2 - 1] == '\n')
            buf2[--len2] = 0;   /* overwrite '\n' with nul-byte */

        if (len1 != len2) {     /* if lengths differ, not equal */
                                /* locate & output difference */
            for (i = 0; buf1[i] == buf2[i]; i++) {}
            printf ("%s & %s differ at char %d (%c != %c)\n",
                    buf1, buf2, i, buf1[i], buf2[i]);
            continue;              /* get next word from file 2 */
        }

        if (strcmp (buf1, buf2) == 0)        /* compare strings */
            printf ("%s\n", buf1);           /* print if equal  */
        else {                    /* locate & output difference */
            for (i = 0; buf1[i] == buf2[i]; i++) {}
            printf ("%s & %s differ at char %d (%c != %c)\n",
                    buf1, buf2, i, buf1[i], buf2[i]);
        }
    }

使用/輸出示例

$ ./bin/fgets_cmp_wrds dat/f1cmp.txt dat/f2cmp.txt
Milk & Vanilla differ at char 0 (M != V)
Milk & Soda differ at char 0 (M != S)
Milk & Sugar differ at char 0 (M != S)
Sugar & Vanilla differ at char 0 (S != V)
Sugar & Soda differ at char 1 (u != o)
Sugar
Eggs & Vanilla differ at char 0 (E != V)
Eggs & Soda differ at char 0 (E != S)
Eggs & Sugar differ at char 0 (E != S)

查看一下,如果您還有其他問題,請告訴我。

暫無
暫無

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

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