[C++] lecture de fichier pb d'indice

Fermé
chreks - 4 juin 2007 à 00:38
 chreks - 4 juin 2007 à 14:15
bonjour,
j'ai besoin de votre aide s'il vous plait. je suis un débutant en C++ et je galère pour résoudre un problème concernant la récupération de données à partir d'un fichier.

en fait mon fichier est une matrice creuse qui se présente de cette facon :
0: (1,0) (2,0) (3,5) (4,2) (5,8) (6,3) (7,2) (8,4)
1: (0,0) (2,0) (3,8) (4,4) (5,1) (6,7) (7,5) (8,3)
2: (0,0) (1,0) (3,7) (4,4) (5,2) (6,2) (7,3) (8,6)
3: (4,0) (5,0) (0,5) (1,8) (2,7) (6,2) (7,6) (8,8)
4: (3,0) (5,0) (0,2) (1,4) (2,4) (6,3) (7,9) (8,1)
5: (3,0) (4,0) (0,8) (1,1) (2,2) (6,6) (7,7) (8,9)
6: (7,0) (8,0) (0,3) (1,7) (2,2) (3,2) (4,3) (5,6)
7: (6,0) (8,0) (0,2) (1,5) (2,3) (3,6) (4,9) (5,7)
8: (6,0) (7,0) (0,4) (1,3) (2,6) (3,8) (4,1) (5,9)

c'est une matrice dont je récupere les données avec une structure map pour la matrice et donc j'aimerais faire des calculs sur cette matrice .

Chaque ligne d'un fichier correspond à une ligne de la matrice et se
présente sous la forme :
<n°ligne>:\tab(<n°colonne>,<coefficient>)\tab(<n°colonne>,<coefficient>)\tab(<n°colonne>,<coefficient>)...

mon programme est le suivant et j'ai petit problème d'indice que je n'arrive pas à voir, et qui me bloke tous les calculs qui suivent!

#include <fstream>
#include <iostream>
#include <map>
#include <list>
#include <string>
#include <vector>
#include <stdlib.h>
#include <math.h>



extern "C"{
#include <stdio.h> // sscanf
#include <string.h>
}



template <typename Tkey1,typename Tkey2,typename Tdata>
class sparse_matrix_t : public std::map<Tkey1,std::map<Tkey2,Tdata> >{
public:
    typedef std::map<Tkey2,Tdata> row_t;
    typedef std::map<Tkey1,row_t> matrix_t;
    
// Recuperer une valeur
    inline Tdata get(const Tkey1 & k1,const Tkey1 & k2) const {
	typename matrix_t::const_iterator f1(this->find(k1));
	if(f1 == this->end()) return Tdata();
	const row_t & r = f1->second;
	typename row_t::const_iterator f2(r.find(k2));
	if(f2 == r.end()) return Tdata();
	return f2->second;
    }
    
};


// Une classe de matrice creuse indexée (les deux clés sont des entiers positifs)
template <typename Tdata>
class indexed_sparse_matrix_t : public sparse_matrix_t<unsigned,unsigned,Tdata>{
protected:
    std::size_t nb_row;
    std::size_t nb_col;
public:
// Le constructeur
    indexed_sparse_matrix_t():
	sparse_matrix_t<unsigned,unsigned,Tdata>(),
	nb_row(0),nb_col(0)
	{}
    
// Affecter une valeur
    inline void set(const unsigned & k1,const unsigned & k2,const Tdata & d){
	(*this)[k1][k2] = d;
	if(k1 > nb_row) nb_row = k1+1;
	if(k2 > nb_col) nb_col = k2+1;
    }
    
// Recuperer le nombre de ligne
    inline const std::size_t & get_nb_row() const{
	return nb_row;
    }
    
// Recuperer le nombre de colonne
    inline const std::size_t & get_nb_col() const{
	return nb_col;
    }
};

// Afficher la matrice (operateur <<)
template <typename Tstream,typename Tdata>
Tstream & operator<<(Tstream & out,const indexed_sparse_matrix_t<Tdata> & m){
    const std::size_t & nb_row = m.get_nb_row();
    const std::size_t & nb_col = m.get_nb_col();
    for(std::size_t i=0;i<nb_row;++i){
	for(std::size_t j=0;j<nb_col;++j) out << m.get(i,j) << '\t';
	out << std::endl;
    }
    return out;
}


bool lire_ligne(const std::string & line,indexed_sparse_matrix_t<int> & matrix){
    const char *str = line.c_str();
    char *buffer = (char *)malloc(sizeof(char)*(line.size()+1));
    strcpy(buffer,str);
    unsigned ligne=0;
    unsigned colonne=0;
    int valeur;
    char *sep = "()";
    char *maillon, *brkt;

    if(sscanf(buffer," %i : ",&ligne)!=1){
        free(buffer);
        return false;
    }
    strtok_r(buffer,":", &brkt);
//  std::cout << " :  >> buffer = " << buffer << std::endl;
//  std::cout << " :  >> brkt = " << brkt << std::endl;
    for (maillon = strtok_r(brkt, sep, &brkt); maillon; maillon = strtok_r(NULL, sep, &brkt)){
	//   printf("maillon = [%s] \n", maillon);
        int res = sscanf(maillon,"%i,%d ",&colonne,&valeur);
        if(res == 2) matrix.set(ligne,colonne,valeur);
    }

    free(buffer);
    return true;
}


bool lire_fichier(const char *filename,indexed_sparse_matrix_t<int> & matrix){
    std::ifstream f(filename);
    if (f){
        std::cout << "Lecture de [" << filename << ']' << std::endl;
        std::string line;
        for(unsigned noline=1;std::getline(f,line);++noline){
            if(line.empty()) continue;
            if(!lire_ligne(line,matrix)){
                std::cerr << "Erreur : ligne invalide : ligne " << noline << ": "
                    << line << std::endl;
                return false; // on arrê la lecture
            }
        }
        return true; // lecture ok
    }
    std::cerr << "Ne peut ouvrir [" << filename << ']' << std::endl;
    return false; // le fichier n'existe pas ou ne peut êe ouvert
}


int main(){
// Initialiser la matrice
    typedef indexed_sparse_matrix_t<int> matrix_t;
    matrix_t m;
   
    const char *filename="test.txt";

      // Lire le fichier
    if(!lire_fichier(filename,m)){
        std::cerr << "Le contenu du fichier [" << filename << "] est invalide " << std::endl;
        return 1;
	}

// Afficher la matrice
    

    std::cout << m << std::endl;

   const std::size_t & nb_row = m.get_nb_row();

std::cout <<"nb de lignes" <<nb_row<<std::endl;

    return 0;
}

résultat : 

./a.out
Lecture de [test.txt]
0       0       0       5       2       8       3       2
0       0       0       8       4       1       7       5
0       0       0       7       4       2       2       3
5       8       7       0       0       0       2       6
2       4       4       0       0       0       3       9
8       1       2       0       0       0       6       7
3       7       2       2       3       6       0       0
2       5       3       6       9       7       0       0

nb de lignes8

" normalemen c une matrice symetrique"


à l'exécution j'obtient une matrice ou a l'affichage il manque la derniere ligne et la derniere colonne, j'ai trouvé ca bizare, j'ai regardé la valeur de nb_row pr connaitre la nombre de ligne ( = 8 dans ce cas de fichier alors ke ca devrai etre 9 jpense ) , je pense qu'il y une ligne en moins !! a moins que j'ai mal compris le fonctionnement du programme é commen nb_row marchait.
de plus dans les boucles d'affcihage kan je rajoute un" nb_row+1 " je vois afficher les lignes et colonnes manquantes mais je pensais ke cétait incorrecte parckil y a un terme en +!
alors SVP aidez moi c urgen!!
merci d'avance.
A voir également:

2 réponses

le nb_row te donne l'indice du tableau des lignes, mais en C/C++ les
indices commencent à 0 donc la taille est de 9! (8+1 pour l'indice 0 =9)
Ensuite tu ferais mieux de lire caractère par caractère dans un fichier
aussi simple d'après moi, mais c'est personnel
<n°ligne>:\tab(<n°colonne>,<coefficient>)\tab(<n°colonne>,<coefficient>)\tab(<n°colonne>,<coefficient>)...
procedure lire_fichier :
boucle jusqu'à la fin du fichier avec dans la boucle:
-lecture du n°de colone jusqu'au ':'
- appel à lire ligne
procedure lire_ligne:
boucle jusqu'au caractère fin de ligne ou une erreur (mauvais caractère)
-lecture jusqu'au '('
-lecture de valeur jusqu'au ','
-lecture de valeur jusqu'au ')'
tu peux aussi être plus exigent et vérifier vraiment pour avoir un tab mais si il y aura un espace tu pourras plus lire le fichier :(
Avec ça tu auras tout ton fichier sans soucis, c'est un peu prêt ce que tu fais mais avec des complications...
0
merci pour ta réponse, mais ce programme la c'était pas vraiment moi qu'il l'avait fait! c'était mamiemando qui m'avait aidé, et c'est lui qui m'avait proposé ce programme ! je ne saurais le modifier!

mais je trouve ca toujours bizarre parcke dans la boucle affichage il faut que je dise jusqu'a +1 a chaque fois!
alors que moi j'aimerais trouver un truc qui me permet de dire que nb_row et nb_col =nombre de lignes et de colonnes et non pas l'indice du tableau, ainsi ce sera plus commode par la suite de mes calculs.

merci
0
Le problème c'est que tout le temps tu devras utilisé un indice de tableau pour tes calculs, par contre tu peux faire que ton nb_row et nb_col correspond bien au nombre de ligne et colonne ce qui serait pas si mal car si ton fichier est vide tu le sera ( actuelement si il est vide ou il y a un élément que se passe-t-il ? j'ai pas regardé en détail mais je pense pas que tu veras la différence) mais après quand tu feras ta boucle il faudra la faire temps que indice<nb_row ou indice<nb_col car sinon tu sortiras du tableau (range check error).
0
ok merci .
je vais voir ca.
0