How to read from stdin with fgets()?

I've written the following code to read a line from a terminal window, the problem is the code gets stuck in an infinite loop. The line/sentence is of undefined length, therefore I plan to read it in parts into the buffer, then concatenate it to another string which can be extended via realloc accordingly. Please can somebody spot my mistake or suggest a better way of achieving this?

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

5 Answers

here a concatenation solution:

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

You have a wrong idea of what fgets returns. Take a look at this:

It returns null when it finds an EOF character. Try running the program above and pressing CTRL+D (or whatever combination is your EOF character), and the loop will exit succesfully.

How do you want to detect the end of the input? Newline? Dot (you said sentence xD)?

2

Exits the loop if the line is empty(Improving code).

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

Exit when Enter is pressed.

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

Concatenation and dinamic allocation(linked list) to a single string.

/* Autor : Tiago Portela Email : 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;
}
4

Assuming that you only want to read a single line, then use LINE_MAX, which is defined in <limits.h>:

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

If you want to concatenate the input, then replace printf("%s\n", buffer); with strcat(big_buffer, buffer);. Also create and initialize the big buffer at the beginning: char *big_buffer = new char[BIG_BUFFERSIZE]; big_buffer[0] = '\0';. You should also prevent a buffer overrun by verifying the current buffer length plus the new buffer length does not exceed the limit: if ((strlen(big_buffer) + strlen(buffer)) < BIG_BUFFERSIZE). The modified program would look like this:

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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like