Home > Enterprise >  Why doesn't it wait for me to input string after I exit the loop using CTRL D
Why doesn't it wait for me to input string after I exit the loop using CTRL D

Time:01-28

#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:

  1. fgets() returns NULL when the stream is closed. On Linux Ctrl-D will flush the terminal buffer if it's not empty (but fgets() will not return as it remains line buffered), and a 2nd Ctrl-D is required to trigger the EOF state of the stream.

  2. 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)) {
  1. fgets() will not emit EOF 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 or 0xff (whatever char is signed or not but that's still wrong):
        if(char_array[i-1] == EOF)
            break;
  1. 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).

  1. As the input stream is in the EOF state the 2nd fgets() will return NULL. You can clear that state with clearerr(stdin) before calling fgets() to get the 2nd string. If the stream indeed ended, as in, echo "hello world" | ./your_program, the 2nd fgets() 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.

  • Related