Bonjour,
j'ai peu de connaissance en C et beaucoup de problèmes avec les "chaines" de caractères et le C!
J'ai un fichier en entrée que je dois éclater en plusieurs fichiers.
entrée.txt =
DEBUT nomfichier1
infodiverses1
FIN
DEBUT nomfichier2
infodiverses2
FIN
etc...
le but évident étant d'avoir un fichier nommé nomfichier1.txt contenant
infodiverses1, un fichier nommé nomfichier2.txt contenant
infodiverses2 etc...
Je lis donc mon fichier entrée.txt avec fgets tant que je ne suis pas à la fin.
[code]
chainelu char[30];
char *ptr;
fgets(cjainelu,sizeofchainelu),entree.txt);
indice=str_istr (chainelu, " "); /* retourne l'indice de l'occurence " "*/
ptr=&chainelu[indice];
strcat(str,".txt");
[/code]
Problème :
C'est que ptr contient nomfichier1 avec des espaces en fin!!!!!! donc l'ajout n'amene rien.
J'ai essayé de détecter les espaces mais cela ne fonctionne pas.
Alors j'essaye d'extraire la chaine mais je trouve cela compliqué pour pas grand chose.
Pouvez m'aider en m'indiquant pourquoi il se comporte ainsi, comment faire pour simplifier , voir comment faire autrement si une solution plus simple existe et que je me fourvoye dans l'utilisation de C ?
Merci par avance,
C
# Utiliser glib ....
Posté par jlh . Évalué à 2.
voir http://developer.gnome.org/doc/API/2.0/glib/index.html/
pour la documentation de l'api (en anglais malheureusement)
notamment la partie "String utility fonction".
# Ton post est une blague ou
Posté par lcld . Évalué à -5.
Bon, je vais quand même répondre parce qu'une solution en shell tient en 8 lignes : Ex. d'utilisation : ./en_shell < entrée.txt
Et si tu veux des pistes pour le faire en C, montre que ça t'intéresse un minimum.
[^] # Re: Ton post est une blague ou
Posté par liberforce (site web personnel) . Évalué à 2.
C'est super que tu saches le faire, mais n'en dégoute pas les autres. T'as peut être appris le C au berceau, c'est pas le cas de tout le monde.
M'énerve...
[^] # Re: Ton post est une blague ou
Posté par liberforce (site web personnel) . Évalué à 3.
2. chercher les fonctions qui peuvent t'aider à le faire... notamment c'est bien le diable s'il n'y a pas une fonction qui lit une ligne entière dans un fichier texte
3. oui, effectivement, le C de base, pour traiter des chaines de caractère de base, c'est tout pourri. Les langages de script comme python, perl et shell l'enfoncent.
4. Il te reste la solution la plus simple: au lieu de réécrire la roue utiliser une API qui a des fonctions d'n peu plus haut niveau un peu plus conviviales, comme l'excellente glib, effectivement: http://www.gtk.org/api/2.6/glib/glib-File-Utilities.html (regarde bien g_get_file_contents)
5. ne pas se décourager, c'est pas évident quand on débute
6. Commenter son code, mais pas comme tu le fais: dire *ce qu'on fait* et pas *comment on le fait* dans tes commentaires
Si tu ne veux pas utiliser de bibliothèque comme la glib, alors tu trouveras une bonne référence des fonctions standard en C:
http://www.delorie.com/djgpp/doc/libc-2.02/
Les modules qui t'intéressent: stdio (pour l'accès au fichiers dans ons cas), string (pour la manipulation de chaines de caratères)
après, tu fais plusieurs erreurs dans ton code, à vue de nez:
chainelu char[30]; il faut mettre le type avant le nom de variable: char chainelue[30];
char *ptr; ok
Ensuite tu as besoin d'ouvir ton fichier pour récupérer un descripteur de fichier à utiliser dans fgets (regarde fopen: http://www.delorie.com/djgpp/doc/libc-2.02/libc_299.html ), du genre fd = fopen(entree.txt, "r");
fgets(cjainelu,sizeofchainelu),entree.txt); => mauvais usage de sizeof, et on passe un pointeur sur un descripteur de fichier en dernier argument, et pas le nom du fichier :fgets(chainelue, sizeof(chainelue), fd);
[...]
Bref, relis un petit peu tes cours, commence par un ou deux tutoriels de C, parce que là tu manques cruellement de connaissances de base pour faire ce que tu souhaites. N'oublie pas aussi d'écrire ligne par ligne et de compiler juste après chaque ajout, les messages du compilateur te guideront pour corriger tes erreurs. Mais là tu es un peu "juste".
[^] # Re: Ton post est une blague ou
Posté par liberforce (site web personnel) . Évalué à 2.
Ah, et n'hésite pas à utiliser un éditeur qui te fait de la coloration syntaxique ( http://fr.wikipedia.org/wiki/Coloration_syntaxique ), ça te permettra de voir les erreurs les plus grossières...
[^] # Re: Ton post est une blague ou
Posté par Sebastian . Évalué à 2.
Si tu trouves que la personne s'est mal exprimée, il suffit simplement de lui demander des détails et une explication un peu plus claire.
Mais de là à lui envoyer un code à la figure et de lui dire ses quatres vérités c'est un peu fort.
Il y en a qui découvre les languages.
Surtout le C, qui n'est pas un des plus faciles.
Donc la moindre des gentillesses aurait été de lui dire par exemple ... "Il existe une solution plus simple pour traiter ton problème ... un script bash ...".
Voilà un bel exemple de la communauté et de l'entraide :|
[^] # (réponse groupée)
Posté par lcld . Évalué à 3.
Ne me dites pas que c'est le résultat auquel il est arrivé, ou le reste de son message aurait été complètement différent : il donne l'impression de l'avoir compilé alors pourquoi ne pas avoir _copié-collé_ ?
Vous vous rendez compte que vous avez pris la peine de répondre ceci :
"chainelu char[30]; il faut mettre le type avant le nom de variable: char chainelue[30];" ?
Comme vous voulez, mais je pense qu'il gagnera à mieux poser ses questions. Et ce n'est pas comme si c'était son premier post.
Ca n'a rien à voir avec le fait qu'il débute en C.
Je comprends qu'il ne voulait pas forcément faire ça en C.
Si vous préférez que j'ignore ce genre de questions, dites-le.
# Un peu de C...
Posté par alf . Évalué à 1.
Pour le codage en C: fgets sert à lire une ligne de texte. Mais attention, cette fonction n'est pas simple à utiliser. Elle s'arrête soit:
- quand le marqueur de fin de ligne '\n' est rencontré
- quand le buffer que tu lui as passé est plein
- en cas d'erreur interne (I/O, par exemple).
Dans le troisième cas, fgets renvoie NULL; pour différencier les deux premiers, il faut chercher le caractère '\n' dans le buffer (pour chercher un caractère dans une chaîne: strchr). Si la ligne n'est pas complète, il vaut mieux réallouer un buffer plus grand.
Et tout ça est C ISO. Il n'y a pas besoin de dépendre d'une bibliothèque externe, mais il faut avouer que ça peut être utile; Pour lire une ligne d'un fichier sans s'embêter avec fgets/strchr/realloc, tu peux utiliser des choses déjà existantes, comme la fonction fggets de CB Falconer, un participant régulier de comp.lang.c, qui évite tous ces problèmes http://cbfalconer.home.att.net/download/index.htm
. Cette fonction (implementée en C ISO, donc portable), distribuée en domaine public, t'épargne les tests à n'en plus finir. Tu auras juste à écrire quelque chose comme :
char *ligne=NULL;
FILE *fd = fopen("ton_fichier", "r");
if (fd == NULL)
{ /* traitement d'erreur */ }
while (fggets(&ligne, fd) == 0)
{
/* la boucle principale */
}
Ensuite, pour comparer deux chaînes (dans le cas de 'DEBUT' et 'FIN'): strcmp.
Avec ça, tu devrais déjà avoir de quoi faire. Si tu as d'autres questions, ou que l'explication n'est pas claire, n'hésite pas à redemander.
# ma solution
Posté par Cereal Killer . Évalué à 1.
[^] # Re: ma solution
Posté par alf . Évalué à 1.
Si tu n'utilises pas les arguments, un void suffit.
Pense à vérifier si fopen a bien marché.
strdup est une extension GNU (je n'ai rien contre les extensions, c'est juste pour signaler qu'il y pourra y avoir des problèmes de portabilité par la suite).
Et vérifie aussi que la fonction a bien marché, sinon le fopen avec une valeur nulle causera un comportement indéfini.
Idem: vérifier le succès de fopen
Tu as oublié de comparer le début de buf avec "DEBUT". Et si une ligne du fichier d'entrée est plus longue que BUFSIZ, tu tronques les lignes...
De plus, si la ligne comprend un expace au plein milieu, ton fscanf ne prendra pas la fin de la ligne.
Tu pourrais rajouter le fclose dans ce block, pour éviter d'avoir un nombre indéterminé de fichiers ouverts en même temps (ça évite de planter si on ouvre trop de fichiers...).
Pour ton malloc: sizeof(char) vaut 1 par définition, donc tu peux simplifier l'écriture en
Pour la première étape, on a cpt == 1, donc tu réserves 4 caractères (car strlen("out") == 3). Or, tu places ensuite la chaîne "out", puis la chaîne de caractères représentant cpt+1 en décimal, c'est-à-dire "2". Tu aboutis donc à 5 caractères: 'o', 'u', 't', '2', '\0'.
Tu as donc effectué un débordement de tampon, et provoqué un comportement indéfini.
Mais, pour cpt > 1, ta formule marche efefctivement. Note quand même que faire le + cpt réserve plus de caractères qu'il n'en faut. Peut-être as-tu fait exprès, sachant que cpt caractères sont toujours suffisants pour afficher le nombre cpt+1 (si cpt > 1...), mais il faudrait au moins le metre en commentaire.
La ligne est donc suffisante; mais il ne faut pas oublier qu'on prend plus de place mémoire que nécessaire...
Par flemme, on va dire que la réécriture de ce code pour ne pas prendre plus de mémoire que nécessaire est laissé en exercice au lecteur ;)
Par ailleurs, il serait bon de vérifier que malloc n'a pas échoué, à moins de tenir à tester les comportements indéfinis de ton implémentation ;)
Et il faudrait aussi noter que le "32" pour le buffer du sprintf est purement arbitraire (très largement suffisant, mais juste pour noter en commentaire dans le code).
[^] # Re: ma solution
Posté par Cereal Killer . Évalué à 1.
Pour les tests, c'était plus de la flemme qu'autre chose.
Pour fscanf, je l'utilise très rarement (jamais ?) donc je connais pas très bien son comportement, j'avoue ne pas avoir poussé les tests, j'me suis contenter de son exemple. J'avais mis un fgets, mais yavais de pb :/
Pour le reste, j'en prend note.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.