Получение ввода с клавиатуры после fgets - PullRequest
0 голосов
/ 11 марта 2011

Я, для моей жизни, не могу быть в мире со строками c и вводом / выводом.

Для моей программы я просто ввожу строку и она обрабатывается в следующем коде: (tmpstring и chуже определены)

Для моего входящего ввода я пишу в терминал: echo "test" |./program

    int main(int argc, char *argv[]) {
    char tmpstring[2048];
    int ch;
    int r;
    int c;

    fgets(tmpstring, sizeof tmpstring, stdin);
    while((ch = fgetc(stdin))!= EOF && ch != '\n');
    tmpstring[strlen(tmpstring)-1]='\0';

    strncpy(opponent, tmpstring+1, strlen(tmpstring+1));

    move();

Внутри move ();

    char buffer[2048]={0};
    int r, c;
    r=0; c=0;
    printf("Your move (row column):");
    if((fgets(buffer, sizeof buffer, stdin)==NULL) || ((sscanf(buffer,"%d %d", &r, &c))!=2)){
            printf("Invalid input. Please insert two numbers separated by whitespace.\n");
            exit(1);
    }
    //continues

Выполнение этого сразу переходит к неверному вводу без запроса дополнительного ввода.Я прочитал все о том, как вы не должны очищать стандартный ввод (и что это невозможно), но я действительно не знаю, что делать.Я явно пытался «сбросить» stdin со второй частью цикла while.Я изменил && после первого условия на ||в то время как цикл.Без изменений.В целом, как я могу запросить больше ввода после уже использованных fgets?

* edit: больше кода и разделение исходного цикла while

1 Ответ

0 голосов
/ 27 августа 2013

Эта проблема обсуждалась в другом месте.
Я скопирую часть своего собственного поста отсюда:

Максимальная длина строки с использованием scanf -> ANSI C

  • Определяется функция my_scanf() с переменным числом параметров, вызывая библиотеку stdarg.h, объединенную в комбинацию fgets() и vsscanf().
  • Эта функция предназначена для правильной обработки комбинаций fgets() и sscanf() (на самом деле, мы должны использовать vsscanf() для правильной обработки списка аргументов).
  • Входные данные считываются до верхнего предела символов.если вход имеет больше, чем этот предел, он усекается.\ N обрабатываются правильноФункция возвращает то же значение, что и scanf().Таким образом, вы можете использовать my_scanf() вместо этого.

Здесь у вас есть код:

#include <stdio.h>
#include <stdarg.h>

int my_scanf(const char* fmt, const unsigned int maxbuff, ...) {
    va_list ptr;
    int ret;

    if (maxbuff <= 0)
       return EOF; /* Bad size for buffer[] */

    char buffer[maxbuff+1];
    buffer[maxbuff-1] = '\0';  /* Quick buffer cleaning... */

    if (fgets(buffer, maxbuff+1, stdin) == NULL)
       return EOF; /* Error detected */
    else {
        if ((buffer[maxbuff-1] != '\n') && (buffer[maxbuff-1] != '\0'))
            /* Condition logically equivalent to:
                   fgets() has not reached an '\n'
            */
            while (getchar() != '\n')
               ; /* "Flushing" stdin... */

        va_start(ptr, maxbuff);
        ret = vsscanf(buffer, fmt, ptr);
        va_end(ptr);
        return ret;
    }    
}

#define MAXBUFF 20
int main(void) {
   int x; 
   float z;
   int scanf_ret = my_scanf("%d %g", MAXBUFF, &x, &z);
   printf("\nTest:\n x == %d\n z == %g\n scanfret == %d", x, z, scanf_ret);
   getchar();   
   return 0;   
}

Функция my_scanf () имеет прототип

int my_scanf(const char* fmt, const int maxbuff, ...);
  • Она принимает строку формата fmt, который ведет себя так же, как и любой другой scanf().
  • 2-й параметр - это максимальное количество символов , которое будет эффективно приниматься со стандартного входа (клавиатуры).
  • Возвращаемым значением является int , что равно EOF, если maxbuff не имеет смысла, или же произошла ошибка ввода.Если возвращается неотрицательное значение, оно совпадает с тем, которое будет возвращено стандартными функциями sscanf() или vsscanf().

    1. Внутри функции maxbuff увеличивается на 1, потому что fgets() оставляет место для дополнительного символа '\ 0'.
    2. Неположительные значения maxbuff немедленно отбрасываются.
    3. fgets() будет читать строку с stdin (клавиатура), в которой должно быть не более maxbuff символов, включая '\ n'.
    4. Если пользователь ввел очень длинную строку, она будет усечена, и необходим какой-то механизм «сброса», чтобы отбросить все символы до следующего «\ n» (ENTER ).Если нет, то при следующем чтении на клавиатуре могут присутствовать более старые символы, что вовсе не желательно.
      • Условие для "очистки" состоит в том, что fgets() не достигло '\ n' после чтения stdin.
      • Это верно, если и только если buffer[maxbuff - 1] не равно ни \ 0, ни \ n.( Проверьте это! )
    5. Наконец, подходящая (и стандартная) комбинация stdarg.h макросов и функции vsscanf()используется для обработки списка переменных параметров.
...