2013-08-07 8 views
11

Sono un principiante in C e programmazione di sistema. Per un compito a casa, ho bisogno di scrivere un programma che legge l'input dallo stdin che analizza le linee in parole e che invia parole ai sottoprocessi di ordinamento usando le code di messaggi System V (ad esempio, count words). Mi sono bloccato alla parte di input. Sto cercando di elaborare l'input, rimuovere i caratteri non alfa, inserire tutte le parole alfa in minuscolo e infine dividere una riga di parole in più parole. Finora posso stampare tutte le parole alfa in minuscolo, ma ci sono delle linee tra le parole, che credo non siano corrette. Qualcuno può dare un'occhiata e darmi qualche suggerimento?Lettura da un file di testo e analisi delle parole in C

esempio da un file di testo: Il Progetto Gutenberg EBook di L'Iliade di Omero, da Omero

penso che l'uscita corretta dovrebbe essere:

the 
project 
gutenberg 
ebook 
of 
the 
iliad 
of 
homer 
by 
homer 

Ma la mia uscita è la seguente:

project 
gutenberg 
ebook 
of 
the 
iliad 
of 
homer 
         <------There is a line there 
by 
homer 

Penso che la linea vuota sia causata dallo spazio tra "," e "da". Ho provato cose come "if isspace (c) quindi non fare nulla", ma non funziona. Il mio codice è sotto Qualsiasi aiuto o suggerimento è apprezzato.

#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <fcntl.h> 
#include <errno.h> 
#include <unistd.h> 
#include <string.h> 


//Main Function 
int main (int argc, char **argv) 
{ 
    int c; 
    char *input = argv[1]; 
    FILE *input_file; 

    input_file = fopen(input, "r"); 

    if (input_file == 0) 
    { 
     //fopen returns 0, the NULL pointer, on failure 
     perror("Canot open input file\n"); 
     exit(-1); 
    } 
    else 
    {   
     while ((c =fgetc(input_file)) != EOF) 
     { 
      //if it's an alpha, convert it to lower case 
      if (isalpha(c)) 
      { 
       c = tolower(c); 
       putchar(c); 
      } 
      else if (isspace(c)) 
      { 
       ; //do nothing 
      } 
      else 
      { 
       c = '\n'; 
       putchar(c); 
      } 
     } 
    } 

    fclose(input_file); 

    printf("\n"); 

    return 0; 
} 

EDIT **

Ho modificato il mio codice e finalmente l'uscita corretta:

int main (int argc, char **argv) 
{ 
    int c; 
    char *input = argv[1]; 
    FILE *input_file; 

    input_file = fopen(input, "r"); 

    if (input_file == 0) 
    { 
     //fopen returns 0, the NULL pointer, on failure 
     perror("Canot open input file\n"); 
     exit(-1); 
    } 
    else 
    { 
     int found_word = 0; 

     while ((c =fgetc(input_file)) != EOF) 
     { 
      //if it's an alpha, convert it to lower case 
      if (isalpha(c)) 
      { 
       found_word = 1; 
       c = tolower(c); 
       putchar(c); 
      } 
      else { 
       if (found_word) { 
        putchar('\n'); 
        found_word=0; 
       } 
      } 

     } 
    } 

    fclose(input_file); 

    printf("\n"); 

    return 0; 
} 
+4

+1 per la pubblicazione di codice ragionevole. Un suggerimento: 'perror (input)'. Ci sono poche cose peggiori di un messaggio di errore senza un nome di file. –

+0

funzione strtok forse utile. – keety

risposta

6

Penso che devi solo ignorare qualsiasi carattere non alfa! isalpha (c) altrimenti converti in minuscolo. Dovrai tenere traccia quando trovi una parola in questo caso.

int found_word = 0; 

while ((c =fgetc(input_file)) != EOF) 
{ 
    if (!isalpha(c)) 
    { 
     if (found_word) { 
      putchar('\n'); 
      found_word = 0; 
     } 
    } 
    else { 
     found_word = 1; 
     c = tolower(c); 
     putchar(c); 
    } 
} 

Se è necessario gestire gli apostrofi con parole come "non è", questo dovrebbe farlo.

int found_word = 0; 
int found_apostrophe = 0; 
    while ((c =fgetc(input_file)) != EOF) 
    { 
    if (!isalpha(c)) 
    { 
     if (found_word) { 
      if (!found_apostrophe && c=='\'') { 
       found_apostrophe = 1; 
      } 
      else { 
       found_apostrophe = 0; 
       putchar('\n'); 
       found_word = 0; 
      } 
       } 
    } 
    else { 
     if (found_apostrophe) { 
      putchar('\''); 
      found_apostrophe == 0; 
     } 
     found_word = 1; 
     c = tolower(c); 
     putchar(c); 
    } 
} 
+0

Questo funziona! Grazie! =) – user2203774

0

Sembra che si sta separando le parole da spazi, quindi penso solo

while ((c =fgetc(input_file)) != EOF) 
{ 
    if (isalpha(c)) 
    { 
     c = tolower(c); 
     putchar(c); 
    } 
    else if (isspace(c)) 
    { 
     putchar('\n'); 
    } 
} 

funzionerà anche. A condizione che il testo inserito non abbia più di uno spazio tra le parole.

+0

C'è una sola virgola nell'input che non è stata copiata in output. Il riassunto descrive anche "parole". Tuttavia, breve e semplice; facile da regolare. – usr2564301

1

Ho il sospetto che vogliate veramente gestire gli tutti i caratteri non alfabetici come separatori, non solo gestire gli spazi come separatori e ignorare i caratteri non alfabetici. Altrimenti, foo--bar apparirebbe come una singola parola foobar, giusto? La buona notizia è che rende le cose più facili. È possibile rimuovere la clausola isspace e utilizzare semplicemente la clausola else.

Nel frattempo, sia che trattiate i segni di punteggiatura in modo speciale che no, avete un problema: stampate una nuova riga per qualsiasi spazio. Quindi, una riga che termina con \r\n o \n o anche una frase che termina con ., stamperà una riga vuota. L'ovvio modo è quello di tenere traccia dell'ultimo carattere, o di una bandiera, in modo da stampare solo una nuova riga se hai precedentemente stampato una lettera.

Ad esempio:

int last_c = 0 

while ((c = fgetc(input_file)) != EOF) 
{ 
    //if it's an alpha, convert it to lower case 
    if (isalpha(c)) 
    { 
     c = tolower(c); 
     putchar(c); 
    } 
    else if (isalpha(last_c)) 
    { 
     putchar(c); 
    } 
    last_c = c; 
} 

Ma vuoi veramente per il trattamento di tutta la punteggiatura lo stesso? L'affermazione del problema implica che lo fai, ma nella vita reale è un po 'strano. Ad esempio, è probabile che foo--bar si visualizzi come parole separate foo e bar, ma che lo it's venga visualizzato come parola separata it e s?Inoltre, l'utilizzo di isalpha come regola per "caratteri parola" significa anche che, ad esempio, 2nd verrà visualizzato come nd.

Quindi, se isascii non è la regola appropriata per il tuo caso di utilizzo per distinguere i caratteri di parola dai caratteri separatori, dovrai scrivere la tua funzione che fa la giusta distinzione. È possibile esprimere facilmente tale regola in logica (ad es., isalnum(c) || c == '\'') o con una tabella (solo un array di 128 pollici, quindi la funzione è c >= 0 && c < 128 && word_char_table[c]). Fare cose in questo modo ha l'ulteriore vantaggio di estendere il codice in seguito con Latin-1 o Unicode, o per gestire il testo del programma (che ha caratteri diversi rispetto al testo in lingua inglese), oppure ...

+0

Nota ciò interromperà alcune punteggiature che potrebbero essere necessarie per essere mantenute, inclusi trattini e apostrofi. potreste aver bisogno di casi speciali e, in alcuni casi (ad esempio i trattini seguiti da newline), lanciarli comunque. Altrimenti parole come "non è" non manterranno le loro rappresentazioni originali. – WhozCraig

+0

@WhozCraig: Sì; poiché l'OP saltava esplicitamente tutti i segni di punteggiatura, ho scelto di fare lo stesso. Ma se questo non è ciò che vuole, ha bisogno di un codice extra per questo. Aggiungerò una nota a riguardo alla risposta. – abarnert

+0

Il problema di consentire 'isn't' è che dovrebbe anche consentire' classi'' come "una singola parola". Dipende dall'input se le frasi di citazioni singolarmente saranno il problema * next *, quindi. – usr2564301