CONNEXION
  • RetourJeux
    • Sorties
    • Hit Parade
    • Les + populaires
    • Les + attendus
    • Soluces
    • Tous les Jeux
    • Gaming
  • RetourActu Gaming
    • News
    • Astuces
    • Tests
    • Previews
    • Toute l'actu gaming
  • RetourBons plans
    • Bons plans
    • Bons plans Smartphone
    • Bons plans Hardware
    • Bons plans Image et Son
    • Bons plans Amazon
    • Bons plans Cdiscount
    • Bons plans Decathlon
    • Bons plans Fnac
    • Tous les Bons plans
  • RetourJVTech
    • Actus High-Tech
    • Intelligence Artificielle
    • Smartphones
    • Mobilité urbaine
    • Hardware
    • Image et son
    • Tutoriels
    • Tests produits High-Tech
    • Guides d'achat High-Tech
    • JVTech
  • RetourCulture
    • Actus Culture
    • Culture
  • RetourVidéos
    • A la une
    • Gaming Live
    • Vidéos Tests
    • Vidéos Previews
    • Gameplay
    • Trailers
    • Chroniques
    • Replay Web TV
    • Toutes les vidéos
  • RetourForums
    • Hardware PC
    • PS5
    • Switch 2
    • Xbox Series
    • Switch
    • Pokemon pocket
    • FC 25 Ultimate Team
    • League of Legends
    • Tous les Forums
  • PC
  • PS5
  • Xbox Series
  • Switch 2
  • PS4
  • One
  • Switch
  • iOS
  • Android
  • MMO
  • RPG
  • FPS
En ce moment Genshin Impact Valhalla Breath of the wild Animal Crossing GTA 5 Red dead 2
Liste des sujets

[C] problème simple d'algo

ArsenicBottle
ArsenicBottle
Niveau 6
03 mai 2008 à 20:14:29

dans un programme que j'ai fait, je dois écrire les fonctions member et efface : member doit vérifier qu'un mot appartient à une chaine de caractère et efface doit effacer le mot de la chaine.
Problème, ca plante pendant l'exécution, mais je vois pas le problème avec ce petit algo...

Les fonctions suivantes ont déjà été écrite et elle marche :
premier : renvoie le premier mot d'une chaine de car (on travaille avec des chaine de caractères formatées et les mot sont séparés au sein de la chaine par un espace)
saufpremier : renvoie la chaine initiale privée du 1er mot.
egal : vérifie si les 2 chaines sont identiques
vide : teste si la chaine est vide.

A priori l'erreur viendrait de efface, mais je vois pas ou, pourtant c'est simple....

int Member(char * m, char *ch)

{
if (vide(m)) return 1;
else if (vide(ch)) return 0;
else if (egal(m,Premier(ch))) return 1;
else return Member(m,SaufPremier(ch));
}

char *Efface(char *m, char *ch)

{
if (vide(ch)) return ch;
else if (Member(m,ch))
{
if ( egal(m,Premier(ch)) ) return Efface(m,SaufPremier(ch));
else return Phrase(Premier(ch),Efface(m,SaufPremier(ch)));
}
else return ch;

}

dnob700
dnob700
Niveau 10
03 mai 2008 à 21:50:16

dire que tout ça pourrait être coder dans en caml ou dans un autre vrai langage ...

Bon, quelle est l'erreur à l'exécution ? quand tu appelles quelle fonction ? donne nous le code des autres fonctions, car l'erreur est probablement dans la partie "bas niveau".

Indépendamment de ça, la fonction efface est "fausse" car elle a une complexité temporelle dans le pire cas en O(n*n) où n est le nombre de mot de la chaîne, alors qu'elle devrait avoir une complexité de seulement O(n).

ArsenicBottle
ArsenicBottle
Niveau 6
04 mai 2008 à 00:40:51

c'est pas un vrai langaga le C ? (je sens le troll, mais si tu pouvais juste te justifier un peu ca m'aiderai à comprendre)

Je l'exécute dans une fenetre DOS et lorsque doit s'exécuter la fonction efface, ca plante , le programme s'arrète et il affiche "appuyer sur une touche pour continuer" (sachant qu'il n'y a pas de problème sur les autres fonctions de bas niveau (elle effectue correctement leur boulot). La j'ai pas le code sous la main mais s'il faut je le donnerais... Du coup je pense qu'il s'agit uniquement des deux dernières fonctions qui peuvent poser problème.

SInon je dois la créer en récursif cette fonction, du coup je pense pas pouvoir gagner en complexité, si ?

dnob700
dnob700
Niveau 10
04 mai 2008 à 01:03:11

le C est un vrai langage. Mais juste en ocaml exprimer la même chose (tes phrases sont fondamentalement des listes chaînées) prendrait beaucoup moins de temps.

pour la complexité, il suffit de ne pas appeler la fonction "member" dans ta fonction efface. Ce n'est pas un problème de récursivité.

ArsenicBottle
ArsenicBottle
Niveau 6
04 mai 2008 à 10:14:57

d'accord. En fait c'est un tp a faire en cours, donc l'intéret c'est de manipuler le langage C. Mais je ne connais pas le caml de toute facon^^

Sinon après réexécution du programme, j'ai vu que ma fonction SaufPremier ne marchait pas, désolé :honte:

Je me suis peut-être trompé dans le malloc que je ne connais pas très bien... La fonction plante lorque apparament il y a un seul
mot dans la chaine.

char *SaufPremier (const char *ch)
{
int len;
char *p, *q;

p=strchr(ch,' ');
if (p==NULL) return strdup(ch);
else
{
len=strlen(p)+2;
q=(char *) malloc(len);
q=p+1;
q[len]='\0';
return q;
}
}

godrik
godrik
Niveau 30
04 mai 2008 à 13:40:24

faire de la récursivité en C, c'est un peu comme faire de l'art avec paint. Ca marche c'est pas bien elegant...

(ceci était un post qui ne fait pas avancer le débat)

dnob700
dnob700
Niveau 10
04 mai 2008 à 21:36:26

ta fonction saufpremier est une horreur absolue. Dans tout les cas, tu as une fuite de mémoire.

À la place de "return strdup(ch);" tu pourrais faire "return ch;" pour ne pas gaspiller de la mémoire en recopiant inutilement une chaîne que tu vas oublier de libérer.
Et dans le cas où il y a quelque chose, tu peut juste renvoyer p+1, là encore, tu n'a pas besoin de recopier la chaîne (ce que d'ailleurs, tu ne fais pas, du crée juste une zone de mémoire que tu "oublie" instantanément).

D'autre part, le plantage peut venir du fait que ton "len" est faux. C'est soit "strlen(p)", soit "strlen(p+1)+1" (similaire, mais _plus exactes_ car la chaîne débute à p+1). Et dans quand tu écris le 0 final, tu fait un débordement de tempon.

Bref, ce n'est pas grave si tu ne sais pas te servir de malloc, tu n'en a pas du tout besoin.

ArsenicBottle
ArsenicBottle
Niveau 6
05 mai 2008 à 13:44:25

"une horreur absolue" :rire2:

effectivement, après relecture je comprends mes erreurs. Et en fait j'en avais oublié une toute bete : je devais retourner strdup("") au lieu de ch... c'était tout bete.

En tout cas merci pour ces conseils, ca fait plaisir d'etre un peu guidé.

:merci:

dnob700
dnob700
Niveau 10
05 mai 2008 à 21:09:00

ah oui tiens, je n'ai pas fait attention à ça. Mais là c'est pareil, tu peut faire "return "";" pour ne pas gaspiller de mémoire (bon ça ne vas pas, il faut que la chaîne "" soit globale au programme).

Alors tu peut utiliser strchrnul et si la fonction renvoie un pointeur vers 0, alors tu renvoie la chaine elle même et sinon ce qui suit.

Par exemple, ta fonction pourrait être réécrite :
char *SaufPremier (const char *ch)
{
char *p=strchrnul(ch,' ');
return *p ? p+1 : p;
}

ArsenicBottle
ArsenicBottle
Niveau 6
06 mai 2008 à 15:14:47

char *LireChaine(void)

{
char *s, *r, *p, *q, *aux;
int i, j = 0;
int len;

fflush(stdin);
gets(tab1);
s = (char *) malloc(MAX+1);
for(i=0;i<=MAX;i++) s[i]=tab1[i];
s[MAX]='\0';
printf("\n voici la copie de tab1 dans s : <%s> \n"; s);

while (s[j] == ' ')
{
j++;
s++;
}

p=strchr(s,' ');

while (p!=NULL)
{
q=p+1;
while (q[0]==' ') q++;
p+1=q;
p=strchr(p+1,' ')
}

for(i=0;i<=MAX-1;i++) tab1[i]=s[i];
tab[MAX]='\0';
}

est-ce qu'il y a une erreur fondamentale dans ce morceau de programme ? J'essaie de l'executer en vain je comprend pas pq ca bug.
A la base le but est de formater une chaine de caractère, c'est a dire enlever les espaces au début et à la fin, et laisser un seul espace là ou il y en a plein à la suite.

ArsenicBottle
ArsenicBottle
Niveau 6
06 mai 2008 à 15:24:40

while (s[0] == ' ') s++;

au lieu de

while (s[j] == ' ')
{
j++;
s++;
}

désolé

MCWarriors
MCWarriors
Niveau 6
06 mai 2008 à 15:31:00

Le code présenté ne compile même pas.
- MAX et tab1 ne sont pas définis
- p+1=q est incorrect, p+1 n'est pas une lvalue valable
- Il manque un tas de ;
- ...

Ce serait pas mal que tu nous colle le véritable code que tu compiles.

ArsenicBottle
ArsenicBottle
Niveau 6
06 mai 2008 à 19:38:48

a oui pardon, c'est jsute une fonction. En fait le tout était un peu long.

Cela dit je veux bien une explication la dessus : "p+1=q est incorrect, p+1 n'est pas une lvalue valable"

Je ne comprends pas ce que cela veut dire. Ce que je voulais faire c'était éliminer les caractères qui se trouvent entre les pointeurs p et q. donc je voulais remplacer le pointeur p+1 par le pointeur q.

Ce n'est pas correct :question:

Je pense que non^^ mais comment faire cette opération alors ?

godrik
godrik
Niveau 30
06 mai 2008 à 23:18:08

p+1 n'est pas une expression affectable.
3 n'en est pas une non plus.
p en est une parcontre.

En bref, tu ne peux utiliser qu'une variable ou le contenu d'une adresse comme expression affectable

PS: l-value pourrait se traduire par expression affectable

dnob700
dnob700
Niveau 10
06 mai 2008 à 23:55:58

il faut écrire "p = q - 1".

Tu ne peut avoir qu'un nom de variable "simple" à gauche du signe égal.

Mais ton code fait absolument n'importe quoi. Comme tu ne sais pas du tout manipuler les chaines de caractères, je te conseille de faire un petit tour sur le sdz (par exemple ce chapitre et les deux suivants : http://www.siteduzero.com/tuto-3-3828-1-a-l-assaut-des-pointeurs.html ) parce que là, on pourrait corriger ton code, mais ça ne t'apprendrais pas grand chose.

ArsenicBottle
ArsenicBottle
Niveau 6
08 mai 2008 à 21:04:44

ok c'est une bonne idée.

merci

mr_monkey
mr_monkey
Niveau 10
12 mai 2008 à 18:36:39

Ouais c'est toujours délicat de manipuler des chaînes de caractères en C ^^ Ne t'inquiete pas c'est facile de critiquer et de corriger les erreurs des autres mais on fait tous les mêmes

Sous forums
  • Aide à l'achat Mac
  • Steam Deck
  • Création de sites web
  • Création de Jeux
  • Linux
  • Programmation
  • Internet
  • Macintosh
  • Hardware
La vidéo du moment