F
F
Fortunato282018-09-08 16:54:09
linux
Fortunato28, 2018-09-08 16:54:09

Why does getchar() read all characters from stdin?

A question from the realm of the legendary "explain how the program I wrote works".
Bottom line: you need to read from stdin using epoll until the user sends EOF. And how to send - to complete the work. Those. like cat launched with no arguments.
My code:

int epfd = epoll_create(1);
    if(epfd == -1)
    {
        perror("epoll_create is bad");
        exit(EXIT_FAILURE);
    }

    static struct epoll_event ev;

    ev.events = EPOLLIN;
    ev.data.fd = STDIN_FILENO;
    if(epoll_ctl(epfd, EPOLL_CTL_ADD, STDIN_FILENO, &ev) == -1)
    {
        perror("epoll_ctl connSock is bad");
        exit(EXIT_FAILURE);
    }

    string buffLine = "";
    vector<string> urls;
    char buffer;
    char c;
while(true)
    {
        memset(&ev, 0, sizeof(ev));
        int nfds = epoll_wait(epfd, &ev, 1, 3000);
        if(nfds == -1)
        {
            perror("epoll_wait is bad");
            exit(EXIT_FAILURE);
        }

        if((ev.data.fd == STDIN_FILENO) && (ev.events == EPOLLIN))
        {
            /* Не понимаю, почему всё хорошо работает.
             * Почему getchar() считывает все символы.*/
            c = getchar();
            cout << "C = " << c << endl;
            if(c == EOF) // Пользователь передал EOF
                break;
            if(c == '\n') // Пользователь завершил ввод текущей url
            {
                urls.push_back(buffLine);
                buffLine.clear();
            }
            else
                buffLine += c;
        }

I assumed that getchar() would grab one character, and there you would have to enter another cycle or something. Please explain why getchar() reads all characters correctly and everything works as it should.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
Vladimir Dubrovin, 2018-09-10
@Fortunato28

getchar() performs buffered input, when getchar() is called, read() is called, which reads data into the buffer, then on subsequent calls to getchar(), data is returned from the buffer without a read() call. Together with select/poll/epoll it is more correct to use read() directly.

P
pantoriy, 2018-09-12
@pantoriy

Well, this is the so-called canonical mode of reading from the terminal. After all, you are trying to count from him. Of course, you can reconfigure the terminal and turn on the character-by-character reading mode, but this can lead to a crash of the terminal if you do not do it carefully ... It is generally not recommended to change the terminal modes because all the programs in the session work with the terminal ... You will simply fill up the session. It's a disaster... Carefully it's like a delete operation. Don't forget to restore canonical mode when you don't need to! And so, the first time you run getchar(), it reads to the end of the string, along with the end of the string. Or until the entire buffer is full. The buffer size is set in the system and it is 4 kb 8 or 16 mb or whatever you set there. It is not necessary to change this value. Especially in the direction of reduction. Other programs do not know about it. Usually the string is much shorter. Here is advice given, try read. I say right away, it won’t work! It will be the same. In general, it has nothing to do with how you will read. Because the operating mode of the terminal will not change!!! What am I doing? When I counted the required number of characters, I simply reset the remainder. And this is the most reasonable. I did not find a special function for this. You just need to read until you count the end of the line. There is another function, getline. It prints out the entire line at once. But she needs to slip the address of the pointer to the string previously set to NULL. It will allocate memory for the required amount and fill it with the end of the line. You will immediately get 2 hemorrhoids: 1 at the end, the memory for the line must be freed or you will automatically get a memory leak. The second fuss with the end-of-line character. Well, you yourself understand this is inefficient ... especially if it is in a cycle, and it happens. I found out, the best way is to write it like scanf(" %[^\n]%*c", str). str is a regular stack string with a fixed size. For insurance, you can specify the maximum reading length. But then you can clear the buffer with the same scanf("%*[^\n]%*c") command, though I'm not sure that it won't loop (didn't check...). By the way, there is no such problem in Windows. And if you write in another language too. Fortran, for example.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question