2017-02-18 2 views
0

Я создаю программу, запрашивающую пользователя ввести значение char, но если они вводят более одного символа, он переместится на следующую функцию и сломает программу. Я добавил второй метод, который запускается при вводе нескольких входов.Как ограничить ввод моего пользователя

+0

Сделать буфер символов больше; вам не нужно использовать все это. Память дешевая. Массив, скажем, 100 символов, ничто. – Carcigenicate

+0

Я пробовал это, но затем возвращает бесконечный цикл проверки проверки из другой функции. – Luke

+0

зачем использовать строку, когда вы хотите получить символ? – 4386427

ответ

1

Ваша проблема не в том, чтобы ограничить количество символов, записанных на cInput; спецификатор формата %1s делает это уже. Ваша проблема заключается в том, чтобы оставить необработанные символы во входном буфере. Вам необходимо удалить все символы из буфера, если последующий ввод не будет обрабатывать их. Например, если вы оставите буквенный символ в буфере, но позже прочитаете с помощью %d, функция немедленно вернется (потому что неявно используется также строка новой строки), но символ останется буферизированным, поскольку он не является десятичным. Это будет продолжаться бесконечно, если вы никогда не очистите буфер.

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

scanf("%c", &cInput) ; 
while(cInout != '\n' && getchar() != '\n') { } // flush buffered line 

Если вы хотите, чтобы убедиться, что пользователь вводит только один символ, то вы могли бы изменить выше, таким образом:

scanf("%c", &cInput) ; // Get a single character 

if(cInput != '\n' &&  // If the input is not "empty", 
    getchar() != '\n') // but the first character entered was not 
          // immediately followed by a newline... 
{ 
    // Flush to the end of the entered line 
    while(getchar() != '\n') { } 

    // Invalidate the input to force retry 
    cInput = 0 ; 
} 

по крайней мере один символ будет буферном - в новой строки по крайней мере. Действительный ответ будет иметь два символа один в cInput и newline. Приведенное выше условие if(...) считывает второй символ, если он есть (с использованием оценки короткого замыкания cInput) и проверяет, что это конец ввода (новая строка). Если это не так, он читает все буферизованные символы, то аннулирует cInput (в случае, если говорить "No-way\n" были введены, например, так, что cinput содержал 'N'

Для ввода чисел, вы просто читать символы до новой строки не найден:.

scanf("%d", &nValue); 
while(getchar() != '\n') { } // flush buffered line 

Если конечные нечисловые символы должны оказывать весь входной недействителен, вы должны проверить, что следующий символ новой строки.

int converted = scanf("%d", &nValue); 
if(converted == 0 || getchar() != '\n') 
{ 
    valid_input = false ; 
    while(getchar() != '\n') { } // flush buffered line 
} 

Обратите внимание, что существуют другие возможные решения. Это мое предпочтительное решение.

При нанесении на ваши функции (с другими упрощениями):

int intAskUser(void) 
{ 
    char cInput = 0 ; 

    while(cInput != 'N' && cInput != 'Y') 
    { 
     printf("Do you want to enter a value? Y or N\n"); 
     scanf("%c", &cInput) ; 
     if(cInput != '\n' && getchar() != '\n') 
     { 
      while(getchar() != '\n') { } // flush buffered line 
      cInput = 0 ; 
     } 
     else 
     { 
      cInput = toupper(cInput) ; 
     } 
    } 

    // Return answer code 0 to 1 
    return (cInput == 'N') ? 0 : 1 ; 
} 

int getValue(int nLower, int nUpper) 
{ 
    assert(nLower < nUpper) ; // precondition check 

    int nValue = 0 ; 
    bool valid_input = false ; 

    while(!valid_input) 
    { 
     printf("Enter a value between %d and %d: ", nLower, nUpper) ; 
     int converted = scanf("%d", &nValue); 
     if(converted == 0 || getchar() != '\n') 
     { 
      valid_input = false ; 
      while(getchar() != '\n') { } // flush buffered line 
     } 

     valid_input = nValue >= nLower && 
         nValue <= nUpper ; 

     if(!valid_input) 
     { 
      printf("Please try again. "); 
     } 
    } 

    printf("Value: %d", nValue); 
    return nValue; 
} 

Обратите внимание, что toupper() требует ctype.h быть включен, и тип bool требует stdbool.h.

0

Если я правильно понимаю ваш вопрос, вы хотите, чтобы функция возвращала, если пользовательский ввод любого из

  • y с последующим переводом строки
  • Y с последующим переводом строки
  • n с последующим переводом строки
  • N с последующим переводом на новую строку

Во всех остальных случаях вы хотите остаться в функции и получить новый пользовательский ввод (например, nYnhhh, за которым следует новая линия: не возвращение).

Насколько я знаю, нет стандартной функции, которая может достичь этого, поэтому вам нужно написать свой собственный код.

При выполнении, что есть две вещи, чтобы помнить:

  1. Вы должны прочитать по крайней мере, 2 символов для того, чтобы проверить «слишком долго» входных строк.
  2. После неудачных входов вам необходимо очистить входной буфер перед чтением нового ввода. Неудачный ввод - это тот, который не имеет \n как последний символ.

В заключение я рекомендую использовать fgets() вместо scanf(), поскольку он намного проще в использовании. Не используйте gets(), хотя - он опасно уязвим для переполнения буфера.

Ваш код может выглядеть следующим образом:

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

int AskUser(void) 
{ 
    char input[3] = {'\0'}; // Make room for a string of 2 chars + terminating null 
    int c; 
    int len; 

    printf("Do you want to enter a value? Y or N\n"); 
    do 
    { 
     if (!fgets(input, 3, stdin)) 
     { 
      printf("Input error"); 
      exit(1); 
     } 

     len = strlen(input); 
     if (len) 
     { 
      if (input[len-1] != '\n') // Check whether last char is a newline 
      { 
       // It isn't so empty the input buffer 
       while ((c = getchar()) != '\n' && c != EOF) { } 
      } 
     } 

     if (len == 2) // Check for exactly 2 chars in input 
     { 
      if(toupper(input[0]) == 'Y' && input[1] == '\n') 
      { 
       return 1; 
      } 

      if(toupper(input[0]) == 'N' && input[1] == '\n') 
      { 
       return 0; 
      } 
     } 

     printf("Please enter a valid input, Y or N: \n");   

    } while(1); 
} 

int main(void) { 
    printf("Answer is %d\n", AskUser()); 
    return 0; 
}