2010-10-12 17 views
21

Ho scritto il seguente codice per leggere una riga da una finestra di terminale, il problema è che il codice si blocca in un ciclo infinito. La riga/frase è di lunghezza indefinita, quindi ho intenzione di leggerlo in parti nel buffer, quindi concatenarlo a un'altra stringa che può essere estesa via realloc di conseguenza. Per favore qualcuno può individuare il mio errore o suggerire un modo migliore per raggiungere questo obiettivo?Come leggere da stdin con fgets()?

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

#define BUFFERSIZE 10 

int main (int argc, char *argv[]) 
{ 
    char buffer[BUFFERSIZE]; 
    printf("Enter a message: \n"); 
    while(fgets(buffer, BUFFERSIZE , stdin) != NULL) 
    { 
     printf("%s\n", buffer); 
    } 
    return 0; 
} 
+0

Sembra piuttosto ok, quando vuoi terminare il ciclo? Come è ora, puoi terminarlo premendo ctrl + d su * nix o ctrl + z su windows. – nos

+1

Non vedo nulla di evidentemente sbagliato nel codice - quando dici "bloccato in un loop infinito", cosa intendi esattamente? –

+0

La mia sfera di cristallo mi dice che Paul R ha inchiodato il problema. La soluzione è mettere il 'printf' all'interno del ciclo. – pmg

risposta

14

qui una soluzione di concatenazione:

char *text = calloc(1,1), buffer[BUFFERSIZE]; 
printf("Enter a message: \n"); 
while(fgets(buffer, BUFFERSIZE , stdin)) /* break with ^D or ^Z */ 
{ 
    text = realloc(text, strlen(text)+1+strlen(buffer)); 
    if(!text) ... /* error handling */ 
    strcat(text, buffer); /* note a '\n' is appended here everytime */ 
    printf("%s\n", buffer); 
} 
printf("\ntext:\n%s",text); 
4

Hai un'idea sbagliata di cosa restituisce fgets. Date un'occhiata a questo: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

Restituisce null quando trova un carattere EOF. Prova a eseguire il programma in alto e premi CTRL + D (o qualsiasi combinazione è il tuo carattere EOF), e il ciclo uscirà con successo.

Come si desidera rilevare la fine dell'input? Nuova linea? Dot (hai detto frase xD)?

+0

la fine dell'input dovrebbe essere una nuova riga – robdavies35

+0

Analizza il buffer per le nuove righe, quindi :) – slezica

1

Supponendo che si desideri solo leggere una sola riga, quindi utilizzare LINE_MAX, che è definito in <limits.h>:

#include <stdio.h> 
... 
char line[LINE_MAX]; 
... 
if (fgets(line, LINE_MAX, stdin) != NULL) { 
... 
} 
... 
+3

LINE_MAX NON è C89 o C99, è l'unico compilatore specifico – user411313

+1

Divertente si mostra un codice utilizzando 'LINE_MAX' senza includere' limits.h' –

0

Se si desidera concatenare il immettere, quindi sostituire printf("%s\n", buffer); con strcat(big_buffer, buffer);. Inoltre, crea e inizializza il buffer grande all'inizio: char *big_buffer = new char[BIG_BUFFERSIZE];big_buffer[0] = '\0';. È inoltre necessario evitare un sovraccarico del buffer verificando la lunghezza del buffer corrente più la nuova lunghezza del buffer non superi il limite: if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE). Il programma modificato sarebbe il seguente:

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

#define BUFFERSIZE 10 
#define BIG_BUFFERSIZE 1024 

int main (int argc, char *argv[]) 
{ 
    char buffer[BUFFERSIZE]; 
    char *big_buffer = new char[BIG_BUFFERSIZE]; 
    big_buffer[0] = '\0'; 
    printf("Enter a message: \n"); 
    while(fgets(buffer, BUFFERSIZE , stdin) != NULL) 
    { 
     if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE) 
     { 
      strcat(big_buffer, buffer); 
     } 
    } 
    return 0; 
} 
+0

'new' è C++ ma la domanda riguarda C –

1

Esce dal ciclo se la linea è vuota (miglioramento del codice).

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

// The value BUFFERSIZE can be changed to customer's taste . Changes the 
// size of the base array (string buffer)  
#define BUFFERSIZE 10 

int main(void) 
{ 
    char buffer[BUFFERSIZE]; 
    char cChar; 
    printf("Enter a message: \n"); 
    while(*(fgets(buffer, BUFFERSIZE, stdin)) != '\n') 
    { 
     // For concatenation 
     // fgets reads and adds '\n' in the string , replace '\n' by '\0' to 
     // remove the line break . 
/*  if(buffer[strlen(buffer) - 1] == '\n') 
      buffer[strlen(buffer) - 1] = '\0'; */ 
     printf("%s", buffer); 
     // Corrects the error mentioned by Alain BECKER.  
     // Checks if the string buffer is full to check and prevent the 
     // next character read by fgets is '\n' . 
     if(strlen(buffer) == (BUFFERSIZE - 1) && (buffer[strlen(buffer) - 1] != '\n')) 
     { 
      // Prevents end of the line '\n' to be read in the first 
      // character (Loop Exit) in the next loop. Reads 
      // the next char in stdin buffer , if '\n' is read and removed, if 
      // different is returned to stdin 
      cChar = fgetc(stdin); 
      if(cChar != '\n') 
       ungetc(cChar, stdin); 
      // To print correctly if '\n' is removed. 
      else 
       printf("\n"); 
     } 
    } 
    return 0; 
} 

Esci quando si preme Invio.

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

#define BUFFERSIZE 16 

int main(void) 
{ 
    char buffer[BUFFERSIZE]; 
    printf("Enter a message: \n"); 
    while(true) 
    { 
     assert(fgets(buffer, BUFFERSIZE, stdin) != NULL); 
     // Verifies that the previous character to the last character in the 
     // buffer array is '\n' (The last character is '\0') if the 
     // character is '\n' leaves loop. 
     if(buffer[strlen(buffer) - 1] == '\n') 
     { 
      // fgets reads and adds '\n' in the string, replace '\n' by '\0' to 
      // remove the line break . 
      buffer[strlen(buffer) - 1] = '\0'; 
      printf("%s", buffer); 
      break; 
     } 
     printf("%s", buffer); 
    } 
    return 0; 
} 

concatenazione e allocazione dinamica (lista collegata) per una singola stringa.

/* Autor : Tiago Portela 
    Email : [email protected] 
    Sobre : Compilado com TDM-GCC 5.10 64-bit e LCC-Win32 64-bit; 
    Obs : Apenas tentando aprender algoritimos, sozinho, por hobby. */ 

#include <stdio.h> 
#include <stdlib.h> 
#include <stdbool.h> 
#include <string.h> 
#include <assert.h> 

#define BUFFERSIZE 8 

typedef struct _Node { 
    char *lpBuffer; 
    struct _Node *LpProxNode; 
} Node_t, *LpNode_t; 

int main(void) 
{ 
    char acBuffer[BUFFERSIZE] = {0}; 
    LpNode_t lpNode = (LpNode_t)malloc(sizeof(Node_t)); 
    assert(lpNode!=NULL); 
    LpNode_t lpHeadNode = lpNode; 
    char* lpBuffer = (char*)calloc(1,sizeof(char)); 
    assert(lpBuffer!=NULL); 
    char cChar; 


    printf("Enter a message: \n"); 
    // Exit when Enter is pressed 
/* while(true) 
    { 
     assert(fgets(acBuffer, BUFFERSIZE, stdin)!=NULL); 
     lpNode->lpBuffer = (char*)malloc((strlen(acBuffer) + 1) * sizeof(char)); 
     assert(lpNode->lpBuffer!=NULL); 
     strcpy(lpNode->lpBuffer, acBuffer); 
     if(lpNode->lpBuffer[strlen(acBuffer) - 1] == '\n') 
     { 
      lpNode->lpBuffer[strlen(acBuffer) - 1] = '\0'; 
      lpNode->LpProxNode = NULL; 
      break; 
     } 
     lpNode->LpProxNode = (LpNode_t)malloc(sizeof(Node_t)); 
     lpNode = lpNode->LpProxNode; 
     assert(lpNode!=NULL); 
    }*/ 

    // Exits the loop if the line is empty(Improving code). 
    while(true) 
    { 
     assert(fgets(acBuffer, BUFFERSIZE, stdin)!=NULL); 
     lpNode->lpBuffer = (char*)malloc((strlen(acBuffer) + 1) * sizeof(char)); 
     assert(lpNode->lpBuffer!=NULL); 
     strcpy(lpNode->lpBuffer, acBuffer); 
     if(acBuffer[strlen(acBuffer) - 1] == '\n') 
      lpNode->lpBuffer[strlen(acBuffer) - 1] = '\0'; 
     if(strlen(acBuffer) == (BUFFERSIZE - 1) && (acBuffer[strlen(acBuffer) - 1] != '\n')) 
     { 
      cChar = fgetc(stdin); 
      if(cChar != '\n') 
       ungetc(cChar, stdin); 
     } 
     if(acBuffer[0] == '\n') 
     { 
      lpNode->LpProxNode = NULL; 
      break; 
     } 
     lpNode->LpProxNode = (LpNode_t)malloc(sizeof(Node_t)); 
     lpNode = lpNode->LpProxNode; 
     assert(lpNode!=NULL); 
    } 


    printf("\nPseudo String :\n"); 
    lpNode = lpHeadNode; 
    while(lpNode != NULL) 
    { 
     printf("%s", lpNode->lpBuffer); 
     lpNode = lpNode->LpProxNode; 
    } 


    printf("\n\nMemory blocks:\n"); 
    lpNode = lpHeadNode; 
    while(lpNode != NULL) 
    { 
     printf("Block \"%7s\" size = %lu\n", lpNode->lpBuffer, (long unsigned)(strlen(lpNode->lpBuffer) + 1)); 
     lpNode = lpNode->LpProxNode; 
    } 


    printf("\nConcatenated string:\n"); 
    lpNode = lpHeadNode; 
    while(lpNode != NULL) 
    { 
     lpBuffer = (char*)realloc(lpBuffer, (strlen(lpBuffer) + strlen(lpNode->lpBuffer)) + 1); 
     strcat(lpBuffer, lpNode->lpBuffer); 
     lpNode = lpNode->LpProxNode; 
    } 
    printf("%s", lpBuffer); 
    printf("\n\n"); 

    // Deallocate memory 
    lpNode = lpHeadNode; 
    while(lpNode != NULL) 
    { 
     lpHeadNode = lpNode->LpProxNode; 
     free(lpNode->lpBuffer); 
     free(lpNode); 
     lpNode = lpHeadNode; 
    } 
    lpBuffer = (char*)realloc(lpBuffer, 0); 
    lpBuffer = NULL; 
    if((lpNode == NULL) && (lpBuffer == NULL)) 
    { 

     printf("Deallocate memory = %s", (char*)lpNode); 
    } 
    printf("\n\n"); 

    return 0; 
} 
+0

Mi sbaglio, o il ciclo è uscito solo se la linea vuota arriva subito dopo un confine BUFFERSIZE? –

+0

@Alain BECKER Ho migliorato il codice (credo), veramente fuori dal ciclo in questo evento, ma ora esce solo se la riga è vuota (premendo Invio senza digitare nulla), ho provato con TDM-GCC e LCC. – sapitando

+0

Non c'è davvero molto senso nel (a) postare un muro di codice (b) senza spiegazione a (c) una domanda di 6 anni che (d) ha già delle buone risposte. –