[英]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
仔細研究一下,然后集中精力進行驗證。 如果您還有其他問題,請告訴我。
要顯示單詞的不同之處,只需要修改內部循環。 通過循環遍歷buf1
和buf2
的字符並在找到第一個差異時停止,可以進行簡單的比較。 您可以繼續上述兩種情況(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.