Quelqu´un peut m´expliquer pourquoi j´ai tjrs du garbage en fin de ligne lorsque je lis un fichier texte ?
J´ai essayé la méthode fopen, j´ai essayé _open et j´ai essayé de créer un stream ( ce qui me semble être la méthode la plus intéressante jusqu´à maintenant) et dans tous les cas c´est pareil, je récupère le contenu du fichier et j´ai une tale de lettres débiles et étranges en fin de ligne.
Le plus confusionnant dans tout ça c´est que le problème ne semble se produire que si le fichier lu contient des caractères avec des accents
.
Voici mon code ( tronqué pour ne montrer que l´essentiel
) :
---------------
// Les libs nécessaires pour que ça marche ![]()
int readTheFile()
{
struct stat fileInfo;
if(stat("fichier.txt", &) ! = 0)
{
// Le fichier n´a pas été trouvé
return 0;
}
char fileContent[fileInfo.st_size];
ifstream fileStream("palmtree.ini", ios::in);
fileStream.read(fileContent,fileInfo.st_size);
printf(fileContent);
return 1;
}
---------------
fichier.txt:
Maudit que ça marche jamais
stdout.txt:
Maudit que ça marche jamaisw…@
---------------
Merci de votre aide... ça me fait virer fou ce truc
.
Et merde, excusez moi, remplacez la ligne
ifstream fileStream("palmtree.ini", ios::in);
par
ifstream fileStream("fichier.txt", ios::in);
Dans le but de vous montrer mon code ( de façon + claire), j´ai voulu écrire fichier.txt plutôt que palmtree.ini partout et j´ai malheureusement oublié de faire le changement à cette ligne...
Donc si jamais vous trouvez une réponse à mon problème, merci bien d´men faire part ![]()
bah je sais pas si tu te souviens comment fonctionne les chaines de caractères ?
-> faut les terminer par le caractère nul(0) . ..
Herm... nah c´est les premières nouvelles que j´ai de ça...
La solution serait donc... ?
bin de rajouter le caractère 0 à la fin de tes données ! sinon le printf affichera le contenu de ton buffer jusqu´à rencontrer le premier 0 qu´il trouve en mémoire :
( ...)
char fileContent[fileInfo.st_size + 1];
ifstream fileStream("palmtree.ini", ios::in);
fileStream.read(fileContent,fileInfo.st_size);
fileContent[fileInfo.st_size] = 0;
printf(fileContent);
( ...)
euh j´ai pas fait gaffe sur le moment mais c´est pas très " clean" de déclarer la taille de ton buffer à partir d´une variable . .. enfin si ca marche tant mieux ![]()
Eh beh ça fonctionne... et dire que ça fait des semaines que je fais des recherches pour ça...
Mais dis-moi, pourquoi est-ce que c´est pas
fileContent[fileInfo.st_size + 1] = 0;
? ??
C´est ce que j´ai tenté de faire après avoir lu ta première réponse et, évidemment, ça ne fonctionne pas.
J´ai d´la théorie à revoir moi
.
bin parceque les indices de tableaux commencent à partir de 0 . .. donc quand tu déclares :
char fileContent[N]
les indices vont de 0 à N-1 ( ce qui correspond bien à N valeurs)
ton fichier fait apparemment fileInfo.st_size donc il te faut allouer 1 caractère de plus pour le 0 de terminaison
Hmmm j´ai beaucoup de théorie à revoir là
Je déclare fileContent[fileInfo.st_size], j´obtiens une tableau de 0 jusqu´à la grosseur de mon fichier ( donc de 0 à 27 dans le cas de ´Maudit que ça marche jamais´)
Ce qui me donne déjà un caractère de plus où mettre le zéro soit fileContent[fileInfo.st_size] = 0; ou, dans ce cas-ci, fileContent[27] = 0;.
À quoi servirait le + 1 dans
char fileContent[fileInfo.st_size + 1];
?
Merci de ton aide soit dit en passant, même si je pige ± la logique, ça fonctionne
.
hmm t´y es presque mais c´est pas encore tout à fait ca . ..
le fait de rajouter +1 indique qu´il faut réserver un caractère de plus pour ta chaine sinon lorsque tu écriras le 0 ca va écraser des données en mémoire ( à priori l´octer juste après ton tableau . ..)
Donc il faut obligatoirement déclarer avec le +1
char fileContent[fileInfo.st_size + 1];
si tu fais ca :
fileContent[fileInfo.st_size] = 0;
sans le +1, tu vas écraser l´octet suivant le tableau, car je te le rappelle les données s´arrêtent à fileInfo.st_size-1 ! ( d´où le +1 dans la déclaration)
si ca peut t´aider essaie de te faire le dessin du tableau avec N valeurs et regarde ce qu´il se passe pour les indices, le dernier caractère et le fait de rajouter le 0 à la fin.
A méditer . ..
Sur ce, je vais faire dodo ![]()
Je vois donc en gros il faut toujours laissé les deux dernières " cases" d´une chaîne de caractère " libre", une pour contenir un 0 et une pour contenir l´octet qui termine la chaîne.
Eh bien parfait, merci beaucoup, ça vient de me sortir d´la p´tite flaque merdique dans laquelle je trempais depuis un bout
.
Il faut admettre que les p´tits gars qui ont inventé le C++ ce sont donnés beaucoup de mal pour que tout soit compliqué
.
Merci encore !
" une pour contenir un 0 et une pour contenir l´octet qui termine la chaîne"
non 1 seule ! le 0 et l´octet qui termine la chaine sont les mêmes . ...
lorsque tu veux un chaine de taille N il te faut déclarer N+1 caractères ( N caractères + le caractère de fin qui est le carctère 0, ou NULL ou ´\0´ enfin ce sont toutes les mêmes valeurs)
00 | M
01 | A
02 | U
03 | D
04 | I
05 | T
06 |
07 | Q
08 | U
09 | E
10 |
11 | Ç
12 | A
13 |
14 | M
15 | A
16 | R
17 | C
18 | H
19 | E
20 |
21 | J
22 | A
23 | M
24 | A
25 | I
26 | S
------------
27 | NULL
fileInfo.st_size == 27
hmmm il me semble qu´il soit inutile de déclarer avec + 1
je répète une dernière fois... après je m´énerve ! hein!!
quand tu écris dans fileContent[27], il s´agit du 28e caractère ! ! la place en mémoire pour ce caractère n´est pas allouée si tu déclares :
char fileContent[fileInfo.st_size];
puisqu´en faisant ca tu réservres 27 caractères pas un de plus pas un de moins !
donc le dernier caractère accessible sera :
fileContent[26] ! !
L´exemple parfait du gars qui aurait dû commencer par le C ; )
regarde Tech
szString[0]
szString[1]
szString[2]
0,1,2... ça fait 3 éléments ! !! alors que le dernier élément accessible est szString[2] ! !! comme dirait Jean-Claude Vandamme : " it´s magic"
Moi je veux bien vous croire mais vous allez devoir m´expliquer pourquoi mon prog marche quand je compte à " ma façon"
.
Hmmm j´en viens à la conclusion que j´écrivais mon 0 au-delà de mon tableau... Je vois rien d´autre. Mais si c´est bien l´cas, est-ce que ça veut dire que j´ai courru le risque d´aller écraser de l´information en mémoire appartenant à un autre prog
?
" Mais si c´est bien l´cas, est-ce que ça veut dire que j´ai courru le risque d´aller écraser de l´information en mémoire appartenant à un autre prog "
D´un autre prog non mais du tien oui!
Alors il se trouve que ton compilateur est gentil car tu as certainement compilé ton programme en version Debug, et le bug a pu ne pas apparaître et il faut dire qu´un dépassement de buffer d´un seul octet ca se voit pas ou ca peut ne rien faire du tout au niveau du programme ( mais c´est TRES TRES risqué et pas du tout propre).
Par contre en Release, ou si tu avais écris plusieurs octets hors des limites bin là tu aurais eu droit à un beau plantage de ton application.
Donc que tu n´arrives toujours pas à comprendre pourquoi tu as depassé je trouve qu´un dessin s´impose ! !
Relis bien les derniers posts.
Il y a d´autres raisons possibles pour que ton programme ai fonctionné sans problème mais ca devient un peu plus compliqué ( ca peut être une histoire d´alignement des données).
Pour vérifier le problème tente de compiler ca :
void main()
{
char Buffer[7] = " bonjour";
}
on est bien d´accord que la chaine " bonjour" est de longueur 7 ? ok ? Tu verras ce que te dis le compilateur . .. ( il lui manque 1 octet pour qu´il puisse y mettre le caractère NULL.
Maintenant testes ca :
void main()
{
char EcraseMoi = ´A´;
char Buffer[8] = " bonjour";
printf("caractere = %c / ASCII = %d\n",EcraseMoi,EcraseMoi);
printf("%s\n",Buffer);
strcpy(Buffer,"bonjours");
printf("caractere = %c / ASCII = %d\n",EcraseMoi,EcraseMoi);
}
et tires en les conclusions que tu veux . ...