#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
char c, char_array[100];
int i = 0;
printf("Enter characters (press CTRL D to end):\n");
while(fgets(char_array i,sizeof(char_array)-i,stdin)) {
i = i strlen(char_array i);
if(char_array[i-1] == EOF)
break;
}
char_array[i-1] = '\0';
strtok(char_array,"\n");
printf("\nEnter a string:\n");
char string[100];
fgets(string,sizeof(string),stdin);
printf("\nCharacter Array: %s\n", char_array);
printf("String: %s\n", string);
return 0;
}
This is the code and I have tried many different variations(simpler) but it always has the same problem... I enter the characters, press CTRL D and it ends without waiting for me to input a string. please help
I tried everything I could but I just cant make it work and my friends cant too... I have and exam and I need this to be done in 3 days max so I need all the help I can get.
CodePudding user response:
fgets()
returnsNULL
when the stream is closed. On Linux Ctrl-D will flush the terminal buffer if it's not empty (butfgets()
will not return as it remains line buffered), and a 2nd Ctrl-D is required to trigger the EOF state of the stream.You also want to terminate the loop if the array is full otherwise it's an infinite loop:
#define ARRAY_LEN 100
//...
while(i < ARRAY_LEN - 1 && fgets(char_array i, ARRAY_LEN - i,stdin)) {
fgets()
will not emitEOF
as part of the string being read, so this is simply incorrect, and as stdin is line buffered the last character is either\n
or whatever if the last character was read if the buffer is full which could be-1
or0xff
(whatever char is signed or not but that's still wrong):
if(char_array[i-1] == EOF)
break;
- The next line:
char_array[i-1] = '\0';
strips the last character which is either \n
or whatever we read last if the array is full (i.e. data loss).
- As the input stream is in the
EOF
state the 2ndfgets()
will return NULL. You can clear that state withclearerr(stdin)
before callingfgets()
to get the 2nd string. If the stream indeed ended, as in,echo "hello world" | ./your_program
, the 2ndfgets()
with return NULL again of course.
I suggest you use a blank line to signify end of input:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARRAY_LEN 100
int main() {
printf("Enter characters (empty line to end):\n");
char char_array[ARRAY_LEN];
for(size_t i = 0; i < ARRAY_LEN - 1; i = strlen(char_array)) {
if(!fgets(char_array i, ARRAY_LEN - i, stdin)) {
printf("fgets() failed\n");
return 1;
}
if(char_array[i] == '\n') {
char_array[i] = '\0';
break;
}
}
strtok(char_array, "\n");
printf("Enter a string:\n");
char string[ARRAY_LEN];
char *rv = fgets(string,sizeof(string),stdin);
printf("Character Array: %s\n", char_array);
printf("String: %s\n", string);
}
and example session:
Enter characters (empty line to end):
hello
world
Enter a string:
friend
Character Array: hello
String: friend
CodePudding user response:
With stdio streams, error/eof is sticky -- that is, once an error or eof condition has occurred, further operations on the FILE *
will continue to return EOF or NULL (depending on the function), rather than trying to read or write anything further.
To reset the eof state on the FILE *
, you need to call clearerr(stdin)
. Once you do that, you can read additional input from the terminal.