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 :

problème d'impression d'une chaine de caractère


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2017
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2017
    Messages : 15
    Par défaut problème d'impression d'une chaine de caractère
    Bonjour, alors voilà je bloque sur un truc sûrement très idiot, mais je ne vois pas d'où peut provenir mon erreur. De mon malloc peut-être ? Ceci étant le premier code que je pond avec les fonctions malloc et free, ça me parait plus que vraisemblable. Donc avant de vous balancer les lignes de codes, je m'explique :
    Mon programme doit simplement me ressortir les informations donnés à l'execution de celui-ci. Par exemple si je l'execute avec "./a.out la li", il me ressort "./a.out\nla\nli".
    Voici le 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
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    #include <stdlib.h>
     
    char *sum_params(char argc, char **argv)
    {
    	char *dest;
    	int strlen;
    	int i;
    	int j;
    	int o;
     
    	strlen = 1;
    	i = 0;
    	j = 0;
    	o = 0;
     
    	while (i < argc)
    	{
    		strlen = strlen + my_strlen(argv[i]) + 1;
    		i++;
    	}
     
    	i = 0;
    	dest = malloc(sizeof(char) * strlen);
    	free(dest);
     
    	while (o < strlen)
    	{
    		dest[o] = argv[j][i];
    		//my_putchar(dest[o]);
    		i++;
    		o++;
    		if (i > my_strlen(argv[j]))
    		{
    			dest[o] = '\n';
    			//my_putchar(dest[o]);
    			o++;
    			j++;
    			i = 0;
    		}
    	}
     
    	//my_putstr(dest);
    	return (dest);
    }
     
    int main(int ac, char **av)
    {
    	my_putstr(sum_params(ac, av));
    	my_putchar('\n');
    	return (0);
    }
    Voilà. Au début j'ai aussi pensé que mon erreur pouvait venir de mon "my_putstr()", mais j'ai essayé avec "my_putstr("Salut\nCaVa")", et tout m'est ressorti...
    Merci d'avance pour vos réponses !

    EDIT : J'ai aussi essayer de voir si ma chaine de caractère fonctionnait bien, et si ma boucle faisait de même, j'ai donc mis mes "my_putchar(dest[o])" dans la boucle, le plus étrange (enfin pour moi) c'est que ça m'a bien ressorti tous les caractères manquant à la fin...
    EDIT' : J'ai même tenté de voir si mon int strlen, utilisé dans mon malloc() était correct, et il l'est ! Je ne comprends vraiment pas là
    EDIT'' : Ne faites pas attention au "my_" devant strlen(), et putchar() et putstr(), c'est juste que j'utilise ma propre bibliothèque, pédagogiquement, c'est bien plus interessant d'utilisé ses propres fonctions. Vous devez simplement savoir que putstr() me ressort un string sur le terminal, et putchar(), un unique caractère. Même si ça semble évident, je le précise, on ne sait jamais ...

  2. #2
    Expert confirmé
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Décembre 2015
    Messages
    1 599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique
    Secteur : High Tech - Électronique et micro-électronique

    Informations forums :
    Inscription : Décembre 2015
    Messages : 1 599
    Par défaut
    Bonjour,
    * libérer le buffer alloué immédiatement après l'allocation et avant de s'en servir est une très très mauvaise idée.
    * l'insertion du \n doit se faire quand on est la taille de la chaîne, pas après.
    * la chaîne construite doit se terminer par un \0 qui manque.

  3. #3
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 839
    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 839
    Billets dans le blog
    1
    Par défaut
    Bonjour

    Déjà remarques générales: évite de nommer tes variables avec un nom correspondant déjà à une fonction. La fonction strlen() existe et a une action précise (qui en plus me parait identique à ta fonction my_strlen()). Bref ça évite les confusions. Idem avec tes variable "i", "j" et "o". Essaye d'utiliser des noms plus appropriés. "i" et "j" servent en général pour itérer rapidement des boucles quand leur nom n'a pas d'autre utilité mais si ces variables ont une signification plus profonde (comme "j" qui compte tes arguments) alors donne leur un nom plus explicite.
    De même "argc" et "argv" sont des noms conventionnellement associés aux paramètres de "main()". Ca aurait donc été plus logique qu'ils se nommassent ainsi dans le main() et "ac" et "av" dans ta fonction "sum_params".

    Autre remarque: la boucle
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    i=0;
    len=0;
    while (i < argc)
    {
    	len = len + strlen(argv[i]) + 1;
    	i++;
    }

    s'écrira plus facilement
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    for (len=0, i=0; i < argc; i++)
    	len=len + strlen(argv[i]) + 1;   // Eventuellement len+=strlen(argv[i]) + 1 si tu connais les priorités des opérateurs
    (tu n'es pas obligé d'initialiser "len" dans le for() mais ça montre aux lecteurs que "len" et "i" vont ensemble)

    Autrement, si tu ne peux pas remplacer un while() par un for() (comme le second où "o" est incrémenté parfois deux fois) alors écris l'initialisation de ta variable juste avant le while. Ca évitera à tes copains (je pense que tu comptes programmer un jour en équipe) de faire le yoyo pour vérifier que "o" est bien à 0.

    Concernant ton algorithme, tu fais une grosse erreur ici if (i > my_strlen(argv[j])). Si tu réfléchis bien, tu comprendras que tu dois ajouter le '\n' au-moment où "i" a atteint la taille du mot et non quand il la dépasse. Ben oui, les indices commencent à 0. Donc si ton mot fait (par exemple) une seule lettre, tu stockes la lettre[0] dans dest[0] puis "i" passe à 1 et là il a atteint la taille du mot donc là tu rajoutes le '\n" !!!

    Ensuite tu oublies 1) de réserver la taille pour le '\0' et 2) de mettre ce '\0' à la fin de ta boucle. Donc ton tableau "dest" n'est pas une chaine. Donc tu n'as pas le droit de l'afficher via puts(). Accessoirement ton cahier des charges précise que si tu l'executes avec "./a.out la li", il doit te ressortir "./a.out\nla\nli" mais ton algo écrit, lui, "./a.out\nla\nli\n". Détail mineur mais c'est à toi de voir.

    Mais ta plus grosse erreur est ce malloc()+free(). Là je ne sais que te dire. Es-tu certain de savoir à quoi sert free() ???

    PS: sinon ton idée est bonne. J'ai copié ton code chez-moi, l'ai corrigé et il fonctionne.
    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
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2017
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2017
    Messages : 15
    Par défaut
    Super merci beaucoup j'ai compris mon erreur, il me manquait effectivement un '\0', mais je pensais que par défaut, après un free(), chaque "case" de la mémoire était un '\0', donc pour moi il n'y avait pas besoin de précisé à la fin ce '\0'.
    Cependant je pense que je n'ai pas très bien compris l'utilité de free(), je pensais que c'était simplement pour "libéré", remettre en 'NULL', des parties de la mémoire (oui j'ai dit précédemment que je pensais que ça devenait '\0', mais j'ai bien compris que ça ne l'était pas, du coup je suppose que ça devient 'NULL' ?). M'enfin bon, de toute façon je vais me replongé dans le man et faire quelques exercices pour être sûr de bien avoir compris son utilité.

  5. #5
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Chercheur d'emploi
    Inscrit en
    Septembre 2007
    Messages
    7 487
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur d'emploi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 487
    Par défaut
    Bonjour,

    Citation Envoyé par Deezio Voir le message
    Cependant je pense que je n'ai pas très bien compris l'utilité de free(), je pensais que c'était simplement pour "libéré", remettre en 'NULL', des parties de la mémoire (oui j'ai dit précédemment que je pensais que ça devenait '\0', mais j'ai bien compris que ça ne l'était pas, du coup je suppose que ça devient 'NULL' ?).
    malloc() sert à « allouer » de la mémoire, c'est-à-dire à en réserver officiellement l'usage au processus qui l'a demandé, à l'exclusion des autres. Par définition, sur un ordinateur, toute la mémoire est immédiatement disponible et fonctionnelle dès la mise sous tension. En théorie, on pourrait écrire là où ça nous chante, ça ne gênerait personne tant que l'on travaillerait seul. Seulement, à partir du moment où d'autres processus fonctionnent en parallèle et, même sur des mêmes monotâches, s'il y a des ressources conservés en arrière-plan, il faut bien que le système tienne une sorte de « plan d'occupation des sols » pour savoir quelles sont les zones qui sont actuellement utilisées et lesquelles ne le sont pas.

    Quand on a fini, on appelle free() (dans le sens du verbe « libérer ») pour marquer cette plage comme à nouveau disponible et qu'elle puisse éventuellement être ré-allouée à un autre processus. Il s'agit donc simplement de gérer la réservation de la mémoire. En soi, ces fonctions n'ont donc pas vocation à modifier son état et tu la trouves donc dans l'état où on l'a laissé.

    « NULL », en revanche, est une macro définie par les headers du C (avec #define) et qui vaut en principe 0, mais qui sert surtout de marqueur spécial utilisé de la même façon que son homologue en SQL : il s'agit simplement de dire que la valeur n'existe pas du tout ou est indéfinie. C'est généralement ce qu'on utilise par défaut quand on déclare et initialise un nouveau pointeur, ou quand une fonction censée renvoyer un pointeur est dans l'incapacité de le faire, par exemple quand malloc() est à court de mémoire et qu'elle ne peut donc pas renvoyer un pointeur vers la zone fraîchement allouée.

  6. #6
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 839
    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 839
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Deezio Voir le message
    il me manquait effectivement un '\0',
    Pas que ça. Ca c'est un détail minime. L'erreur principale de ton algo c'est ton test pour déterminer à quel moment mettre le '\n'.

    Citation Envoyé par Deezio Voir le message
    je pensais que c'était simplement pour "libéré", remettre en 'NULL'
    Libérer exactement. Donc imagine ce qui se passe si par exemple tu arrives dans un bus (bondé), que tu réserves une place puis que tu la libères à la seconde suivante et que tu pars te promener dans le fond du bus pendant 10mn puis que tu reviens essayer de te rasseoir à ta place...
    En ce qui concerne "remettre à NULL" pourquoi se fatiguer à remettre à 0 une zone mémoire qui sera utilisée plus tard par quelqu'un d'autre qui, lui, y mettra autre chose ??? T'es-tu embêté à remettre à 0 tes variables "i"," j" et "o" avant de quitter ta fonction ??? Quand tu cherches à comprendre comment fonctionne une chose, n'oublie jamais que derrière cette chose il y a un type comme toi qui l'a programmée...
    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
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Avril 2017
    Messages
    15
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 26
    Localisation : France, Dordogne (Aquitaine)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2017
    Messages : 15
    Par défaut
    Mais ce que je ne comprends pas avec free, c'est que lorsque je l'utilise juste avant mon return, ma variable devient nulle...

    EDIT : Non en fait elle ne devient pas nulle, c'est juste mon return qui ne fonctionne plus. Je ne comprends pas vraiment pourquoi ?

  8. #8
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 839
    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 839
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par Deezio Voir le message
    Mais ce que je ne comprends pas avec free, c'est que lorsque je l'utilise juste avant mon return, ma variable devient nulle...
    Ben que tu l'utilises juste après le malloc ou juste avant le return c'est pareil dans les deux cas. Tu libères la zone avant de l'avoir utilisée (parce que si tu la retournes, c'est quand-même un peu pour qu'elle soit utilisée par l'appelant non ???). Et donc dans les deux cas tu l'as allouée et remplie pour rien.

    Citation Envoyé par Deezio Voir le message
    Non en fait elle ne devient pas nulle, c'est juste mon return qui ne fonctionne plus.
    Le return fonctionne très bien. Ou alors les lois du C ont basculé dans le néant.

    Citation Envoyé par Deezio Voir le message
    Je ne comprends pas vraiment pourquoi ?
    Parce que tu n'affiches probablement pas ce qu'il faut. A mon avis tu tentes d'afficher via my_putstr() donc tu tentes d'afficher le contenu de la zone. Mais si tu veux vérifier que ton return a bien fonctionné, c'est la chose retournée qu'il te faut afficher donc ici la valeur numérique de "dest" avant de la renvoyer => printf("%d\n", dest) // Ou printf("%x", dest) si tu préfères l'avoir en hexa.
    Et dans le main tu affiches pareillement la valeur de ce que tu reçois.
    Code c : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    int main(int ac, char **av)
    {
    	char *xxx=sum_params(ac, av);
    	printf("%d\n", xxx);
    	...
    }

    Et tu verras que ce sont les mêmes.

    PS: pourquoi t'as cliqué sur "résolu" ??? La discussion ne l'est pas tout à fait...
    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]

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

Discussions similaires

  1. Réponses: 12
    Dernier message: 01/09/2014, 16h12
  2. Réponses: 3
    Dernier message: 07/03/2009, 14h44
  3. [XSL] Problème d'echappement dans une chaine de caractère
    Par thierry_b dans le forum XSL/XSLT/XPATH
    Réponses: 2
    Dernier message: 03/03/2009, 09h49
  4. Réponses: 2
    Dernier message: 29/07/2008, 12h23
  5. Réponses: 4
    Dernier message: 10/07/2008, 13h34

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