P. Dave
P. Dave

Reputation: 3

Clear buffer stdin

Hello Stackoverflow community, I have a problem with this code:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define MAX_SIZE 50


int main()
{
    char *s = malloc(sizeof(char)*MAX_SIZE);
    do{
        int r = read(STDIN_FILENO, s, MAX_SIZE);
        if(r==-1) printf("error");
        else{
            write(STDERR_FILENO, s, MAX_SIZE);
        }
        while(getchar()!='\n');
    } while(strcmp(s,"end\n")!=0);
    free(s);
    return 0;
}

The problem is that it produces me a wrong output, stdin doesn't results "clean" at each iteration of the 'do while'. I know that on windows i must use fflush(stdin) but watching on internet i saw that this function is not portable for linux. i use linux, and always watching on internet i saw that many people say the solution is while(getchar()!='\n); instead of fflush(stdin), but the problem is not resolved... Can you explain me why?

Upvotes: 0

Views: 393

Answers (2)

nodakai
nodakai

Reputation: 8033

FYI, an equivalent C++ program

#include <iostream>
#include <string>

int main() {
    for (std::string line; std::getline(std::cin, line); ) {
        if (line == "end")
            break;
    }
}

Upvotes: 0

R Sahu
R Sahu

Reputation: 206747

Problems that I see:

  1. You are passing the wrong argument to write. Instead of

    write(STDERR_FILENO, s, MAX_SIZE); 
    

    it should be

    write(STDERR_FILENO, s, r); // Write the number of characters that were read
                                // not MAX_SIZE
    
  2. The strategy to skip till the end of the line is not well thought out. You have:

    int r = read(STDIN_FILENO, s, MAX_SIZE);
    if(r==-1) printf("error");
    else{
        write(STDERR_FILENO, s, MAX_SIZE);
    }
    while(getchar()!='\n');
    

    First of all, read will not stop reading when it encounters a newline. It will read up to MAX_SIZE characters. It will gobble up as many newlines as it can in the process. What you need to do is use fgets() instead.

    char* cp = fgets(s, MAX_SIZE, stdin);
    if ( cp == NULL )
    {
       // If fgets fails, you probably reached the end of the file.
       break;
    }
    
    fprintf(stderr, "%s", s);
    
  3. The line

    while(strcmp(s,"end\n")!=0);
    

    will lead to undefined behavior if you use read to read the data from a file since read does not automatically add a terminating null character to s. Using fgets avoids that problem.

Also, since you know the size of the array at compile time, you can use:

char s[MAX_SIZE];

instead of using malloc to allocate memory at run time.

Upvotes: 1

Related Questions