Partage
  • Partager sur Facebook
  • Partager sur Twitter

Saisir une adresse IP en C + controle de la saisie

Sujet résolu
14 juillet 2013 à 12:48:44

Bonjour à tous, 

Je suis débutante en langage C et je rencontre un problème. 

Je souhaiterai que l'utilisateur entre une adresse IP mais je voudrais en contrôler la saisie. 

Pour cela j'ai pensé à mettre la saisie dans une chaîne de caractère, puis contrôler le nombre de points entre les chiffres mais il faut aussi regarder si les chiffres sont bien entre 0 et 9 pour éviter 192.bddv.63.21 par exemple.. C'est là où se situe mon problème, je ne sais pas faire.. Car il y a les caractères point qui m’embêtent.

J'ai vu que je pouvais utiliser la fonction strtok pour enlever les points mais si je fais ça je ne pourrais plus contrôler chaque chiffre.. 

J'espère avoir été claire, désolé si ce n'est pas le cas.

Merci d'avance pour votre réponse!

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:07:22

Salut =)

Si tu as :

char ip[] = "192.923.63.21";

Tu peux donc vérifier les points en contrôlant que ip[3], ip[7] et ip[10] soient bien égaux au caractère '.'

Pour les chiffres, tu peux utiliser la fonction atoi (ASCII to Integer) qui te donne la valeur numérique d'un caractère ASCII ( '6' te donnera 6). Tu n'as donc plus qu'a utiliser cette fonction sur ip[0], ip[1], ... pour effectuer tes vérifications.

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:13:35

Ajoute à ton programme:

........

int     i;

i = 0;
while (str[i])
{
   if (str[i] == '.')
        printf("J'ai bien trouvé un point, caractère n°%d de l'adresse IP.", i); 
    i = i + 1;




......

En mettant ton "int i" avec tes déclarations, et puis il peut s'appeler autrement.  

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:23:06

Merci pour vos réponses rapides ! 

char Adresse[16];
	int erreur;
	int i;
	int compt;

	printf("Entrez une adresse \n");
gets(Adresse);
	printf("Vous avez saisie  %s \n  " ,Adresse );
erreur=0;
compt=0;
	for ( i = 0 ; erreur == 0 && i < strlen(Adresse) -1  ; i++ )
{
    if (Adresse[i]=='.')
    {
        Adresse[i]==' ';
        compt=compt+1;
        i++;
    }

    if ( Adresse[i] < '0' || Adresse[i] > '9' )
    {
        erreur = 1;
    }

}

if(erreur==1 || compt!=3)
{
    printf("Erreur");
}

    return 0;
}


J'ai fait ça.. 

Cela fonctionne dans la plupart des cas mais si je rentre 127.0.0.0.0 le programme ne me dis rien.. 

Je ne comprends pas parce que compt sera égal à 4 n'est ce pas? 

Pouvez-vous m'éclairer? 

Merci encore :)

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:33:08

Ton erreur dans ton ton for :

i < strlen(Adresse) -1

strlen renvoie le nombre de caractère jusqu'au '\0' final mais sans le compter. Donc là tu demande à ta boucle de t'arrêter 2 caractères avant la fin (à cause également de l'inférieur strict) ce qui évite le .0 final qui devrait faire une erreur.

-
Edité par Renault 14 juillet 2013 à 15:33:36

  • Partager sur Facebook
  • Partager sur Twitter
Je soutiens activement le projet Fedora.
14 juillet 2013 à 15:33:21

Pour vérifier les valeurs de tes variables, affiche les ;)

-
Edité par DeTilt 14 juillet 2013 à 15:34:12

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:41:02

En effet, je viens de vérifier la valeur de compt en l'affichant et en modifiant ma condition :) 

Merci encore :) 

Une dernière petite question.. 

Pour vérifier que mes valeurs sont bien entre 0 et 255 il faut que j'utilise strtok pour enlever les points puis atoi() pour convertir et vérifier c'est bien ça? 

En tout cas merci pour votre aide très efficace! 

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:48:10

Il y a plein de méthodes. Je ne suis pas fan de l'idée de modifier la chaine de caractères personnellement. Je pense que je créerais une seconde chaine de caractères plus courte (de 1 à 3 chiffres), que je remplirai avant le premier point, comparerait à 0 et 255, petit free, je passe au 2ème petit groupe de chiffres...
A toi de voir, si tu préfères strtok.  
Le mieux quand tu codes c'est pas de te poser de questions, c'est d'essayer, de voir quels sont tes problèmes, et d'ajuster. Si tu demandes avant d'essayer une méthode à chaque fois tu risques d'apprendre beaucoup plus lentement. Jette toi à l'eau, fais tes algos tente ta logique ;)
  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 15:53:23

D'accord :) 

Merci de tes conseils ! C'est très sympa de ta part !

Je vous tiendrai au courant :) 

Passez une bonne journée 

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 16:11:47

Après toute votre aide voici ce que ça donne.. :) 

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

int main()
{
	char Adresse[16];
	int erreur;
	int i;
	int compt;
	char *str = NULL;
	int iValeurAdresse;
	int iAdresseIp[4];

	printf("Entrez une adresse \n");
gets(Adresse);
	printf("Vous avez saisie  %s \n  " ,Adresse );
erreur=0;
compt=0;
	for ( i = 0 ; erreur == 0 && i < strlen(Adresse)  ; i++ )
{
    if (Adresse[i]=='.')
    {
        Adresse[i]==' ';
        compt=compt+1;
        //printf("%d", compt);
        i++;
    }

    if ( Adresse[i] < '0' || Adresse[i] > '9' )
    {
        erreur = 1;
    }

}

if(erreur==1 || compt!=3)
{
    printf("Erreur");
}
else
{
    str = strtok (Adresse,".");
    i=0;
    	while (str != NULL)
	{
		iValeurAdresse = atoi(str);
		if(iValeurAdresse > 255 || iValeurAdresse < 0)
		{
			printf("Erreur \n");
			str = NULL;
			
		}
		else
		{
			iAdresseIp[i] = iValeurAdresse;
		}
		i++;
		str = strtok(NULL, ".");
	}
}

for(i=0;i<4;i++)
{
    if(i==3)
    {
        printf("%d", iAdresseIp[i]);
    }
    else
    printf("%d.", iAdresseIp[i]);
}

    return 0;
}

Comme vous pouvez le voir je bidouille un peu pour l'affichage.. Si vous avez un conseil pour que ce soit plus "propre" je suis preneuse :) 

Merci

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 18:28:28

Bonjour,

Pourquoi pas un :

unsigned ip1, ip2, ip3, ip4;

if( scanf("%u.%u.%u.%u" , &ip1 , &ip2, &ip3, &ip4) != 4 ||
    ip1>255 || ip2>255 || ip3>255 || ip4>255 )
    printf("Saisie erronée\n");

Ou à la limite si tu veux permettre à l'utilisateur de saisir ca avec un autre séparateur que le '.', alors ceci peut faire l'affaire :

unsigned ip1, ip2, ip3, ip4;

if( scanf("%u%*c%u%*c%u%*c%u" , &ip1 , &ip2, &ip3, &ip4) != 4 ||
    ip1>255 || ip2>255 || ip3>255 || ip4>255 )
    printf("Saisie erronee\n");




-
Edité par uknow 14 juillet 2013 à 19:37:09

  • Partager sur Facebook
  • Partager sur Twitter
14 juillet 2013 à 22:32:52

C'est vrai que scanf fait aussi un très joli boulot pour ce genre de choses.
  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 8:40:16

Le scanf remplacerait mes deux boucles à ce que je vois..

Mais est-ce qu'il gère si l'utilisateur saisit un caractère?

En tout cas merci, je vais essayer ça :)

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 8:42:24

Et pour l'affichage final, vous pensez que cela est assez propre?

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 8:48:52

Ineys677 a écrit:

Et pour l'affichage final, vous pensez que cela est assez propre?


Certes c'est une mauvaise idée qu'est de dérouler une boucle, mais dans ton cas tu as 4 objets dans ton tableau, AMHA tu peux dérouler la boucle :

printf( "%d.%d.%d.%d", iAdresseIp[0],
                       iAdresseIp[1],
                       iAdresseIp[2],
                       iAdresseIp[3] );



  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 9:03:08

Mais oui ! Tu as tout à fait  raison !

J'aurai dû y penser..

Ton idée est tellement mieux! Merci encore

Bonne journée ! :)

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 18:15:56

uknow a écrit:

Bonjour,

Pourquoi pas un :

unsigned ip1, ip2, ip3, ip4;

if( scanf("%u.%u.%u.%u" , &ip1 , &ip2, &ip3, &ip4) != 4 ||
    ip1>255 || ip2>255 || ip3>255 || ip4>255 )
    printf("Saisie erronée\n");

Ou à la limite si tu veux permettre à l'utilisateur de saisir ca avec un autre séparateur que le '.', alors ceci peut faire l'affaire :

unsigned ip1, ip2, ip3, ip4;

if( scanf("%u%*c%u%*c%u%*c%u" , &ip1 , &ip2, &ip3, &ip4) != 4 ||
    ip1>255 || ip2>255 || ip3>255 || ip4>255 )
    printf("Saisie erronee\n");



Suite à vos differentes reponses j'ai donc fait ce bout de code : 

printf("Saisir svp : \n");
    scanf("%d" , &iAdresseIp[0]);
    scanf("%d" , &iAdresseIp[1]);
    scanf("%d" , &iAdresseIp[2]);
    scanf("%d" , &iAdresseIp[3]);

if( scanf("%d.%d.%d.%d" , &iAdresseIp[0] , &iAdresseIp[1], &iAdresseIp[2], &iAdresseIp[3]) != 4 ||
    iAdresseIp[0]>255 || iAdresseIp[1]>255 || iAdresseIp[2]>255 || iAdresseIp[3]>255 )
    printf("Saisie erronée\n");

Néanmoins le programme attend 5 valeurs ce qui me renvoie au if à chaque fois.. 

Je n'arrive pas à y voir très clair car je lui demande clairement de rentrer 4 valeurs et non 5..

C'est certainement une erreur de ma part. Pouvez-vous me mettre sur la voie svp ?

Merci 

-
Edité par Ineys677 15 juillet 2013 à 18:19:58

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 18:36:50

J'ai tapé ça vite fait, si tout va bien ça devrait compiler et fonctionner.

int IsValidIp(char* szIP)
{
	int isValid;
	int i;
	unsigned char byte;
	int iIpLen;
	char dotCount;
	
	
	isValid = 1;
	iIpLen = strlen(szIP);
	dotCount = 0;

	// Si on nous donne une chaine de caractère vide ou bien que la chaine dépasse les 15 caractères ce n'est pas une bonne IP
	if(iIpLen == 0 || iIpLen > 15)
	{
		isValid = 0;
	}
	else
	{
		/* On récupère le premier octet */
		byte = (unsigned char)atoi(szIP);
		/* S'il est plus grand que 255 alors ce n'est pas une IP valide */
		if(byte > 255)
		{
			isValid = 0;
		}
		
		/* on parcours la chaine */
		for(i = 0; i < iIpLen && isValid == 1; i++)
		{
			/* on compte le nb de point */
			if(szIP[i] == '.') 
			{
				dotCount ++;
				/* puis on check si l'octet que l'on récupère est valide */
				byte = (unsigned char)atoi(&szIP[i+1]);
				if(byte > 255)
				{
					isValid = 0;
				}
			}
		}
		/* s'il n'y a pas trois points dans l'ip alors ce n'est pas une ip valide */
		if(dotCount != 3)
		{
			isValid = 0;
		}
		
	}
	

	return isValid;
}
  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 19:31:58

Merci Woosterfield c'est très gentil! :) 

Mais dans ton code, on ne prend pas en compte si l'utilisateur saisi un lettre, si ?

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 20:29:39

C'est pas faux, je corrige ça ;)

int IsValidIp(char* szIP)
{
    int isValid;
    int i;
    unsigned char byte;
    int iIpLen;
    char dotCount;
     
     
    isValid = 1;
    iIpLen = strlen(szIP);
    dotCount = 0;
 
    // Si on nous donne une chaine de caractère vide ou bien que la chaine dépasse les 15 caractères ce n'est pas une bonne IP
    if(iIpLen == 0 || iIpLen > 15)
    {
        isValid = 0;
    }
    else
    {
        /* On récupère le premier octet */
        byte = (unsigned char)atoi(szIP);
        /* S'il est plus grand que 255 alors ce n'est pas une IP valide */
        if(byte > 255)
        {
            isValid = 0;
        }
         
        /* on parcours la chaine */
        for(i = 0; i < iIpLen && isValid == 1; i++)
        {
			/* on check si on nous donne bien seulement des chiffres ou le point */
			if(!(szIP[i] >= '0' && szIP[i] <= '9') && szIP[i] != '.')
			{
				isValid = 0;
			}
		
            /* on compte le nb de point */
            if(szIP[i] == '.')
            {
                dotCount ++;
                /* puis on check si l'octet que l'on récupère est valide */
                byte = (unsigned char)atoi(&szIP[i+1]);
                if(byte > 255)
                {
                    isValid = 0;
                }
            }
        }
        /* s'il n'y a pas trois points dans l'ip alors ce n'est pas une ip valide */
        if(dotCount != 3)
        {
            isValid = 0;
        }
         
    }
     
 
    return isValid;
}



-
Edité par Woosterfield 15 juillet 2013 à 20:30:32

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 21:25:12

Je te remercie beaucoup pour ton aide ! 

Je testerai en rentrant chez moi et te dirai si tu m'as sauvé la vie :p 

:)

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 21:47:10

Pour info, je viens de tester 256.256.256.256 et le programme me retourne ok... 

  • Partager sur Facebook
  • Partager sur Twitter
15 juillet 2013 à 22:14:51

Ineys677 a écrit:

Suite à vos differentes reponses j'ai donc fait ce bout de code : 

printf("Saisir svp : \n");
    scanf("%d" , &iAdresseIp[0]);
    scanf("%d" , &iAdresseIp[1]);
    scanf("%d" , &iAdresseIp[2]);
    scanf("%d" , &iAdresseIp[3]);

if( scanf("%d.%d.%d.%d" , &iAdresseIp[0] , &iAdresseIp[1], &iAdresseIp[2], &iAdresseIp[3]) != 4 ||
    iAdresseIp[0]>255 || iAdresseIp[1]>255 || iAdresseIp[2]>255 || iAdresseIp[3]>255 )
    printf("Saisie erronée\n");

Néanmoins le programme attend 5 valeurs ce qui me renvoie au if à chaque fois.. 


Tu as mélangé les deux, c'est l'une ou l'autre. Le if à lui même se suffit, enlève les 5 scanf qui le précède.

  • Partager sur Facebook
  • Partager sur Twitter
16 juillet 2013 à 8:39:00

Bonjour,

Woosterfield, je pense que ton erreur vient de ta conversion avec atoi().

Quand tu dis que tu récupère le premier octet, est-normal que tu lui passe toute la chaine en paramètre?

Merci encore pour votre aide



  • Partager sur Facebook
  • Partager sur Twitter
16 juillet 2013 à 22:41:10

Non, en faite atoi() prend en compte les premiers chiffres qu'il voit jusqu’à ce qu'il y ai un null byte ou bien autre chose, le soucis vient du fait que j'ai converti ce que atoi() me renvoi en unsigned char, ce qui limite le résultat à 255, donc ça retourne toujours vrai.

Voila la fonction fonctionnelle, (cette fois ci je l'ai testée :P)

int IsValidIp(char* szIP)
{
    int isValid;
    int i;
    int byte;
    int iIpLen;
    char dotCount;
      
      
    isValid = 1;
    iIpLen = strlen(szIP);
    dotCount = 0;
  
    // Si on nous donne une chaine de caractère vide ou bien que la chaine dépasse les 15 caractères ce n'est pas une bonne IP
    if(iIpLen == 0 || iIpLen > 15)
    {
        isValid = 0;
    }
    else
    {
        /* On récupère le premier octet */
        byte = atoi(szIP);

        /* S'il est plus grand que 255 alors ce n'est pas une IP valide */
        if(byte > 255)
        {
            isValid = 0;
        }
          
        /* on parcours la chaine */
        for(i = 0; i < iIpLen && isValid == 1; i++)
        {
            /* on check si on nous donne bien seulement des chiffres ou le point */
            if(!(szIP[i] >= '0' && szIP[i] <= '9') && szIP[i] != '.')
            {
                isValid = 0;
            }
         
            /* on compte le nb de point */
            if(szIP[i] == '.')
            {
                dotCount ++;
                /* puis on check si l'octet que l'on récupère est valide */
                byte = atoi(&szIP[i+1]);
                if(byte > 255)
                {
                    isValid = 0;
                }
            }
        }
        /* s'il n'y a pas trois points dans l'ip alors ce n'est pas une ip valide */
        if(dotCount != 3)
        {
            isValid = 0;
        }
          
    }
      
  
    return isValid;
}



-
Edité par Woosterfield 16 juillet 2013 à 22:42:08

  • Partager sur Facebook
  • Partager sur Twitter
18 juillet 2013 à 14:16:50

Merci à tous pour votre aide !!!

Sujet résolu :)

  • Partager sur Facebook
  • Partager sur Twitter
27 mars 2020 à 18:26:31

Bonsoir !

S'il vous plait quelqu'un pourrai m'aide ?

Écrier un programme C++ qui à partie de la saisie d'une adresse IPv4 au clavier vérifie sa validité et affiche ensuite :

- la classe

- le masque par défaut 

- l'adresse de réseau

- l'adresse de diffusion

- la plage d'adresse d’hôtes 

- le nombre de machines dans ce réseau 

-
Edité par hisseinousman1 27 mars 2020 à 19:11:12

  • Partager sur Facebook
  • Partager sur Twitter
27 mars 2020 à 19:03:21

Bonsoir ! Quand tu posteras ta demande dans le forum C++, et dans un nouveau sujet, n'oublie pas de préciser en détail de quelle aide tu as besoin. (Là, en l'absence de précision, on risque de croire que tu veux qu'on fasse le boulot à ta place.)
  • Partager sur Facebook
  • Partager sur Twitter
27 mars 2020 à 20:35:14

@hisseinousman1 Bonjour, merci de ne pas déterrer d'ancien sujet résolu et  créer votre propre sujet dans le respect des règles du forum.

Déterrage

Citation des règles générales du forum :

Avant de poster un message, vérifiez la date du sujet dans lequel vous comptiez intervenir.

Si le dernier message sur le sujet date de plus de deux mois, mieux vaut ne pas répondre.
En effet, le déterrage d'un sujet nuit au bon fonctionnement du forum, et l'informatique pouvant grandement changer en quelques mois il n'est donc que rarement pertinent de déterrer un vieux sujet.

Au lieu de déterrer un sujet il est préférable :

  • soit de contacter directement le membre voulu par messagerie privée en cliquant sur son pseudonyme pour accéder à sa page profil, puis sur le lien "Ecrire un message"
  • soit de créer un nouveau sujet décrivant votre propre contexte
  • ne pas répondre à un déterrage et le signaler à la modération

Je ferme ce sujet. En cas de désaccord, me contacter par MP.

  • Partager sur Facebook
  • Partager sur Twitter