IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

 C Discussion :

Sortie différente sur while et for identiques


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Invité
    Invité(e)
    Par défaut Sortie différente sur while et for identiques
    Bonjour,
    Sur ce code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    #include <stdio.h>
     
    int main(){
     
            char value[11] ="OH1B2RT56U";
    	char ref[5] ="abcd";
    	char new[40][3];
    	int i =0, j =0, k =0, l =0;
     
    	while(ref[i] !='\0'){
     
    		while(value[j] !='\0'){
     
    			new[k][l] =value[j];
    			l++;
    			new[k][l] =ref[i];
    			l =0;
    			printf("%s ",new[k]);
    			k++, j++;
    		}
    		j =0;
    		i++;
    	}
    	printf("\n");
     
    	k =0, l =0;
     
    	for(int i =0; ref[i] !='\0'; i++){
     
    		for(int j =0; value[j] !='\0'; j++){
     
    			new[k][l] =value[j];
    			l++;
    			new[k][l] =ref[i];
    			l =0;
    			printf("%s ",new[k]);
    		}
    	}
     
    	return (0);
    }
    Les deux boucles font la même chose, mais à la sortie la boucle while tourne free style et n'affiche jamais les mêmes signes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Oa Ha 1a Ba 2a Ra Ta 5a 6a Ua Ob Hb 1b Bb 2b Rb Tbԇ�U 5bU 6b��� Ub Oc Hc 1c Bc 2c�U� Rc Tc��U� 5cU� 6c Uc�ԇ�U Od�U Hd 1dgl� Bd 2dP�ԇ�U Rd��U Td 5d 6d Ud 
    Oa Ha 1a Ba 2a Ra Ta 5a 6a Ua Ob Hb 1b Bb 2b Rb Tb 5b 6b Ub Oc Hc 1c Bc 2c Rc Tc 5c 6c Uc Od Hd 1d Bd 2d Rd Td 5d 6d Ud
    Quelqu'un, peut-il me dire pourquoi ?

  2. #2
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par défaut
    Non les 2 boucles ne sont pas identiques

    k++


    En réalité ton code est trop mauvais
    • La variable l ne sert à rien, et pire c'est n'importe quoi les ++/ =0 et tu oublies le caractère sentinel '\0' pour chaque duo de lettres
    • Tu n'as pas besoin de redéfinir les variables i et j (dans les boucles for)
    • il manque la gestion de la variable k


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    int main(){
        char value[11] = "OH1B2RT56U"; // or char value[] = "OH1B2RT56U";
        char ref[5]    = "abcd"; // or char ref[] = "abcd";
        char new[40][3];
        int i=0, j=0, k=0;
     
        while(ref[i] !='\0'){
            while(value[j] !='\0'){
                new[k][0] = value[j];
                new[k][1] = ref[i];
                new[k][2] = '\0';
     
                printf("%s ", new[k]);
     
                ++k; ++j;
            }
            j=0; ++i;
        }
        printf("\n");
     
        k=0;
     
        for(i=0; ref[i] !='\0'; ++i){
            for(j=0; value[j] !='\0'; ++j, ++k){
                new[k][0] = value[j];
                new[k][1] = ref[i];
                new[k][2] = '\0';
     
                printf("%s ", new[k]);
            }
        }
     
        return (0);
    }

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par MissLoop Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    			new[k][l] =value[j];
    			l++;
    			new[k][l] =ref[i];
    			l =0;
    			printf("%s ",new[k]);
    Quelqu'un, peut-il me dire pourquoi ?
    Tu ne peux pas demander à afficher via "%s" un tableau de char dans lequel il n'y a pas de '\0', ce n'est pas une string. Donc tu obtiens n'importe quoi et c'est tout à fait normal.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  4. #4
    Invité
    Invité(e)
    Par défaut
    @ foetus
    Non les 2 boucles ne sont pas identiques
    Oui, oui je me suis trompée.
    D'ailleurs, si j'avais rempli le tableau de la boucle for, j'aurais constaté le même résultat.

    Tu n'as pas besoin de redéfinir les variables i et j (dans les boucles for)
    Merci pour cette remarque.

    ... et pire c'est n'importe quoi les ++/ =0...
    Lopo compris...
    Veux-tu dire qu'il y a trop de ++ et que l'affectation à 0 est redondante ?

    Dans tous les cas merci pour ta remarquable réponse.
    Joyeux Noël.

  5. #5
    Invité
    Invité(e)
    Par défaut
    Salut Sve@r, j'espère que tu vas bien.
    J'explore le C en ce moment et je rame quelque peu, mais c'est assez passionnant.

    Pour en revenir au "stop" ou plus précisément à la "fin de section" que représente '\0', je pensais que dans tous les cas le caractère de fin était géré automatiquement.
    De plus, j'ai décrété qu'un tableau de char à 2 dimensions devait gérer ses éléments char ensemble comme une string. Et ta judicieuse remarque :
    Tu ne peux pas demander à afficher via "%s" un tableau de char dans lequel il n'y a pas de '\0', ce n'est pas une string.
    Trouve tout son sens lorsque je troque mon :
    Contre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    write(1, &new[k], 2);
    write(1, " ", 1);
    Qui renvoie le bon affichage.
    Merci beaucoup pour ta réponse en te souhaitant d'excellentes fêtes de fin d'année, heureuse d'échanger à nouveau.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 840
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 840
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par MissLoop Voir le message
    Pour en revenir au "stop" ou plus précisément à la "fin de section" que représente '\0
    En C, le type "string" tel qu'on l'entend dans les autres langages (une chaine manipulable, copiable, testable) n'existe pas. Donc il a fallu trouver un truc: et ce truc ça a été que ce serait un tableau de char. Un tableau en C étant toujours (garanti par la norme) contigü en mémoire, il suffit d'avoir la première case pour avoir tout le tableau.
    Mais il n'y a pas de système en C permettant de connaitre la taille d'un tableau. C'est le programmeur qui crée son tableau qui connait sa taille et donc qui le gère. Mais comment faire pour une chaine? Comment savoir où elle se termine? Il a donc été convenu qu'on lui rajouterait un caractère particulier "en plus" valant 0x00 qu'on peut aussi noter '\0' (ce qu'on fait en général pour garder la notation "char")

    Citation Envoyé par MissLoop Voir le message
    , je pensais que dans tous les cas le caractère de fin était géré automatiquement.
    Il faut préciser ce que tu entends par "géré". Si tu crées une fonction qui par exemple compte les caractères d'un chaine, toi tu sais que si on passe une vraie chaine à ta fonction, elle se terminera par '\0' puisque c'est la convention et que si l'appelant ne la respecte pas, son code ne peut pas fonctionner. Donc de fait tu coderas ta fonction pour chercher ce '\0' et arrêter là le comptage. De fait, toutes les fonctions qui reçoivent une chaine pour la traiter feront la même chose (principe des conventions: on les respecte). Donc de ce point de vue là, les fonctions gèrent effectivement ce '\0' sous réserve qu'il y soit.
    Si maintenant tu crées une fonction qui remplit (crée, copie ou tout autre verbe impliquant la notion de création) une chaine, tu sais que pour que ta fonction soit acceptée il faudra qu'elle positionne ce '\0' sinon ta fonction ne respecte pas la convention et reste inutilisable par les autres. De fait, toutes les fonctions de création de strings garantissent qu'elles te donneront en sortie un tableau de char contenant ce '\0' (sauf sur 2 fonctions strncpy et strncat mais on ne va pas en parler immédiatement). Donc de ce point de vue là, les fonctions de création de strings garantissent la présence du '\0' et on peut alors dire qu'elles le gèrent correctement.

    Mais quand toi tu crées une string manuellement, caractère par caractère, le compilo ne sait pas que tu veux créer une string. Lui, tout ce qu'il voit, c'est un remplissage de tableau. Donc si tu veux que ce tableau soit considéré comme string il te faut mettre ce '\0'.
    Seule et unique exception: quand tu déclares ta string, tu peux écrire char s[]="hello". Là le compilateur t'offre un petit cadeau et se charge lui de mettre le '\0'. Ce qui revient à écrire char s[]={'h', 'e', 'l', 'l', 'o', '\0'}.
    Donc non, le caractère de fin n'est pas géré automatiquement, il est juste géré par tous les programmeurs et contributeurs qui t'offrent des fonctions de traitement de chaine déjà toutes faites. Mais si toi tu veux te mettre à créer ta chaine, tu dois alors, comme les autres, faire le job en entier. Et surtout n'oublie jamais toi de le prendre en considération quand tu réfléchis à la taille de ta chaine. Bref si tu écris char s[5] ça veut dire que ta chaine ne pourra contenir que 4 caractères dits "utiles" car la 5° position sera prise par le '\0'. D'ailleurs généralement on écrit plutôt char s[4+1] pour bien montrer aux autres lecteurs qu'on a bien pensé au '\0'.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  7. #7
    Invité
    Invité(e)
    Par défaut
    Tu as démêlé une pelote cérébrale que je me réservais pour me tricoter un bonnet bien chaud, histoire de garder à bonne température ma pauvre boîte crânienne, bien joué !

    Je n'avais ABSOLUMENT pas compris qu'en C le type string n'existait simplement pas. J'ai bien remarqué que ce type était absent, mais je pensais qu'il se substituait grâce au type char et qu'il se manipulait en nombre avec les tableaux à deux dimensions ; vu l'ancienneté du langage, sa gestion exclusivement numérique et surtout sa proximité processeur (après le C, on nage ou pas, enfin, on essaye sûrement de survivre... dans l'océan du langage machine).

    Mais il n'y a pas de système en C permettant de connaitre la taille d'un tableau.
    Et donc le programmeur peut utiliser sizeof() pour gérer un tableau rempli par un utilisateur.

    Il faut préciser ce que tu entends par "géré".
    Je pensais qu'il suffisait de définir le nombre de caractère comprenant '\0' pour que dans tous les cas le compilo comprenne qu'il s'agit de traiter une string...

    Seule et unique exception: quand tu déclares ta string, tu peux écrire char s[]="hello". Là le compilateur t'offre un petit cadeau et se charge lui de mettre le '\0'. Ce qui revient à écrire char s[]={'h', 'e', 'l', 'l', 'o', '\0'}.
    ...puisqu'il était capable de lire un tableau de char comme une string en inscrivant himself le end of the road qui va bien ; en lui offrant en plus la taille +1 de ma string (je veux dire de ma suite de char), je me suis dit qu'il serait indulgent, reconnaissant et pourquoi pas complètement satisfait d'avoir à faire à quelqu'un de consciencieux... mais je m'égare...

    Mais si toi tu veux te mettre à créer ta chaine, tu dois alors, comme les autres, faire le job en entier.
    ...ceci dit si j'avais compris, j'aurais fait le job en entier.

    D'ailleurs généralement on écrit plutôt char s[4+1] pour bien montrer aux autres lecteurs qu'on a bien pensé au '\0'.
    Aux autres lecteurs certes, mais beaucoup à soi-même.
    MER............CI!

  8. #8
    Expert confirmé
    Homme Profil pro
    Analyste/ Programmeur
    Inscrit en
    Juillet 2013
    Messages
    4 772
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Analyste/ Programmeur

    Informations forums :
    Inscription : Juillet 2013
    Messages : 4 772
    Par défaut
    Citation Envoyé par MissLoop Voir le message
    lopo compris...
    Veux-tu dire qu'il y a trop de ++ et que l'affectation à 0 est redondante ?
    @Sve@r a également répondu sur cette partie

    Tu as 1 tableau à 2 dimensions, certes, mais c'est plutôt 1 tableau de chaînes de caractères (de 2 caractères puisqu'on ne compte pas le caractère sentinel '\0')

    Donc pour remplir tes chaînes de 2 caractères, tu initialises ta variable l à 0 pour affecter le premier caractère et ensuite tu l'incrémentes de 1 l++ pour affecter le deuxième caractère, et ainsi de suite (lignes 15, 17, 33, 35)
    Et c'est n'importe quoi regarde mon code : tu as juste à affecter les caractères normalement avec les index (new[k][0] = value[j]; new[k][1] = ref[i]; new[k][2] = '\0';)

    Et non le caractère sentinel '\0' n'est pas géré automatiquement c'est à toi de le mettre (regarde mon code, tu le mets dans la dernière case)
    Si tu ne veux pas te prendre la tête avec '\0', il faut initialiser ton tableau au début soit :
    • avec memset(new, 0, (40 * 3 /* * sizeof(char) */));, memset documentation en anglais
    • à la définition char new[40][3] = {0}; (<- note le {0}), mais pas sûr que cela fonctionne dans tous les cas, il faut vérifier

    Au passage oui, le caractère '\0' équivaut à 0.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Ok c'est plus clair.
    Merci pour les moyens de contourner la gestion du caractère '\0', j'va potasser.

  10. #10
    Membre Expert Avatar de edgarjacobs
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2011
    Messages
    791
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 65
    Localisation : Belgique

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2011
    Messages : 791
    Par défaut
    Citation Envoyé par foetus Voir le message
    • à la définition char new[40][3] = {0}; (<- note le {0}), mais pas sûr que cela fonctionne dans tous les cas, il faut vérifier
    Si le compilateur respecte la norme (ce qui est, à ma connaissance limitée, toujours le cas), c'est garanti par §6.7.9.21 (norme c11)

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Question sur les boucles for, while
    Par Spotjaune dans le forum Débuter
    Réponses: 9
    Dernier message: 18/10/2015, 11h28
  2. while et for sur tableau
    Par macbida dans le forum Langage
    Réponses: 1
    Dernier message: 11/01/2012, 14h21
  3. Réponses: 11
    Dernier message: 28/04/2008, 16h29
  4. [MySQL] Résultat de requête différent sur 2 serveurs identiques
    Par schlitters dans le forum PHP & Base de données
    Réponses: 4
    Dernier message: 17/12/2005, 00h24
  5. Sum différents sur sur une même table ...
    Par Saloucious dans le forum Langage SQL
    Réponses: 4
    Dernier message: 05/10/2005, 15h51

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo