Découpage ligne et stockage dans un vecteur [Résolu/Fermé]

Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
-
Bonjour tt le monde,

j'ai un fichier qui contient deux valeurs de type double séparés par un point virgule.
à l'aide de getline(), j'ai pu lire mon fichier.
maintenant je cherche à découper cette ligne en fonction de mon délimiteur (le point virgule).
comment je peux faire pour découper cette ligne et stocker le résultat dans un vecteur en utilisant c++?
je reste dipso pour plus de détail

Merci
Afficher la suite 

20/31 réponses

Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Bonjour.

Tu peux utiliser à nouveau std::getline en lui précisant ton délimiteur (par défaut il prend \n).

std::ifstream file("toto.txt");
std::string line;
while (std::getline(file, line))
{
  std::istringstream ss(line);
  std::string word;
  while (std::getline(ss, word, ';'))
  {
    std::cout << word << " ";
  }
  std::cout << std::endl;
}


Pour le tableau un simple std::vector<double> suffira. Il ne te restera qu'à convertir les std::string en double et ajouter à ton tableau via un .push_back().


Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
je vous remercie pour votre réponse rapide et utile :)
en tournant votre code j'ai trouvé ce que j'ai cherché à faire :)
Mais svp est ce que vous pouvez me montrer comment faire pour la partie std::vector<double> c'est pas évident pour moi
Merci d'avance :)
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Exemple d'insertion dans un vecteur: http://www.cplusplus.com/reference/vector/vector/push_back/

Exemple de conversion:
std::string s = "5.2"; 
double d = std::stod(s); 



Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
j'ai essayé de faire un petit prog pour tester stod :
#include <sstream>
#include <iostream>
#include <vector>
#include <string>

using namespace std;
string s6 ("3.14"); // chaine contenant des chiffres

double d6 = stod(s6);

cout<<"i5="<<i5<<" d6="<<d6<<endl;


mais il y avait un msg d'erreur :

stod was not declared in this scope


svp càd quoi ce msg !!
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Evite les using namespace, voir: http://0217021.free.fr/portfolio/axel.berardino/articles/bon-usage-using-namespace/

C'est sûrement que tu utilises une vieille version de C++. Mets à jour, et regarde si l'option --std=c++11 est bien activé.
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
tt à fait je suis en train d'utiliser une veille version, j'ai pas l'option c++11
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
bonjour

suite à mes essais, j'ai réussi à faire un petit code qui lit le fichier, découpe la ligne et stocke le résultat dans un vecteur.

voici mon code et si vous avez des remarques n'hésitez pas à laisser un commentaire.

Merci

#include <iostream>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <cstdio>
#include <string.h>
#include <cstdlib>

using namespace std;


int main()
{
   ifstream file("C:/Users/AH673B4N/Documents/_Developpement/Dymola/ThreePhaseCableABCDBuilder/Inputs/mesure1.csv");
   string line;
   vector<double> vec;
   while (getline(file, line))
{
       cout << line << endl;
       istringstream ss(line);
       string word;
       while (getline(ss, word,';')){
       double value = strtod(word.c_str(), NULL); // cnversion string to double
       vec.push_back(value); //remplissage du vecteur
  }
}
//Affichage du vecteur
for (int i = 0; i < vec.size(); i++){
        cout << vec[i] << '\n';
 }
 //cout << vec[0] << " " << vec [1] ;
    return 0;
}
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Quelques petites remarques:
- Évite les using namespace std (cf lien donné plus haut dans la discussion), ce n'est pas une bonne idée.
- Tu n'as normalement pas besoin d'inclure quoi que ce soit du C (si tu as du ".h" dans un include system, c'est sûrement évitable).
- La plupart de tes includes ne sont pas nécessaires (tu pourrais en retirer et quand même compiler).
- Il faut penser à gérer les erreurs (pas de fichier, pas de conversion possible, etc...).
- Pour les boucles, tu peux directement utiliser un "for étendu" (for (auto& element : collection){}) au lieu de récupérer la taille du vecteur et devoir gérer un index.

Voici une proposition de correction:
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>

int main()
{
  const std::string filename = "C:/Users/AH673B4N/Documents/_Developpement/Dymola/ThreePhaseCableABCDBuilder/Inputs/mesure1.csv";
  std::ifstream file(filename);
  std::string line;
  std::vector<double> vec;

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  while (std::getline(file, line))
  {
    std::istringstream ss(line);
    std::string word;
    while (std::getline(ss, word, ';'))
    {
      try
      {
      vec.push_back(std::stod(word));
      }
      catch (std::invalid_argument& e)
      {
        std::cerr << "Can't convert " << word << " to double (" << e.what() << ")" << std::endl;
      }
    }
  }

  std::cout << "Vec: ";
  for (auto& val : vec) // on aurait aussi pu écrire for (double val : vec)
    std::cout << val << " ";
  std::cout << std::endl;

  return 0;
}



Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
je vous remercie de tt mon cœur :)
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
Bonjour
Svp j'ai une autre question, si par exemple j'ai un fichier.csv mais qui contient plusieurs lignes et plusieurs colonnes (par exemple 200 lignes et 20 colonnes), comment je peut faire pour transformer ce fichier en une matrice M[i][j]? est ce que ça sera le même principe qu'auparavant ?
Merci
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Ça sera exactement le même principe. Au lieu d'avoir un std::vector<double>, tu auras un std::vector<std::vector<double>>. Ce n'est pas plus compliqué.

Alternativement, pour lire du CSV, tu peux aussi utiliser ce projet:
https://github.com/ben-strasser/fast-cpp-csv-parser

Au choix.
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
svp est ce qu'il y a une fonction qui permet d'ignorer la première ligne de mon fichier (la première ligne représente les entêtes je vais pas l'utiliser dans la suite de mon prog)

Merci :)
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Vu que c'est toi qui boucle ligne à ligne, il te suffit de compter les lignes. Si la ligne est celle que tu ne veux pas, alors il te suffit de passer à l'itération suivante (soit avec un gros "if", ou alors avec un "continue").
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
je vais vous montrer mon code et dites moi svp j'ai des grands doutes !! je suis pas sure de mon logique
#include <iostream>
#include <fstream>
#include <sstream>
#include <vector>
#include <string.h>

int main()
{
  const std::string filename = "C:/Users/AH673B4N/Documents/_Developpement/Dymola/ThreePhaseCableABCDBuilder/Inputs/Measurements.csv";
  std::ifstream file(filename);
  std::string line;
  std::vector<std::vector<double>> vec;
  int lines = 0;

  if (!file) // tester l'existance du fichier et la possibilité d'ouverture
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

while(!file.eof()) // eof end of file
        {
    std::getline (file, line);
    lines++; //incrémentation des lignes
    std::istringstream ss(line);
    std::string word;
    while (std::getline(ss, word, ';'))
    {
      try
      {
          for (int i =1; i<lines; i++)
          {
      vec.push_back(std::vector<double>(std::stod(word)));
          }

      }
      catch (std::invalid_argument& e)
      {
        std::cerr << "Can't convert " << word << " to double (" << e.what() << ")" << std::endl;
      }
    }
  }

  std::cout << "Vec: ";
  for (auto& val : vec) // on aurait aussi pu écrire for (double val : vec)
{
  std::cout << val << " ";
  //std::cout << vec [1]<< std:: endl;
  std::cout << std::endl;
  //std::cout << vec [0]+vec[1] << std::endl; // on eut faire des opérations sur les cases du mon tableau, les cases sont accessibles
}


  return 0;
}


en plus j'ai un msg d'erreur : no match for 'operator<<' (operand types are 'std::ostream {aka std::basic_ostream<char>}' and 'std::vector<double>')

j'arrive pas à comprendre le msg

dsl pour les questions bêtes !
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Plusieurs soucis:
- Tu utilises "lignes" comme étant la taille de tes colonnes. A chaque ligne, tu vas essayer de lire de plus en plus de colonnes. Il y a une erreur de raisonnement ici.
- Le message d'erreur que tu as, vient du fait que dans "val : vec", val n'est plus un double, mais un std::vector<double>. Or tu ne peux pas l'afficher directement. Il te faut une autre boucle imbriqué pour en afficher les éléments.
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
Bonjour,

Je vous remercie pour votre réponse.
J'ai fait mon prog d'une autre manière. Le prog fonctionne bien mais je suis tjrs à l'écoute de vos conseils :)

Merci.

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>

int main()
{
    const std::string filename = "C:/Users/Measurements.csv";
    std::ifstream in(filename); // open the file
    std::string line, field;
    std::vector <std::vector <string> > array;  // the 2D array
    std::vector<string> v;

    if (!in) // error if the file doesn't exist
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

    while ( std::getline(in,line) )    // get next line in file
    {
        v.clear();
        std::stringstream ss(line);

        while (std::getline(ss,field,';'))  // break line into comma delimitted fields
        {
            v.push_back(field);  // add each field to the 1D array
        }

        array.push_back(v);  // add the 1D array to the 2D array
    }

    // print out what was read in

    for (size_t i=0; i<array.size(); ++i)
    {
        for (size_t j=0; j<array[i].size(); ++j)
        {
            std:: cout << array[i][j] << " | "; // (separate fields by |)
        }
        std:: cout << "\n";
    }

    //std:: cout << "array[1][3]= " << array[1][3] <<etd::endl;

    return 0;
}
Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
Plusieurs soucis:
- Pas de check d'erreur (lors de la conversion). Donc ton programme peut planter ou faire n'importe quoi si tu lui donnes un fichier pas compatible. Ça devrait être géré.
- Pas besoin de clear ton vecteur à chaque fois. Déclare une variable dans un scope restreint, et elle n'existera que dans ce scope. D'une manière générale, ne pas déclarer des variables en haut de ta fonction, mais au moment où tu en as besoin.
- Attention, tu ne vérifies pas si le vecteur à insérer est vide quand tu l'insères dans le premier vecteur (c'est-à-dire que tu as sûrement un vecteur final contenant plein de tableaux vides potentiels sur des lignes incorrectes).
- Pour afficher ton tableau, une simple double boucle de for étendu suffisait.

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>

int main()
{
  const std::string filename = "C:/Users/Measurements.csv";
  std::ifstream file(filename);

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  std::string line;
  std::vector<std::vector<double>> array;
  while (std::getline(file, line))
  {
    std::vector<double> v;
    std::string field;
    std::stringstream ss(line);
    while (std::getline(ss, field, ';'))
    {
      try
      {
        v.push_back(std::stod(field));
      }
      catch (std::invalid_argument& e)
      {
        std::cerr << "Can't convert " << field << " to double (" << e.what() << ")" << std::endl;
        continue;
      }
    }
    if (!v.empty()) // Prevent invalid lines to display empty lines later
      array.push_back(v);
  }

  std::cout << "Vec:\n";
  for (auto& vec : array)
  {
    for (auto& value : vec)
      std::cout << value << "|";
    std::cout << std::endl;
  }

  return 0;
}


PS: utilise <code cpp> au lieu de <code> pour activer la coloration syntaxique.


Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
Bonjour,

vous avez raison, mais il y a qlq soucis:

1- le fichier contient des entêtes, comment je peux faire pour parcourir mes lignes afin de débarrasser de la première ligne lors de la conversion vers "double"?
2- les doubles de mon fichier sont séparés par une virgule et non par un point, du coup comme résultat j'ai obtenu un vecteur contenant juste la partie entière de chaque valeur. or moi je dois récupérer la valeur telle qu'elle est !
Merci pour votre aide :)

Messages postés
3830
Date d'inscription
dimanche 12 décembre 2004
Statut
Modérateur
Dernière intervention
19 novembre 2018
0
Merci
1) Un entête commence normalement par #, donc il suffit de ne pas lire une ligne qui commence par cela. Si ce n'est pas le cas, le code le gère déjà, puisque toute ligne non convertie n'est pas dans le tableau final. Les erreurs sont uniquement affichées et n'affectent pas le tableau résultat.
2) Là, c'est assez compliqué à faire. En fait, un double prend un "." et non une ",". Dès le moment ou tu veux un double particulier (par exemple si tu décides que 3.14 s'écrit maintenant 3,14 ou 3#14 ou 3-14, ou 3$14), alors ce n'est plus un double ! Tu dois alors créer un convertisseur spécial qui précise quel est le séparateur voulu. Il faut modifier la "locale" (langue) en cours et lui dire que le séparateur est maintenant ",". La syntaxe n'est pas aisée du tout. Il faut écrire sa propre fonction std::stod (que j'ai appelé "comaStod") et utiliser une locale personnalisée.

#include <string>
#include <sstream>
#include <iostream>
#include <vector>
#include <fstream>
#include <clocale>

template <class charT, charT sep>
class punct_facet: public std::numpunct<charT> {
protected:
  charT do_decimal_point() const { return sep; }
};

double comaStod(std::string const& s)
{
  std::istringstream iss(s);
  iss.imbue(std::locale(std::cout.getloc(), new punct_facet<char, ','>));
  double d;
  if (!(iss >> d))
    throw std::invalid_argument("invalid double");

  return d;
}

int main()
{
  const std::string filename = "C:/Users/Measurements.csv";
  std::ifstream file(filename);

  if (!file)
  {
    std::cerr << "Can't open file " << filename << std::endl;
    return 1;
  }

  std::string line;
  std::vector<std::vector<double>> array;
  while (std::getline(file, line))
  {
    // Ignore line starting with #
    if (line.empty() || line[0] == '#')
      continue;
    std::vector<double> v;
    std::string field;
    std::stringstream ss(line);
    while (std::getline(ss, field, ';'))
    {
      try
      {
        v.push_back(comaStod(field));
      }
      catch (std::invalid_argument& e)
      {
        std::cerr << "Can't convert " << field << " to double (" << e.what() << ")" << std::endl;
        continue;
      }
    }
    if (!v.empty())
      array.push_back(v);
  }

  std::cout << "Vec:\n";
  for (auto& vec : array)
  {
    for (auto& value : vec)
      std::cout << value << "|";
    std::cout << std::endl;
  }

  return 0;
}



Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Messages postés
29
Date d'inscription
mardi 18 septembre 2018
Dernière intervention
6 décembre 2018
0
Merci
1000 merci à vous :)
concernant la première ligne, elle ne commence pas par #. En fait, elle contient 16 colonnes nommés comme suit :

Freq(Hz) R1 (Ohm) R2 (Ohm) R3 (Ohm) L1(Henry) L2(Henry) L3(Henry) Le1(Henry) Le2(Henry) Le3(Henry) CA(Farad) CB(Farad) CC(Farad) CD(Farad) CE (Farad) CF(Farad)

c'est vrai cette ligne non convertie n'est pas mise dans le tableau final. Juste des erreurs sont affichées mais qd mm je vais essayer d'ignorer cette ligne pour avoir un affichage propre :)

Je vous remercie encore une fois :)

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.