Passage de valeurs de fonction a fonction

[Résolu]
Signaler
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007
-
Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008
-
salut à tous,

Je débute en c++ et je n'arrive pas à faire le truc de base. En fait dans ma fonction principale je rentre le nom d'un fichier puis je dis d'appliquer la fonction read (fonction perso) à ce fichier. Dans cette fonction read les données sont stockées sous forme de tableau.

Question : Comment réutiliser ce tableau dans la fonction principale ??

Merci de votre aide.
Ci-dessous le code en question.
<hr size="2" width="100%" />#include <cstdio>
#include
#include <fstream>

using namespace std;

char read (ifstream & f);

int main ()
{
    ifstream file("test.txt", ios::binary); //flux d'entrée
    read(file);
   
   
    system ("PAUSE");
    return EXIT_SUCCESS;
}

char read (ifstream & f)
{
     //taille du fichier d'entrée
    f.seekg(0, ios::end);
    int sizeOfArray = f.tellg();
    f.seekg(0, ios::beg);
   
    char array[sizeOfArray]; //tableau de la taille du fichier
   
    //lecture
    for (int position = 0; position < sizeOfArray; position++)
    {
        char valeur = f.get();
        array[position] = valeur;
        cout << position << " : " << array[position] << endl;
    }
}

17 réponses

Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008

Je reconnais que gérer la mémoire dans la fonction appelante est
plus sûr surtout si plein d'objets doivent être alloués (dans une
boucle par exemple). Cependant dans de nombreux cas on ne peut pas
faire autrement (par exemple si l'allocation fait appel à un
constructeur qui initialise des paramètres) et ici je ne crois pas que
cela soit primordial. Mais cela reste mon avis, après tout il n y a pas
de vérité générale.


Par ailleurs s'il s'agit d'améliorer le code, le mieux aurait
certainement été de ne pas déclarer le fichier dans main(), mais dans
read(). Mais la encore cela dépend de ce que tu fais après de ton
fichier.


Charger le contenu du fichier dans un tableau: pourquoi pas? après tout
nous ne savons pas ce que souhaite faire binoua, peut-être veut-il
stocker une image dans un tableau pour pouvoir y effectuer des
traitements beaucoup plus rapidement (je donne un exemple au hasard).
Si bimoua souhaite comme il dit modifier des données du fichier, il est
plutot judicieux de les faire en mémoire vive (+cache) que de faire
travailler le disque dur.


Merci pour l'idée du fichier en mode exclusif.
Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008

Tu peux allouer ton tableau array dans la fonction read:

array = new char[sizeOfArray];


Tu le retournes à la fin de read() par return array. Du coup read() a pour type char * un non char.

Dans main: char * main_array = read(file);


Tu peux aussi déclarer ou allouer ton tableau dans main et le passer par référence à read().
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

J'ai un plantage au moment de la compilation sur la commande array = new char[sizeOfArray] à savoir que array n'est pas déclaré. Je comprend pas bien étant donné que cette ligne est une déclaration non ?

Pour déclarer mon tableau dans main et le passer à read j'ai un pb : pour déclarer un tableau il faut avoir sa taille. Or ici la taille du tableau est définie dans read. Est-ce que je suis obligé de faire une fonction "taille" séparée ?
Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008

Non ce nest pas une déclaration mais une allocation.

Tu dois d'abord écrire char * array;


Effectivement, la taille est définie dans read, donc seule la premiere
solution marche à savoir une allocation dans read et main récupère le
pointeur sur le tableau:


main()

{

 ...

 char * array;

 array = read(file);

 ...

}
Messages postés
354
Date d'inscription
mercredi 18 décembre 2002
Statut
Membre
Dernière intervention
24 mars 2011
1
THEwarrior333, tu pourrais au moins lui dire que le pointeur renvoyé par la fonction doit etre liberé quand on en a plus besoin, sinon je t'explique pas les fuites mémoires !

Il vaut mieux allouer le tableau de le main et le passer à read, l'appelant doit maitriser la mémoire.

Le problème ici est que la lecture du fichier n'est pas appropriée. Imagine que le fichier passé à read fait 2Go ??? La mémoire explose !

Une meilleure solution est de garder le fichier ouvert et de naviguer à l'interieur selon les besoins ... Enfin tour ça depend de ce que tu veux faire.

D@runia
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

A priori je n'aurais pas ces problème de mémoire. Autrement, mon code a cette tête maintenant :


#include <cstdio>

#include

#include <fstream>


using namespace std;


char read (ifstream & f);


int main ()

{

    ifstream file("test.txt", ios::binary); //flux d'entrée

    char * array;

    array = read(file);

       

    system ("PAUSE");

    return EXIT_SUCCESS;

}


char read (ifstream & f)

{

     //taille du fichier d'entrée

     f.seekg(0, ios::end);

     int sizeOfArray = f.tellg();

     f.seekg(0, ios::beg);

    

     //lecture

     array = new char[sizeOfArray];

     for (int position = 0; position < sizeOfArray; position++)

     {

         int valeur = f.get();

         array[position] = valeur;

        

         cout << position << " : " << array[position] << endl;

     }

     return array;

}

J'ai 2 erreurs de compilation :
<li>invalid conversion from 'char' to 'char*' à la ligne array read(file)</li><li>'array' undeclared à la ligne array new char[sizeOfArray]</li>
Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008

C'est vrai je n'ai pas dit qu'il fallait libérer la mémoire après,
toutes mes excuses J'imaginais que binoua connaissait l'allocation et
que sa question ne concernait que la maniere de passer un tableau en
parametre:

delete [] array dans le main permet de détruire le tableau. N'oublies
pas les [] qui correspondent à la désallocation d'un tableau d'objets
et non d'un seul objet.


Sinon l'allocation peut tres bien se faire dans read, je ne vois pas le
probleme. Il y a des tas de fonctions qui effectuent l'allocation
elles-mêmes et c'est au programmeur de faire gaffe à bien gérer la
mémoire. (cf DirectX par exemple.)


binoua: ta fonction read ne doit plus etre du type char mais char * car elle renvoie un char *.

char * read(ifstream & f);


et tu as oublié encore de déclarer array dans read():

char * array;

array = new char[sizeOfArray]];
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

youpi ça marche !!!

Oui en fait je savais pour les histoires de mémoire mais comme vous avez pu le constater, je débute avec les pointeurs !

Encore merci
++
Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008

De rien.


Une question que je me posais (peut-être le sais-tu Darunia):

est-ce une bonne idée d'effectuer la boucle de remplissage du tableau
avec comme critère d'arrêt la taille du fichier déterminée en début de
fonction?

Car si le fichier est modifié pendant la lecture, ca risque de planter.
Alors que si la boucle est effectuée tant que le curseur n'est pas en
fin de fichier on n'a pas ce problème:


position = 0;

int valeur;

while( f.good() )
{

    valeur = f.get()
    array[position] = valeur;       
    cout << position << " : " << array[position] << endl;

    position++;
}
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

oui ce que tu dis est vrai mais d'un autre côté si il faut rajouter

if (position > taille) {break}

parce que sinon tu risques de rentrer trop de données par rapport à la capacité du tableau.
Donc dans un soucis de simplicité je suis partis du principe que le fichier ne serait pas modifié pendant la lecture et j'ai donc fait la boucle que l'on connait.
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

Au passage petite question supplémentaire : y a-t-il un moyen de retourner également la valeur sizeOfArray dans read.
Parce que c'est problématique n'est ce pas que ma fonction read soit char* et que je veuille également retourner une valeur chiffrée ?
Messages postés
192
Date d'inscription
vendredi 19 mars 2004
Statut
Membre
Dernière intervention
30 janvier 2008

Deja tu as raison il faut tester position>taille.


Pour ta question du retour d'une valeur supplémentaire:


il y a plusieurs façons de considérer ce cas et comme l'a dit Darunia, cela dépend de ce que tu veux faire.

- Une possibilité est d'abandonner l'idée d'une fonction read et de tout mettre dans le main.

- Tu peux aussi allouer ton tableau dans le main, sa taille y étant calculable puisque tu y déclares ton fichier:
f.seekg(0, ios::end);
int sizeOfArray = f.tellg();
f.seekg(0, ios::beg);

est alors à placer dans le main. A ce moment la, il te suffit de passer
ton tableau à read par passage de pointeur ou par référence:
dans main:
...
read(file, array);
...
delete [] array;


et ta fonction read():

void read(ifstream & f, char * & array)
{

    // Tu continues de manipuler des array[position]

}


ou encore:
dans main:
...
read(file, &array);
...
delete [] array;


et ta fonction read():

void read(ifstream & f, char ** array)
{

    // Tu manipules des (*array)[position]

}


- Autre possibilité inutile ici mais qui peut te servir dans d'autres
cas: passer à read() par référence/pointeur une structure contenant ton
tableau et sa taille (et plein d'autres infos si tu veux). Cette
structure est modifiée par read et comme tu l'as passée par
référence/pointeur, au retour de read, la structure est bien modifiée,
il ne s'agit pas d'une copie.
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

ok merci je vais voir ce qui est le mieux pour mon application
Messages postés
354
Date d'inscription
mercredi 18 décembre 2002
Statut
Membre
Dernière intervention
24 mars 2011
1
binoua -> "a priori" tu n'as pas de problème de pointeur. Peut etre parce que tu es encore en mode debug (si tu bosses sous visual studio). Quand tu vas passer en mode release ... patatra !

THEWarrior333 -> Il vaut mieux que ce soit l'appelant qui maitrise la mémoire. Imagine si toutes les fonctions se prennent 1 ou 2 Mo dans le heap à chaque appel, il est impossible pour le programmeur de savoir si il va etre ammené a manquer de mémoire ou non.

C'est vrai que dans ce cas c'est un peu spécial, car on ne peut trop savoir quelle taille fait le fichier avant de l'avoir ouvert. Mais je pense que ça veut dire aussi que le traitement a été mal pensé. Normalement, une lecture de fichier réprésente des données plus structurées qu'un simple tableau.

Pour le probleme de modification de fichier pendant la lecture, le plus simple est encore d'ouvrir en fichier enmode exclusif.

Je pense aussi que c'est une mauvaise idée de lire le fichier octet par octet, tu devrais le lire par bloc de 256 ou 512 octets par exemple, question de rapidité.

[mailto:D@runia D@runia]
Messages postés
8
Date d'inscription
dimanche 11 mars 2007
Statut
Membre
Dernière intervention
21 juin 2007

je bosse sous dev-c++.

en fait ce programme est pensé pour des fichiers de très petite taille (max 20 Ko). C'est pour ça que je ne me suis pas posé les question de mémoire.
Lire le fichier par octet me sert parce que par la suite je voudrais modifier les octets 1 par 1. S'il y a une méthode plus simple et/ou plus adaptée n'hésitez pas à me tenir au courant !
Messages postés
354
Date d'inscription
mercredi 18 décembre 2002
Statut
Membre
Dernière intervention
24 mars 2011
1
D@runia
Messages postés
354
Date d'inscription
mercredi 18 décembre 2002
Statut
Membre
Dernière intervention
24 mars 2011
1
D@runia