Probleme avec un petit prog C

Fermé
tapharule - 2 févr. 2009 à 11:20
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 - 4 févr. 2009 à 18:35
Bonjour, j ai un probleme dans mon prog qui est sence me mettre les mots d une phrase dans un char **
o moment dafficher si la chaine est trop longue jai des caractaire bizar qui apparaissent
et le + bizar c que ci je change la valeur du malloc j obtien dautre ecriture encore

voici mon code source

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

//char *malloc(int size);

/*
fonction qui compte les mots d une string
*/

int cpt_word(char *str)
{
int i;
int cpt;
char car_prec;

i = 0;
cpt = 0;
car_prec = ' ';
while (str[i] != '\0')
{
if ((car_prec == ' ') && (str[i] != ' '))
{
cpt++;
}
car_prec = str[i];
i++;
}
return (cpt);
}

/*
chaine qui prend la position d une str et sauvegarde la chaine depuis la position jusqu a la rencontre d un espace
*/

char *copy(char *str, char *dest, int debut)
{
int i;

i = 0;
while ((str[debut] != ' ') && (str[debut] != '\0'))
{
dest[i] = str[debut];
debut++;
i++;
}
dest[i] = '\0';
return (dest);
}

/*
** chaine qui compte le nombre de lettre d un mot (utiliser pour faire un malloc)
*/

int cpt_letter(char *str, int debut)
{
int i;

i = 0;
while ((str[debut] != ' ') && (str[debut] != '\0'))
{
debut++;
i++;
}
return (i);
}

/*
** fonction general qui met chaque mots dans le char **
*/

char **my_str_to_wordtab(char *str)
{
int i;
int j;
char car_prec;
char **tab;

i = j = 0;
tab = malloc((cpt_word(str) + 1) * sizeof(**tab));
car_prec = ' ';
while (str[i] != '\0')
{
if ((car_prec == ' ') && (str[i] != ' '))
{

tab[j] = malloc((cpt_letter(str, i) + 25) * sizeof(*tab));
copy(str, tab[j], i);
j++;
}
car_prec = str[i];
i++;
}
tab[j] = '\0';
return (tab);
}

/*
int main(int argc, char **argv)
{
int i;
char **tab;

tab = my_str_to_wordtab(argv[1]);
i = 0;
while (tab[i] != '\0')
{
i++;
}
}
*/

7 réponses

pour le main

int main(int argc, char **argv)
{
int i;
char **tab;

tab = my_str_to_wordtab(argv[1]);
i = 0;
while (tab[i] != '\0')
{
printf("%s\n", tab[i]);
i++;
}
}
1
./a.out "a b c d e f g h i j k l m n o p q r s t u v w x y z"
���
b
c
d
e
f
g
h
i
j
k
l
m
n
o
p
q
r
s
t
u
v
w
x
z



compren po les ???
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 840
2 févr. 2009 à 11:36
Salut,
T'as le droit d'utiliser des fonctions déjà existantes ou tout refaire à la main ?
Ton but, c'est de mettre dans un tableau 2D tout ce qui passe en arguments c'est ça ?

Je te propose le code suivant :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char** my_str_wordtab(const size_t sz,char**argv){
    char **tab;
    tab=malloc(sz*sizeof *tab);
    if(tab==NULL){
        fputs("erreur allocation",stderr);
        exit(1);
    }

    for(int i=0;i<sz;i++){
        int taille=strlen(argv[i+1]);
        tab[i]=malloc((taille+1)*sizeof **tab);
        if(tab[i]==NULL){
            fputs("erreur allocation",stderr);
            exit(1);
        }
        strncpy(tab[i],argv[i+1],taille+1);
    }

    return tab;
}

void desallocation(const int sz, char **tab){
    for(int i=0;i<sz;i++){
        free(tab[i]);tab[i]=NULL;
    }

    free(tab);tab=NULL;
}


int main(int argc, char **argv){
    char **tab;

    if(argc>1){
        tab=my_str_wordtab(argc-1,argv);
        for(int i=0;i<argc-1;i++)
            puts(tab[i]);

        desallocation(argc-1,tab);
    }

    return 0;
}
0
merci pour ta reponse . non je ne peux utiliser les fonctions du systeme sinon mon exo etait le suivant

)Écrire une fonction qui decoupe une chaine de caracteres en mots.
La fonction renvoie un tableau, où chaque case contient l'adresse
d'une chaine de caractere representant un mot. Le dernier element
du tableau devra etre egal a 0 pour marquer la fin du tableau.
La chaine qui sera transmise sera modifiable (et modifiee).
La fonction devra être prototypée de la maniére suivante :

char **my_str_to_wordtab(char *str);

or toi ton programme il ne fait que mettre dans ton tab[0] les argument passe en parametre donc meme pas dinteret de cree un char **; vu que yora jamais rien dans tab[1]
donc tu vois normalement si apres avoir compiler jexecute ./a.out "je suis null"
je suis cense avoir dans tab[0] = "je"
dans tab[1] = "suis"
et dans tab[2] = "null"
or dans ton code si j execute ./a.out "je suis null"
jorais dans tab[0] = "je suis null"

sinon jai pu resoudre le probleme dans mon code ct juste un blem sur lallocation o lieu de faire sizeof(*tab)
je faisais sizeof(**tab) et la ou jen mete deux etoile il fallai en mettre qu une seule du coup o lieu de multiplier par 4byte je multiplier par 1bite

Merci davoir utiliser de ton temps pour m aider
0
dwyane > dwyane
4 févr. 2009 à 05:32
voici mon code final ci sa tinteress jai juste effacer une * et encore merci

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

//char *malloc(int size);

int cpt_word(char *str)
{
int i;
int cpt;
char car_prec;

i = 0;
cpt = 0;
car_prec = ' ';
while (str[i] != '\0')
{
if ((car_prec == ' ') && (str[i] != ' '))
{
cpt++;
}
car_prec = str[i];
i++;
}
return (cpt);
}

char *copy(char *str, char *dest, int debut)
{
int i;

i = 0;
while ((str[debut] != ' ') && (str[debut] != '\0'))
{
dest[i] = str[debut];
debut++;
i++;
}
dest[i] = '\0';
return (dest);
}

int cpt_letter(char *str, int debut)
{
int i;

i = 0;
while ((str[debut] != ' ') && (str[debut] != '\0'))
{
debut++;
i++;
}
return (i);
}


char **my_str_to_wordtab(char *str)
{
int i;
int j;
char car_prec;
char **tab;

i = j = 0;
tab = malloc((cpt_word(str) + 1) * sizeof(*tab));
// sizeof(**tab) CT LA MON ERREUR
car_prec = ' ';
while (str[i] != '\0')
{
if ((car_prec == ' ') && (str[i] != ' '))
{

tab[j] = malloc((cpt_letter(str, i) + 1) * sizeof(**tab)); // ICI JALLOUE* 4*trop de memoire ca je faisai sizeof(*tab)
copy(str, tab[j], i);
j++;
}
car_prec = str[i];
i++;
}
tab[j] = '\0';
return (tab);
}


int main(int argc, char **argv)
{
int i;
char **tab;

tab = my_str_to_wordtab(argv[1]);
i = 0;
while (tab[i] != '\0')
{
printf("%s\n", tab[i]);
i++;
}
}
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 840
4 févr. 2009 à 12:12
Sauf que je n'avais pas l'énoncé, donc pas évident d'aider.

or toi ton programme il ne fait que mettre dans ton tab[0] les argument passe en parametre donc meme pas dinteret de cree un char **
Non tu as dû mal lire mon programme.
Il créé un tableau de pointeurs dont le pointeur i pointera vers des zones du heap alloués avec l'argument argv[i+1].
La preuve est que que dans le main(), j'affiche la valeur du tableau tab[i]. tab[0] contient seulement le premier argument comme tu le souhaitais.

De plus dans ton programme, tu oublies de désallouer les zones du heap avec free, ce qui conduit à des fuites mémoires.
Dans ton main(), tu oublies de faire un return 0;.
Et puis tout simplement ton programme ne marche pas.
Si tu demandes d'afficher tab[1] explicitement lorsque tu enverras deux arguments, ton programme fera un joli segfault, et c'est normal puisque ton algorithme est faux.
Tu mets : while (str[i] != '\0')
Donc à la fin du premier argument (qui contient un \0 pour désigner la fin de la mémoire), t'arrêtes la boucle.
Ce n'est pas seulement le dernier argument qui contient le \0. Si l'espace permet de séparer les arguments au lancement du programme, dans la mémoire ce n'est pas traité de la même façon. Les espaces n'existent plus.

Cdlt
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
si je te dis que ton programme est faux c pas parce que je l ai lu mais car je les tester essaye le main suivant dans ton code

int main(int argc, char **argv)
{
printf("%s", tab[0]);
return (0);
}

il taffichera toute la ligne de commande a coup sur et si tu fait un printf("%s", tab[1]); sa segfault

mais dsl mon programme marche parfaitement si tu reussi a le faire beuguer fait me signe bien sur pour les free je les fait dans mon programme final (c a dire celui que j ai rendu)


Tu mets : while (str[i] != '\0')
Donc à la fin du premier argument (qui contient un \0 pour désigner la fin de la mémoire), t'arrêtes la boucle.

tout a fait c juste le premier argument en ligne de commande qui m intereses d ou argv[1] .
pour tout dire on etait meme pas obliger de prendre les argument en ligne de commande ct juste pour faire different test en ligne de commande mais jorai pu ouvrir mon code mettre dans le main
tab = my_str_to_word_tab("ceci est mon test");
est voir ci j ai les bon resultats en rendant l exo on doit enlever le main c pk jai po fai le test if (argc > 1)
et le return (0);


cordialement
0
en faite c que tu n as pas bien compris l exo

c juste une fonction qui prend une chaine et te met chacun des mots dans un tableau de chaine
sinon je respecte ceux qui libere la memoire apres allocation . de nos jours les gens passent leur temps a surallouer et ce preocupent tres peu des fuites . ceux qui rend leur prog vulnerables aux hackeurs .
merci
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 840 > dwyane
4 févr. 2009 à 13:07
Comme je t'ai dit dans mon message 9, ton programme ne met pas chacun des mots dans un tableau puisque si tu demandes l'affichage de la deuxième case, ça segfault.
ce preocupent tres peu des fuites . ceux qui rend leur prog vulnerables aux hackeurs .
Oui, pour le DoS. Mais il y a aussi ceux qui ne fixe pas une taille maximum quand lorsqu'il copie, ce qui peut conduire à récrire sur l'eip au sein du frame de la pile et forcer le retour de la fonction à exécuter une zone dont un pirate aura le contrôle (principe du buffer overflow).
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 840
4 févr. 2009 à 13:02
mais dsl mon programme marche parfaitement si tu reussi a le faire beuguer fait me signe
D'ac.
Donc, à partir de ton programme, je change juste le main.
int main(int argc, char **argv)
{
    int i;
    char **tab;

    tab = my_str_to_wordtab(argv[1]);
    i = 0;
    if(argc>2) puts(tab[1]);
    return 0;
}

Je compile. Et je lance :
fiddy@laptop2008:~/bidouille$ ./prg a b
Erreur de segmentation (core dumped)

Pourtant normalement il aurait dû afficher b, puisque c'est le deuxième argument.

Même chose avec mon programme :

fiddy@laptop2008:~/bidouille$ ./prg1 a b
b

Et si j'affiche tab[0] comme tu me l'as demandé, j'obtiens :
fiddy@laptop2008:~/bidouille$ ./prg1 a b
a

Ce qui est normal puisqu'on demande d'afficher le premier argument (qui est ici a).
0
relie l exo stp
tu tetonne que sa sexfault ?

int main(int argc, char **argv)
{
int i;
char **tab;

tab = my_str_to_wordtab(argv[1]);
i = 0;
if(argc>2) puts(tab[1]);
return 0;
}

Je compile. Et je lance :

fiddy@laptop2008:~/bidouille$ ./prg a b
Erreur de segmentation (core dumped)


Pourtant normalement il aurait dû afficher b, puisque c'est le deuxième argument.


BEN NON a tab[1] il ne doit y avoir un '\0'
toi tu copy chaque argument passer en parametre dans une case du tableau
c a dire tab[0] = argv[0]
tab[1] = argv[1];

or non c pas se qui est demande pour ce main


int main(int argc, char **argv)
{
int i;
char **tab;

tab = my_str_to_wordtab(argv[1]);
i = 0;
while (tab[i] != '\0')
{
printf("tab[%d] = %s\n", i, tab[i]);
i++;
}
}

sa maffiche

./a.out "ceci est mon test" noubli po que ./a.out "a" "b" != ./a.out a b
tab[0] = ceci
tab[1] = est
tab[2] = mon
tab[3] = test


or toi pour le meme main

./a.out "ceci est mon test"
tab[0] = ceci est mon test

es ke tu voi un peu quand tu test c juste le first argument qui tinteress pas le reste sa pren en parametre un char *str et nn un char **tab
0
fiddy Messages postés 11069 Date d'inscription samedi 5 mai 2007 Statut Contributeur Dernière intervention 23 avril 2022 1 840
4 févr. 2009 à 18:35
Méa culpa. Effectivement, je croyais que ton énoncé était de mettre dans un tableau de pointeurs les arguments lancés au programme. Retirons tout ce que j'ai dit dans ce cas ^^.
0