您的任務確定文件中字對的頻率的目的似乎是不可思議的,那就是讓您在調用system
時將shell實用程序的管道字符串包裝起來。那可能教你關於C的是什麼?存在允許shell訪問的system
函數?那麼,它確實如此,而且你可以完成課程,沒有任何學問。
似乎更有可能的是,意圖是讓你瞭解使用結構的持有相關數據集合在一個單一的對象,或在最小陣列或指針索引檢查對在文件中的相鄰詞語中。在2種常規方法中,使用結構或索引算術,使用結構更有利。簡單地容納一對單詞以及看到的對的頻率就是你所需要的。例如:
enum { MAXC = 32, MAXP = 100 };
typedef struct {
char w1[MAXC];
char w2[MAXC];
size_t freq;
} wordpair;
(注意,該enum
簡單定義的常量MAXC
(32
)和MAXP
(100
)每字最多字符,最大對記錄您可以用兩個#define
語句同一端。 )
可以聲明的wordpair
結構,這將保持在一對或單詞w1
和w2
和多少時間對被認爲是在freq
的陣列。結構數組可以像對待任何其他數組一樣對待,排序等。
要分析文件,只需將前兩個單詞讀入第一個結構,保存一個指向第二個單詞的指針,然後讀取文件中剩餘的剩餘單詞,比較由指針和新單詞形成的對是否已經存在(如果只是簡單地更新所看到的次數),並且如果它不存在,則添加一個新對以更新指向讀取的新單詞的指針,然後重複。
下面是一個簡短示例,它將檢查命令行中作爲參數給出的所有文件名中單詞的出現次數(例如./progname file1 file2 ...
)。如果沒有給出文件,默認情況下代碼將從stdin
中讀取。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 32, MAXP = 100 };
typedef struct {
char w1[MAXC];
char w2[MAXC];
size_t freq;
} wordpair;
size_t get_pair_freq (wordpair *words, FILE *fp);
int compare (const void *a, const void *b);
int main (int argc, char **argv) {
/* initialize variables & open file or stdin for seening */
wordpair words[MAXP] = {{"", "", 0}};
size_t i, idx = 0;
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) {
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
/* read from file given, or from stdin (default) */
idx = get_pair_freq (words, stdin);
/* read each remaining file given on command line */
for (i = 2; i < (size_t)argc; i++)
{ if (fp && fp != stdin) { fclose (fp); fp = NULL; }
/* open file for reading */
if (!(fp = fopen (argv[i], "r"))) {
fprintf (stderr, "error: file open failed '%s'.\n",
argv[i]);
continue;
}
/* check 'idx' against MAXP */
if ((idx += get_pair_freq (words, fp)) == MAXP)
break;
}
if (fp && fp != stdin) fclose (fp);
/* sort words alphabetically */
qsort (words, idx, sizeof *words, compare);
/* output the frequency of word pairs */
printf ("\nthe occurrence of words pairs are:\n\n");
for (i = 0; i < idx; i++) {
char pair[MAXC * 2] = "";
sprintf (pair, "%s:%s", words[i].w1, words[i].w2);
printf (" %-32s : %zu\n", pair, words[i].freq);
}
return 0;
}
size_t get_pair_freq (wordpair *pairs, FILE *fp)
{
char w1[MAXC] = "", w2[MAXC] = "";
char *fmt1 = " %32[^ ,.\t\n]%*c";
char *fmt2 = " %32[^ ,.\t\n]%*[^A-Za-z0-9]%32[^ ,.\t\n]%*c";
char *w1p;
int nw = 0;
size_t i, idx = 0;
/* read 1st 2 words into pair, update index 'idx' */
if (idx == 0) {
if ((nw = fscanf (fp, fmt2, w1, w2)) == 2) {
strcpy (pairs[idx].w1, w1);
strcpy (pairs[idx].w2, w2);
pairs[idx].freq++;
w1p = pairs[idx].w2; /* save pointer to w2 for next w1 */
idx++;
}
else {
if (!nw) fprintf (stderr, "error: file read error.\n");
return idx;
}
}
/* read each word in file into w2 */
while (fscanf (fp, fmt1, w2) == 1) {
/* check against all pairs in struct */
for (i = 0; i < idx; i++) {
/* check if pair already exists */
if (strcmp (pairs[i].w1, w1p) == 0 &&
strcmp (pairs[i].w2, w2) == 0) {
pairs[i].freq++; /* update frequency for pair */
goto skipdup; /* skip adding duplicate pair */
}
} /* add new pair, update pairs[*idx].freq */
strcpy (pairs[idx].w1, w1p);
strcpy (pairs[idx].w2, w2);
pairs[idx].freq++;
w1p = pairs[idx].w2;
idx++;
skipdup:
if (idx == MAXP) { /* check 'idx' against MAXP */
fprintf (stderr, "warning: MAXP words exceeded.\n");
break;
}
}
return idx;
}
/* qsort compare funciton */
int compare (const void *a, const void *b)
{
return (strcmp (((wordpair *)a)->w1, ((wordpair *)b)->w1));
}
使用/輸出
鑑於你的"Hi how are you are you."
例如,(根據你LOCALE
按排序順序)產生所期望的結果。
$ echo "Hi how are you are you." | ./bin/file_word_pairs
the occurrence of words pairs are:
Hi:how : 1
are:you : 2
how:are : 1
you:are : 1
(還有就是你對結果進行排序沒有要求,但它使查找/確認輕鬆了許多具有較長的文件)
刪除快速排序
$ echo "Hi how are you are you." | ./bin/file_word_pairs
the occurrence of words pairs are:
Hi:how : 1
how:are : 1
are:you : 2
you:are : 1
雖然你是自由的嘗試使用您的system
版本,爲什麼不花時間學習如何解決C中的問題。如果您想通過撥打system
來學習如何操作,請撥打Linux
課程,因爲這樣做與C沒什麼關係。
仔細查看,在手冊頁中查找對您而言是新手的函數,然後詢問您之後不瞭解的任何內容。
唉! 「在C」?你爲什麼不直接輸入該命令? –
@weather葉片編輯 – user3328381
這是一個任務嗎?你確定你可以使用'system'來調用外部工具嗎?分配通常要求您在不調用其他程序的情況下實現實際功能。 – kaylum