Проверьте, является ли input целочисленным типом В C

загвоздка в том, что я не могу использовать 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 ответов


num всегда содержит целое число, потому что это int. The реальные проблема с вашим кодом в том, что вы не проверяете scanf возвращаемое значение. scanf возвращает количество успешно прочитанных элементов, поэтому в этом случае она должна возвращать 1 для допустимых значений. Если нет, было введено недопустимое целое значение и num переменная, вероятно, не была изменена (т. е. все еще имеет произвольное значение, потому что вы ее не инициализировали).

С вашего комментарий, вы только хотите, чтобы пользователь мог ввести целое число, за которым следует клавиша enter. К сожалению, это не может быть достигнуто просто 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");

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

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;
        }
    }
}

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

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

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

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

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

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. если какой-либо из оставшихся символов не удовлетворяет указанной выше функции проверки, то это недопустимая целочисленная строка.

сначала спросите себя, как бы вы когда-нибудь ожидать, что этот код не возвращает целое число:

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

вы указали переменную как тип integer, затем вы scanf, а только целое (%d).

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


Я просмотрел все входные данные выше, что было очень полезно, и сделал функцию, которая была подходящей для моего собственного приложения. Функция действительно только оценивает, что ввод пользователя не является "0", но это было достаточно хорошо для моей цели. Надеюсь, это поможет!

#include<stdio.h>

int iFunctErrorCheck(int iLowerBound, int iUpperBound){

int iUserInput=0;
while (iUserInput==0){
    scanf("%i", &iUserInput);
    if (iUserInput==0){
        printf("Please enter an integer (%i-%i).\n", iLowerBound, iUpperBound);
        getchar();
    }
    if ((iUserInput!=0) && (iUserInput<iLowerBound || iUserInput>iUpperBound)){
        printf("Please make a valid selection (%i-%i).\n", iLowerBound, iUpperBound);
        iUserInput=0;
    }
}
return iUserInput;
}

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

#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;
}

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

#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;
}

Я разработал эту логику, используя gets и подальше от scanf hassle:

void readValidateInput() {

    char str[10] = { '' };

    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] = '';
        numOfTasks = atoi(str);
        //printf("Captured Number of tasks from stdin is %d\n", numOfTasks);
    }
}

printf("type a number ");
int converted = scanf("%d", &a);
printf("\n");

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

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


У меня была такая же проблема, наконец, понял, что нужно делать:

#include <stdio.h>
#include <conio.h>

int main ()
{
    int x;
    float check;
    reprocess:
    printf ("enter a integer number:");
    scanf ("%f", &check);
    x=check;
    if (x==check)
    printf("\nYour number is %d", x);
    else 
    {
         printf("\nThis is not an integer number, please insert an integer!\n\n");
         goto reprocess;
    }
    _getch();
    return 0;
}

Я искал более простое решение, используя только циклы и операторы if, и это то, что я придумал. Программа также работает с отрицательными целыми числами и корректно отклоняет любые смешанные входы, которые могут содержать как целые числа, так и другие символы.


#include <stdio.h>
#include <stdlib.h> // Used for atoi() function
#include <string.h> // Used for strlen() function

#define TRUE 1
#define FALSE 0

int main(void)
{
    char n[10]; // Limits characters to the equivalent of the 32 bits integers limit (10 digits)
    int intTest;
    printf("Give me an int: ");

    do
    {        
        scanf(" %s", n);

        intTest = TRUE; // Sets the default for the integer test variable to TRUE

        int i = 0, l = strlen(n);
        if (n[0] == '-') // Tests for the negative sign to correctly handle negative integer values
            i++;
        while (i < l)
        {            
            if (n[i] < '0' || n[i] > '9') // Tests the string characters for non-integer values
            {              
                intTest = FALSE; // Changes intTest variable from TRUE to FALSE and breaks the loop early
                break;
            }
            i++;
        }
        if (intTest == TRUE)
            printf("%i\n", atoi(n)); // Converts the string to an integer and prints the integer value
        else
            printf("Retry: "); // Prints "Retry:" if tested FALSE
    }
    while (intTest == FALSE); // Continues to ask the user to input a valid integer value
    return 0;
}

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

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

#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;
    }
}

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

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

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

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

Примечание : это работает только для ненулевых чисел.

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

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

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

    number = atoi(string);

    if(number != 0)
        printf("The number is %d\n", number);
    else
        printf("Not a number !!!\n");
    return 0;
}