funciona - ¿Cómo leer desde stdin con fgets()?
leer caracteres en c (5)
Aquí una solución de concatenación:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 10
int main() {
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);
return 0;
}
He escrito el siguiente código para leer una línea desde una ventana de terminal, el problema es que el código se atasca en un bucle infinito. La línea / oración es de longitud indefinida, por lo tanto planeo leerla en partes en el búfer, luego concatenarla a otra cadena que puede extenderse a través de realloc
consecuencia. ¿Alguien puede detectar mi error o sugerir una mejor manera de lograrlo?
#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;
}
Sale del bucle si la línea está vacía (código de mejora).
#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;
}
Salir cuando se presiona 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 enlazada) 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;
}
Si desea concatenar la entrada, reemplace printf("%s/n", buffer);
con strcat(big_buffer, buffer);
. También cree e inicialice 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 al verificar que la longitud del búfer actual 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;
}
Suponiendo que solo desea leer una sola línea, use LINE_MAX
, que se define en <limits.h>
:
#include <stdio.h>
...
char line[LINE_MAX];
...
if (fgets(line, LINE_MAX, stdin) != NULL) {
...
}
...
Tienes una idea equivocada de lo que devuelve fgets. 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 cualquier combinación que sea su carácter EOF), y el bucle saldrá exitosamente.
¿Cómo quieres detectar el final de la entrada? ¿Nueva línea? ¿Punto (dijiste la oración xD)?