Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

GetLine corrompt mes affectations..

5 réponses
Avatar
Yann Laviolette
Bonjour!

J'utilise C++ Builder 6. J'ai des fichiers de configuration qui sont lus
pour obtenir le chemin des fichiers à compresser. Sauf que le problème
arrive toujours seulement quand j'utilise GetLine. Une fois que j'ai fait un
GetLine, je ne peux plus faire t'affectation car lors de l'affectation,
c'est la valeur du buffer pour la lecture qui est affectée même si c'est
loin d'être ce que le code dit!!!

Je ne sais pas si quelqu'un à eu le même problème que moi, mais je ne sais
vraiment plus quoi faire, j'ai chercher beaucoup mais sans succès... J'ai
mis une copie de mon code, et j'ai attirer l'attention d'où on se rend
compte du problème...

Est-ce que quelqu'un pourrait m'aider? Ça serait très gentil!

Merci beaucoup à l'avance!

Yann Laviolette

----------------------------------------------------------------------------
------------
Code:

AnsiString DateJour;
DateJour = DateToStr(Date());

// Lecture du fichier de destination
ifstream LectureDestination("c:\\destination.bpt", ios::in);

if(!LectureDestination){
ShowMessage("Le fichier destination n'a pas pu être
ouvert!");
}

while(LectureDestination >> pathDestination){
}

//----------------------------------

// Lecture du fichier source
ifstream LectureSource("c:\\source.bpt", ios::in);

if(!LectureSource){
ShowMessage("Le fichier source n'a pas pu être ouvert!");
}

char pathSource[255]; // Chemin de la source
char NomFichierDestination[255]; // Nom du fichier de a la
destination

char * buffer = "";

while(LectureSource.getline(buffer, 1000)){
AnsiString PathFichierSource = buffer;
AnsiString NomFichierSource = buffer;


// Isole les données voulues du buffer
PathFichierSource =
PathFichierSource.SubString(PathFichierSource.Pos('<')+1,
(PathFichierSource.Pos('>')- PathFichierSource.Pos('<')-1));
NomFichierSource =
NomFichierSource.SubString(NomFichierSource.Pos('[')+1,
(NomFichierSource.Pos(']') - NomFichierSource.Pos('[')-1));

AnsiString sPathDestination = pathDestination;
zfArchive->FileName = sPathDestination + DateJour + " - "
+ NomFichierSource + ".zip";

###########################################################
---> LE PROBLÈME ARRIVE ICI...
ShowMessage(zfArchive->FileName);
---> zfArchive contient la valeur de sPathDestination + DateJour + sauf que
la valeur de NomFichierSource est corrompu par la valeur du buffer et ".zip"
aussi est corrompu par la valeur du buffer...
###########################################################

zfArchive->OpenArchive();
zfArchive->BaseDir = PathFichierSource;
zfArchive->AddFiles("*.*");
zfArchive->CloseArchive();
}
}

5 réponses

Avatar
Loïc Joly
Yann Laviolette wrote:

Code:


Ton code ne ressemble pas trop à du C++ classique. Et il utilise des
extentions spécifiques à Borland. Ce n'est pas trop ton problème ici,
mais ça gène un peu la lecture sur un newsgroup.

[...]
char * buffer = "";

while(LectureSource.getline(buffer, 1000))


Le problème est dès ici :
Tu dois fournir à getline un tableau de caractères, pas un pointeur non
alloué. Donc, ici tu corromps la mémoire, et comme c'est typique dans ce
genre de cas, l'erreur ne ce voit que plus tard.

J'aurais réécrit ton programme dans le style (code non testé) :


ifstream source("c:/source.bpt");
if(!source){
ShowMessage("Le fichier source n'a pas pu être ouvert!");
}
string currentLine;
while (getline(source, currentLine))
{
// fait quelquechose
}

Remarques :
Tu n'as pas besoin de préciser ios::in pour des istream.
Evite d'utiliser des char*, les string, c'est plus simple.
Evite d'utiliser des ansi_string, les string, c'est standard.
L'opérateur >> s'arrête aux espaces, donc si pathDestination contient
"c:/Program files/", le début de ton code ne marchera pas.
Ton code d'extraction d'information n'est pas blindé contre des fichiers
qui ne seraient pas au bon format.

--
Loïc

Avatar
Pierre Maurette
Loïc Joly a écrit:
[...]
Ton code ne ressemble pas trop à du C++ classique. Et il utilise des
extentions spécifiques à Borland. Ce n'est pas trop ton problème ici,
mais ça gène un peu la lecture sur un newsgroup.
[...]

Remarques :
Tu n'as pas besoin de préciser ios::in pour des istream.
Evite d'utiliser des char*, les string, c'est plus simple.
Evite d'utiliser des ansi_string, les string, c'est standard.
En fait, je me demande si Yann ne devrait pas choisir plus clairement

entre les approches "Borland" VCL (AnsiString, etc...) et "classique"
STL (ifstream, std::string, etc...), voire "plain old C" (char*).
La dernière approche est particulière, en ce sens qu'elle est
incontournable (en STL ou en VCL, peu importe), par exemple dès qu'on
veut utiliser des API Windows non encapsulées par la VCL.
L'environnement C++Builder6 permet toutes ces approches, je fais par
exemple de l'ANSI C90 en mode console (pour utiliser CodeGuard, qui
est le seul outil de ce type que je possède).

L'opérateur >> s'arrête aux espaces, donc si pathDestination contient
"c:/Program files/", le début de ton code ne marchera pas.
Ton code d'extraction d'information n'est pas blindé contre des fichiers
qui ne seraient pas au bon format.
Si Yann a le contrôle du format de ses fichiers de configuration, il

peut utiliser TIniFile, c'est fait pour ça.
Bien entendu, c'est moins portable et moins pédagogique ...
--
Bonne journée,
Pierre

Avatar
Horst Kraemer
"Yann Laviolette" wrote:


char * buffer = "";


Remplacer par

char buffer[1000];

ou bien par

char * buffer = new char[1000];
...
delete [] buffer;


Par char * p = ...; tu ne réserves pas de la mémoire utilisable comme
tampon. Primo, ="" ne réserve qu'un seul byte (qui contient 0) et
secundo la mémoire vers laquelle un pointeur initialisé par

p = "toto";

pointe ne peut pas être changée. Il faut que tu traites un pointeur
initialisé par

p = ".......";

comme s'il était déclaré

const char * p;

Le fait qu'on a le droit d'initialiser un pointeur tu type char* par
="....." bien qu'il soit interdit de changer la chaine vers laquelle
il pointe est un truc introduit par compatibilité au langage C.

--
Horst

--
Lâche pas la patate!

Avatar
Yann Laviolette
Merci à tous!

Vous êtes vraiment les meilleurs! En passant Loïc, je vais prendre en compte
les conseils que tu m'a dit mais pour la fonction getline, je ne peux pas
utiliser de string, il attend un tableau de caractère... Je vais modifier
tous les autres points que tu m'a dit!

Merci beaucoup à tous!

Yann Laviolette




"Yann Laviolette" a écrit dans le message
de news:GPDQc.10156$
Bonjour!

J'utilise C++ Builder 6. J'ai des fichiers de configuration qui sont lus
pour obtenir le chemin des fichiers à compresser. Sauf que le problème
arrive toujours seulement quand j'utilise GetLine. Une fois que j'ai fait
un

GetLine, je ne peux plus faire t'affectation car lors de l'affectation,
c'est la valeur du buffer pour la lecture qui est affectée même si c'est
loin d'être ce que le code dit!!!

Je ne sais pas si quelqu'un à eu le même problème que moi, mais je ne sais
vraiment plus quoi faire, j'ai chercher beaucoup mais sans succès... J'ai
mis une copie de mon code, et j'ai attirer l'attention d'où on se rend
compte du problème...

Est-ce que quelqu'un pourrait m'aider? Ça serait très gentil!

Merci beaucoup à l'avance!

Yann Laviolette

--------------------------------------------------------------------------
--

------------
Code:

AnsiString DateJour;
DateJour = DateToStr(Date());

// Lecture du fichier de destination
ifstream LectureDestination("c:destination.bpt", ios::in);

if(!LectureDestination){
ShowMessage("Le fichier destination n'a pas pu être
ouvert!");
}

while(LectureDestination >> pathDestination){
}

//----------------------------------

// Lecture du fichier source
ifstream LectureSource("c:source.bpt", ios::in);

if(!LectureSource){
ShowMessage("Le fichier source n'a pas pu être ouvert!");
}

char pathSource[255]; // Chemin de la source
char NomFichierDestination[255]; // Nom du fichier de a la
destination

char * buffer = "";

while(LectureSource.getline(buffer, 1000)){
AnsiString PathFichierSource = buffer;
AnsiString NomFichierSource = buffer;


// Isole les données voulues du buffer
PathFichierSource > PathFichierSource.SubString(PathFichierSource.Pos('<')+1,
(PathFichierSource.Pos('>')- PathFichierSource.Pos('<')-1));
NomFichierSource > NomFichierSource.SubString(NomFichierSource.Pos('[')+1,
(NomFichierSource.Pos(']') - NomFichierSource.Pos('[')-1));

AnsiString sPathDestination = pathDestination;
zfArchive->FileName = sPathDestination + DateJour + " -
"

+ NomFichierSource + ".zip";

###########################################################
---> LE PROBLÈME ARRIVE ICI...
ShowMessage(zfArchive->FileName);
---> zfArchive contient la valeur de sPathDestination + DateJour + sauf
que

la valeur de NomFichierSource est corrompu par la valeur du buffer et
".zip"

aussi est corrompu par la valeur du buffer...
###########################################################

zfArchive->OpenArchive();
zfArchive->BaseDir = PathFichierSource;
zfArchive->AddFiles("*.*");
zfArchive->CloseArchive();
}
}




Avatar
Cyrille Karmann
"Yann Laviolette" disait:
Merci à tous!

Vous êtes vraiment les meilleurs! En passant Loïc, je vais prendre en
compte les conseils que tu m'a dit mais pour la fonction getline, je ne
peux pas utiliser de string, il attend un tableau de caractère...


La méthode std::ifstream::getline( ) attend un char*, certes, mais
std::getline() définie dans <string>, elle, permet d'utiliser
std::string.

--
Cyrille