LINUX.ORG.RU

Не могу считать строку в C

 


0

0
int main(int argc, char **argv)
{
	char c = getchar();
	printf("%c\n", c);
	char str[128];
	fgets(str, 10, stdin);
	printf("%s\n", str);
	return EXIT_SUCCESS;
}

Собственно вот. После того как ввожу символ, нажимаю ENTER, строка автоматически считывается.
Как решить то?

★★★★

Все правильно: getchar работает с небуферизованным вводом, а fgets — с буферизованным. Или крестик сними, или трусы надень!

Eddy_Em ☆☆☆☆☆ ()

Заюзал scanf, все норм.

FIL ★★★★ ()
Ответ на: комментарий от Eddy_Em

getline дважды, например:

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


int main(int argc, char **argv)
{
	char s[128], *ss = NULL;
	ssize_t l;
	size_t rl;
	printf("%s\n", fgets(s, 2,stdin));
	l = getline(&ss, &rl, stdin);
	if(l > 0) printf("readed %zd symbols: %s\n", l, ss);
	l = getline(&ss, &rl, stdin);
	if(l > 0) printf("readed %zd symbols: %s\n", l, ss);
	return 0;
}
Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от Eddy_Em

getchar работает с небуферизованным вводом, а fgets — с буферизованным.

и там и там ввод буферизован, в данном случае одним и тем-же буфером (stdin) :-)

MKuznetsov ★★★★★ ()
Ответ на: комментарий от MKuznetsov

Да, чушь ляпнул. Просто fgets — хрень какая-то. getline нормально робит. Но лучше таки read. Не люблю буферизацию

Eddy_Em ☆☆☆☆☆ ()
Ответ на: комментарий от MKuznetsov

Вот, последнее время так делаю:

struct termios oldt, newt; // terminal flags
// run on exit:
/*
void quit(int sig){
        //...
        tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // return terminal to previous state
        //...
}
*/
// initial setup:
void setup_con(){
        tcgetattr(STDIN_FILENO, &oldt);
        newt = oldt;
        newt.c_lflag &= ~(ICANON | ECHO);
        if(tcsetattr(STDIN_FILENO, TCSANOW, &newt) < 0){
                tcsetattr(STDIN_FILENO, TCSANOW, &oldt);
                exit(-2); //quit?
        }
}

/**
 * Read character from console without echo
 * @return char readed
 */
int read_console(){
        int rb;
        struct timeval tv;
        int retval;
        fd_set rfds;
        FD_ZERO(&rfds);
        FD_SET(STDIN_FILENO, &rfds);
        tv.tv_sec = 0; tv.tv_usec = 10000;
        retval = select(1, &rfds, NULL, NULL, &tv);
        if(!retval) rb = 0;
        else {
                if(FD_ISSET(STDIN_FILENO, &rfds)) rb = getchar();
                else rb = 0;
        }
        return rb;
}

/**
 * getchar() without echo
 * wait until at least one character pressed
 * @return character readed
 */
int mygetchar(){ 
        int ret;
        do ret = read_console();
        while(ret == 0);
        return ret;
}

Eddy_Em ☆☆☆☆☆ ()
#include <stdio.h>
#include <stdlib.h>

int main() {
    char c = getchar();
    printf("char: %c\n", c);
    fpurge(stdin);
    char str[128];
    fgets(str, sizeof(str), stdin);
    printf("line: %s\n", str);
    return EXIT_SUCCESS;
}
ihanick ()
Ответ на: комментарий от MKuznetsov

А какой ввод(вывод) небуферизован?

anonymous ()

После того как ввожу символ, нажимаю ENTER, строка автоматически считывается

Давай разберём как работает твой код:

char c = getchar(); 

Запросили один символ из потока ввода. Поток ввода буферизован, а значит программа в нём ничего не видит, пока ты не нажмёшь ENTER. Как только ты нажал ENTER у тебя в потоке ввода появляется два символа c\n, getchar берёт первый символ из потока, в потоке остаётся \n. Дальше ты запускаешь считывание строки:

fgets(str, 10, stdin);
fgets читает поток ввода, пока не найдёт символ перевода строки. В потоке ввода у тебя, как ты помнишь, в данный момент находится один символ \n. Угадай, что считает fgets?

Подтверждение:

$ cat test.c
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
	char c = getchar();
	char nl = getchar();
	printf("%c 0x%02X\n", c, nl);
	char str[128];
	fgets(str, 10, stdin);
	printf("%s\n", str);
	return EXIT_SUCCESS;
}
$ gcc test.c && ./a.out
q
q 0x0A
qwer
qwer

$

Решение тоже понятно: если хочешь данные введённые на следующей строке, то тебе нужно считать из потока ввода все символы до первого перевода строки.

kim-roader ★★ ()
Ответ на: комментарий от ihanick
     fpurge(stdin);

man fpurge

These functions are nonstandard and not portable. The function fpurge() was introduced in 4.4BSD and is not available under Linux. The function __fpurge() was introduced in Solaris, and is present in glibc 2.1.95 and later.
Usually it is a mistake to want to discard input buffers.

kim-roader ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.