web-dev-qa-db-fra.com

Vérifier si l'entrée est de type entier en C

Le problème, c'est que je ne peux utiliser ni atoi ni aucune autre fonction de ce type (je suis presque sûr que nous sommes supposés nous appuyer sur des opérations mathématiques).

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

J'ai essayé:

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

mais aucun d'entre eux n'a fonctionné.

Des idées?

24
Gal

num contiendra toujours un entier car c'est une int. Le problème de real avec votre code est que vous ne vérifiez pas la valeur de retour scanf. scanf renvoie le nombre d'éléments lus avec succès. Dans ce cas, il doit donc renvoyer 1 pour les valeurs valides. Sinon, une valeur entière non valide a été entrée et la variable num n'a probablement pas été modifiée (c'est-à-dire qu'elle a toujours une valeur arbitraire car vous ne l'avez pas initialisée).

À partir de votre commentaire, vous souhaitez uniquement autoriser l'utilisateur à entrer un entier suivi de la touche Entrée. Malheureusement, ceci ne peut pas être simplement réalisé par scanf("%d\n"), mais voici une astuce pour le faire:

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");
33
AndiDog

Vous devez d'abord lire votre entrée sous forme de chaîne, puis analyser la chaîne pour voir si elle contient des caractères numériques valides. Si c'est le cas, vous pouvez le convertir en entier.

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;
        }
    }
}
22
Paul R

Utiliser scanf avec le spécificateur de conversion %d pose plusieurs problèmes:

  1. Si la chaîne d'entrée commence par un entier valide (tel que "12abc"), les "12" seront lus dans le flux d'entrée, convertis et attribués à num, et scanf renverra 1; (probablement) ne devrait pas;

  2. Si la chaîne d'entrée ne commence pas par un chiffre, scanf ne lira pas les caractères du flux d'entrée, num ne sera pas modifié et la valeur de retour sera 0;

  3. Vous ne spécifiez pas si vous devez gérer des formats non décimaux, mais cela ne fonctionnera pas si vous devez gérer des valeurs entières aux formats octal ou hexadécimal (0x1a). Le spécificateur de conversion %i gère les formats décimal, octal et hexadécimal, mais vous avez toujours les deux premiers problèmes. 

Tout d’abord, vous devez lire l’entrée sous forme de chaîne (utilisez de préférence fgets). Si vous n'êtes pas autorisé à utiliser atoi, vous n'êtes probablement pas non plus autorisé à utiliser strtol. Vous devrez donc examiner chaque caractère de la chaîne. Le moyen sûr de vérifier les valeurs numériques consiste à utiliser la fonction de bibliothèque isdigit (il existe également les fonctions isodigit et isxdigit pour la vérification des chiffres octaux et hexadécimaux, respectivement), telles que

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

(Si vous n'êtes même pas autorisé à utiliser isdigit, isodigit ou isxdigit, claquez alors votre enseignant/professeur pour avoir rendu la tâche plus difficile que nécessaire.) 

Si vous devez être capable de gérer les formats octal ou hexadécimal, alors cela devient un peu plus compliqué. La convention C stipule que les formats octaux doivent avoir un chiffre 0 en tête et que les formats hexagonaux ont un code 0x en tête. Ainsi, si le premier caractère non-blanc est un 0, vous devez vérifier le caractère suivant avant de savoir quel format non décimal utiliser. 

Le contour de base est 

  1. Si le premier caractère non-blanc n'est pas un '-', '+', '0' ou un chiffre décimal différent de zéro, il ne s'agit pas d'une chaîne entière valide;
  2. Si le premier caractère non-blanc est '-', il s'agit d'une valeur négative, sinon nous supposons une valeur positive;
  3. Si le premier caractère est '+', il s'agit d'une valeur positive.
  4. Si le premier caractère sans espace ni signe est un chiffre décimal différent de zéro, l'entrée est au format décimal et vous utiliserez isdigit pour vérifier les caractères restants;
  5. Si le premier caractère sans espace ni signe est un "0", l'entrée est au format octal ou hexadécimal;
  6. Si le premier caractère sans espace ni signe est un "0" et que le caractère suivant est un chiffre compris entre "0" et "7", l'entrée est au format octal et vous utiliserez isodigit pour vérifier les caractères restants. ;
  7. Si le premier caractère sans espace ni signe est un 0 et que le second caractère est x ou X, l'entrée est au format hexadécimal et vous utiliserez isxdigit pour vérifier les caractères restants;
  8. Si l'un des caractères restants ne remplit pas la fonction de vérification spécifiée ci-dessus, il ne s'agit pas d'une chaîne entière valide. 
13
John Bode

Tout d'abord, demandez-vous comment vous attendez jamais que ce code renvoie ET NON un nombre entier:

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

Vous avez spécifié la variable en tant que type entier, puis vous avez scanf, mais seulement pour un entier (%d).

Que pourrait-il éventuellement contenir à ce stade?

4
abelenky

J'ai examiné la contribution de chacun ci-dessus, ce qui était très utile, et j'ai créé une fonction adaptée à ma propre application. La fonction évalue simplement que l’entrée de l’utilisateur n’est pas un "0", mais c’était suffisant pour mon but. J'espère que cela t'aides!

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

C’est une solution plus conviviale, je suppose:

#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
sjsam

Essaye ça...

#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;
}
0
OscaRoCa
printf("type a number ");
int converted = scanf("%d", &a);
printf("\n");

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

scanf () renvoie le nombre de spécificateurs de format qui correspondent, ainsi renvoie zéro si le texte saisi ne peut pas être interprété comme un entier décimal.

0
Eduardo

J'ai développé cette logique en utilisant et en évitant les problèmes de 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
Shaimaa Yehia