2010-10-12 26 views
21

He escrito el siguiente código para leer una línea desde una ventana de terminal, el problema es que el código se bloquea en un ciclo infinito. La línea/frase es de longitud indefinida, por lo tanto, planeo leerla en partes en el búfer, luego concatenarla a otra cadena que se puede extender a través de realloc en consecuencia. ¿Alguien puede detectar mi error o sugerir una mejor manera de lograr esto?¿Cómo leer desde 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

Parece bastante bien, ¿cuándo quieres que termine el ciclo? Tal como está ahora, puede finalizar presionando ctrl + d en * nix o ctrl + z en Windows. – nos

+1

No veo nada obviamente mal con el código, cuando dices "atrapado en un ciclo infinito", ¿a qué te refieres exactamente? –

+0

Mi bola de cristal me dice que Paul R ha solucionado el problema. La solución es poner el 'printf' dentro del ciclo. – pmg

Respuesta

14

aquí una solución concatenación:

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

Tiene una idea equivocada de lo que vuelve a generar. Eche un vistazo a esto: http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

Devuelve nulo cuando encuentra un carácter EOF. Intente ejecutar el programa anterior y presione CTRL + D (o la combinación que sea su carácter EOF), y el ciclo se cerrará satisfactoriamente.

¿Cómo se quiere detectar el final de la entrada? ¿Nueva línea? Dot (dijiste la oración xD)?

+0

el final de la entrada debe ser una nueva línea – robdavies35

+0

Escanee su búfer para líneas nuevas, luego :) – slezica

1

Suponiendo que sólo desea leer una sola línea, a continuación, utilizar LINE_MAX, que se define en <limits.h>:

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

LINE_MAX NO es C89 o C99, su único compilador específico – user411313

+1

Es curioso que muestre un código usando 'LINE_MAX' sin incluir' limits.h' –

0

Si desea concatenar la entrada, luego reemplace printf("%s\n", buffer); con strcat(big_buffer, buffer);. También crea e inicializa el búfer grande al principio: char *big_buffer = new char[BIG_BUFFERSIZE];big_buffer[0] = '\0';. También debe evitar un desbordamiento del búfer verificando que la longitud actual del búfer más la nueva longitud del búfer no exceda el límite: if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE). El programa modificado se vería así:

#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' es C++ pero la pregunta es sobre C –

1

Sale del bucle si la línea está vacía (Mejorando el código).

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

salida cuando se pulsa ENTER.

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

Concatenación y asignación dinámica (lista vinculada) a una sola cadena.

/* 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

¿Estoy equivocado, o el ciclo solo se sale si la línea vacía aparece justo después de un límite de BUFFERSIZE? –

+0

@Alain BECKER He mejorado el código (supongo), realmente fuera del ciclo en este caso, pero ahora se va solo si la línea está vacía (presionando Enter sin escribir nada), probé con TDM-GCC y LCC. – sapitando

+0

No tiene mucho sentido (a) publicar un muro de código (b) sin explicación para (c) una pregunta de 6 años que (d) ya tiene buenas respuestas. –

Cuestiones relacionadas