2016-04-03 20 views
-5

yinelenen olay sayısını yazdırın, bu kod tek sözcük sayıları için çalışır ve büyük küçük harfle noktalama sözcükleriyle sözcükler arasında ayrım yapar. Bu kodun tek sözcükler yerine çiftler için çalışmasını sağlamak için kolay bir yol var mı? Bir metin dosyasındaki her bir sözcük çiftinin oluşumunu yazdırmam gerektiği gibi. Yardımın çokDosyadaki iki benzersiz kelimenin olası her çifti için, bu çiftin

#include <stdio.h> 
#include <stdlib.h> 


int main(int argc, char **argv) 
{ 
FILE* f = fopen (argv[1], "r"); 
char buffer[10000]; 
if (argc != 2) 
{ 
    fprintf(stderr, "Usage: %s file\n", argv[0]); 

} 
fclose(f); 
snprintf(buffer, sizeof(buffer), "tr -cs '[:punct:][a-z][A-Z]' '[\\n*]' < %s |" 
           " sort | uniq -c | sort -n", argv[1]); 

return(system(buffer)); 
} 

Örnek girişi

, takdir
The Cat Sat On The Mat 

Çıktı (Kedi, Cts, Açık The, Mat, Kedi, Kedi Cts, Kedi günü, 30 çift için)

+1

Huh! "C" de mi? Neden bu komutu doğrudan yazmadın? –

+0

@weather vane bunu düzenlemek – user3328381

+1

Bu bir atama mı? Dış araçları aramak için 'system' kullanmanıza izin verildiğinden emin misiniz? Atamalar genellikle diğer programları çağırmadan gerçek işlevselliği uygulamanızı gerektirir. – kaylum

cevap

0

Bir dosyada kelime çiftlerinin sıklığını belirleyen atamanızın amacının, system numaralı çağrıya piped-string kabuk yardımcı programlarını sarmanızı sağlamak düşünülemez gibi görünüyor. Bu size C hakkında ne öğretir? Kabuk erişimine izin veren bir system işlevi var mı? Eh, öyle, ve yapabildiğin ders, hiçbir şey öğrenilemez.

Size tek bir nesne içinde ilgili verilerin koleksiyonları tutmak için yapıların kullanımını anlamak için, ya da minimum dizinin en veya işaretçi indeksleme çiftleri için kontrol etmek için niyet olduğunu çok daha muhtemel görünüyor bir dosya içindeki bitişik sözcüklerde. 2 normal yaklaşımdan bir yapının veya indeks aritmetiğinin kullanılması, bir yapının kullanılması çok daha faydalıdır. Bir çift kelimeyi tutabilmek için basit bir şey ve eşin görüldüğü frekans tek ihtiyacınız olan şey. örneğin:.

enum { MAXC = 32, MAXP = 100 }; 

typedef struct { 
    char w1[MAXC]; 
    char w2[MAXC]; 
    size_t freq; 
} wordpair; 

(not, enum basitçe aynı sona iki #define ifadeleri kullanabilirsiniz kaydetmek için sabitleri MAXC (32) ve başına kelime maksimum karakterler için MAXP (100) ve maksimum çiftleri tanımlar)

bir çift veya kelimeleri w1 ve w2 ve kaç sefer o çifti freq görülür yapacak wordpair yapı dizisi bildirebilirsiniz. Yapının dizisi, sıralanan diğer diziler gibi ele alınabilir, vb ..

Dosyayı analiz etmek için, ilk kelimeyi ilk yapıda okumalı, ikinci kelimeye bir işaretçiyi kaydetmeli ve imlecin oluşturduğu çiftin ve okunan yeni sözcüğün var olup olmadığını (eğer görüldüğü takdirde sadece birkaç kez güncellendiyse) dosyada kalan her kalan kelimeyi okuyun ve eğer yoksa, yeni bir çift ekleyin. Okunacak yeni kelimeyi işaret eden işaretçi ve tekrarlayın. Aşağıda, komut satırında argümanlar olarak verilen tüm dosya adlarındaki sözcüklerin eşleşmesini kontrol eden kısa bir örnek verilmiştir (örneğin, ./progname file1 file2 ...). Hiçbir dosya verilmediyse, kod stdin'dan varsayılan olarak okunur.

#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)); 
} 

kullanımı

"Hi how are you are you." sizin, örneğin göz önüne alındığında, (sizin LOCALE göre sıralanmış sırayla) istenen sonuçlar üretir/çıkış.

$ 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 

(sonuçları sıralamak gereği yoktur, ancak daha uzun dosyalarla çok daha kolay arama/onay yapar) özgür olmakla birlikte

$ 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 

Qsort Çıkarma system sürümünüzü kullanmayı denemek için, neden C'deki soruna nasıl yaklaşacağınızı öğrenmek için zaman ayırmayın. Bir system numaralı telefondan nasıl yapılacağını öğrenmek istiyorsanız,numaralı telefonu arayın. 210 dersi, bu şekilde yaptığınız gibi, C ile çok az şey yapar.

man sayfalarındaki man sayfalarındaki yeni işlevlere bakın ve daha sonra anlamadığınız herhangi bir şeyi sorun. .

+0

Çok beğenilen David! Ben sadece gcc program.c sonra derlemek için çalışıyorum./a.out words_file.txt ama çalışmıyor, herhangi bir öneri? – user3328381

+0

Elbette gcc -Wall -Wextra dosyaadı.c' Bu 'a.out' üretecek. Daha sonra '' fameame' 'dosya adında çiftleri okumak için. Ayrıca, derlemenize '-o 'ekleyebilir ve yürütülebilir dosyalarınıza gerçek bir ad verebilir, ör. 'gcc -Wall -Wextra -o myexename dosyaadı.c' ve bu 'myexename' sizin yürütülebilir dosya olarak yaratacaktır. –

+0

Kullandım: 'gcc -Wall -Wextra -Ofast -o bin/file_word_pairs file_word_pairs.c' sadece' -Ofast' optimizasyonunu ekledi. –