Проверьте, является ли ввод целочисленным типом в C - PullRequest
28 голосов
/ 01 ноября 2010

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

 int num; 
 scanf("%d",&num);
 if(/* num is not integer */) {
  printf("enter integer");
  return;
 }

Я пробовал:

(num*2)/2 == num
num%1==0
if(scanf("%d",&num)!=1)

но ничего из этого не сработало.

Есть идеи?

Ответы [ 13 ]

36 голосов
/ 01 ноября 2010

num всегда будет содержать целое число, потому что это int.Проблема real в вашем коде заключается в том, что вы не проверяете возвращаемое значение scanf.scanf возвращает количество успешно прочитанных элементов, поэтому в этом случае должно возвращаться 1 для допустимых значений.Если нет, то было введено недопустимое целочисленное значение, и переменная num, вероятно, не изменилась (т.е. все еще имеет произвольное значение, потому что вы его не инициализировали).чтобы позволить пользователю ввести целое число, а затем клавишу ввода.К сожалению, это не может быть просто достигнуто с помощью scanf("%d\n"), но вот хитрость, чтобы сделать это:

int num;
char term;
if(scanf("%d%c", &num, &term) != 2 || term != '\n')
    printf("failure\n");
else
    printf("valid integer followed by enter key\n");
22 голосов
/ 01 ноября 2010

Сначала вам нужно прочитать входные данные в виде строки, а затем проанализировать строку, чтобы увидеть, содержит ли она допустимые числовые символы. Если это так, то вы можете преобразовать его в целое число.

char s[MAX_LINE];

valid = FALSE;
fgets(s, sizeof(s), stdin);
len = strlen(s);
while (len > 0 && isspace(s[len - 1]))
    len--;     // strip trailing newline or other white space
if (len > 0)
{
    valid = TRUE;
    for (i = 0; i < len; ++i)
    {
        if (!isdigit(s[i]))
        {
            valid = FALSE;
            break;
        }
    }
}
13 голосов
/ 01 ноября 2010

Существует несколько проблем с использованием scanf со спецификатором преобразования %d для этого:

  1. Если входная строка начинается с допустимого целого числа (например, «12abc»)), тогда «12» будет считано из входного потока и преобразовано и присвоено num, а scanf вернет 1, так что вы укажете успех, когда вы (вероятно) не должны;

  2. Если входная строка не начинается с цифры, то scanf не будет читать любые символов из входного потока, num будетне будет изменено, и возвращаемое значение будет 0;

  3. Вы не указываете, нужно ли обрабатывать недесятичные форматы, но это не будет работать, если вам придется обрабатыватьцелочисленные значения в восьмеричном или шестнадцатеричном формате (0x1a).Спецификатор преобразования %i обрабатывает десятичный, восьмеричный и шестнадцатеричный форматы, но у вас все еще есть первые две проблемы.

Прежде всего, вам нужно прочитать входные данные как строку (предпочтительно используя fgets).Если вам не разрешено использовать atoi, возможно, вам также не разрешено использовать strtol.Так что вам нужно изучить каждый символ в строке.Безопасный способ проверить значения цифр - использовать библиотечную функцию isdigit (есть также функции isodigit и isxdigit для проверки восьмеричных и шестнадцатеричных цифр соответственно), например

while (*input && isdigit(*input))
   input++;    

(если вам даже не разрешено использовать isdigit, isodigit или isxdigit, тогда шлепните своего учителя / профессора за выполнение задания сложнее, чем это на самом деле должно быть).

Если вам нужно иметь возможность обрабатывать восьмеричные или шестнадцатеричные форматы, тогда все становится немного сложнее.Соглашение C для восьмеричных форматов должно иметь ведущую цифру 0, а для шестнадцатеричных форматов - 0x.Таким образом, если первый непробельный символ равен 0, вам необходимо проверить следующий символ, прежде чем вы сможете узнать, какой недесятичный формат использовать.

Основной контур:

  1. Если первый непробельный символ не является '-', '+', '0' или ненулевой десятичной цифрой, то этоне является допустимой целочисленной строкой;
  2. Если первый непробельный символ - '-', то это отрицательное значение, в противном случае мы принимаем положительное значение;
  3. Если первый символ'+', то это положительное значение;
  4. Если первый непробельный и незнаковый символ является ненулевой десятичной цифрой, то ввод будет в десятичном формате, и вы будете использовать isdigit для проверки оставшихся символов;
  5. Если первый непробельный и незнаковый символ равен '0', то ввод выполняется в восьмеричном или шестнадцатеричном формате;
  6. Если первыйнепробельный и незнаковый символ - это «0», а следующий символ - это цифра от «0» до «7», тогда ввод вводится в восьмеричном формате, и вы будете использовать isodigit для проверки оставшихся символов;
  7. Если первым непробельным и незнаковым символом был 0, авторым символом является x или X, тогда ввод осуществляется в шестнадцатеричном формате, и вы будете использовать isxdigit для проверки оставшихся символов;
  8. Если какой-либо из оставшихся символов не удовлетворяет указанной функции проверкивыше, то это не допустимая целочисленная строка.
4 голосов
/ 01 ноября 2010

Сначала спросите себя, как бы вы когда-либо ожидали, что этот код НЕ вернет целое число:

int num; 
scanf("%d",&num);

Вы указали переменную как тип integer, затемscanf, но только для целого числа (%d).

Что еще он может содержать в этой точке?

0 голосов
/ 04 марта 2017
printf("type a number ");
int converted = scanf("%d", &a);
printf("\n");

if( converted == 0) 
{
    printf("enter integer");
    system("PAUSE \n");
    return 0;
}

scanf () возвращает количество совпадающих спецификаторов формата, поэтому возвращает ноль, если введенный текст не может быть интерпретирован как десятичное целое число

0 голосов
/ 08 ноября 2016

Я нашел способ проверить, является ли данный ввод целочисленным или нет, используя функцию atoi ().

Считайте ввод как строку и используйте функцию atoi (), чтобы преобразовать строку вinteger.

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

Есть намного больше функций для преобразования строки в long, double и т. д., проверьте стандартную библиотеку "stdlib.h" для получения дополнительной информации.

Примечание: Работает только для неноль чисел.

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

int main() {
    char *string;
    int number;

    printf("Enter a number :");
    string = scanf("%s", string);

    number = atoi(string);

    if(number != 0)
        printf("The number is %d\n", number);
    else
        printf("Not a number !!!\n");
    return 0;
}
0 голосов
/ 19 июля 2016

Я разработал эту логику с использованием проблем от scanf:

void readValidateInput() {

    char str[10] = { '\0' };

    readStdin: fgets(str, 10, stdin);
    //printf("fgets is returning %s\n", str);

    int numerical = 1;
    int i = 0;

    for (i = 0; i < 10; i++) {
        //printf("Digit at str[%d] is %c\n", i, str[i]);
        //printf("numerical = %d\n", numerical);
        if (isdigit(str[i]) == 0) {
            if (str[i] == '\n')break;
            numerical = 0;
            //printf("numerical changed= %d\n", numerical);
            break;
        }
    }
    if (!numerical) {
        printf("This is not a valid number of tasks, you need to enter at least 1 task\n");
        goto readStdin;
    }
    else if (str[i] == '\n') {
        str[i] = '\0';
        numOfTasks = atoi(str);
        //printf("Captured Number of tasks from stdin is %d\n", numOfTasks);
    }
}
0 голосов
/ 03 марта 2016

Это более удобный для пользователя, я думаю:

#include<stdio.h>

/* This program checks if the entered input is an integer
 * or provides an option for the user to re-enter.
 */

int getint()
{
  int x;
  char c;
  printf("\nEnter an integer (say -1 or 26 or so ): ");
  while( scanf("%d",&x) != 1 )
  {
    c=getchar();

    printf("You have entered ");
    putchar(c);
    printf(" in the input which is not an integer");

    while ( getchar() != '\n' )
     ; //wasting the buffer till the next new line

    printf("\nEnter an integer (say -1 or 26 or so ): ");

  }

return x;
}


int main(void)
{
  int x;
  x=getint();

  printf("Main Function =>\n");
  printf("Integer : %d\n",x);

 return 0;
}
0 голосов
/ 27 января 2016

Этот метод работает для всего (целых и даже двойных), кроме нуля (он называет его недействительным):

Цикл while предназначен только для повторяющихся действий пользователя. В основном он проверяет, является ли целое число х / х = 1. Если это так (как это было бы с числом), его целое / двойное число Если это не так, очевидно, это не так. Ноль не проходит тест, хотя.

#include <stdio.h> 
#include <math.h>

void main () {
    double x;
    int notDouble;
    int true = 1;
    while(true) {
        printf("Input an integer: \n");
        scanf("%lf", &x);
        if (x/x != 1) {
            notDouble = 1;
            fflush(stdin);
        }
        if (notDouble != 1) {
            printf("Input is valid\n");
        }
        else {
            printf("Input is invalid\n");
        }
        notDouble = 0;
    }
}
0 голосов
/ 20 ноября 2014

Попробуйте это ...

#include <stdio.h>

int main (void)
{
    float a;
    int q;

    printf("\nInsert number\t");
    scanf("%f",&a);

    q=(int)a;
    ++q;

    if((q - a) != 1)
        printf("\nThe number is not an integer\n\n");
    else
        printf("\nThe number is an integer\n\n");

    return 0;
}
...