2012-10-30 1 views
1

donc j'ai un fichier data3.txt qui ressemble essentiellement comme ceci:sstream en utilisant l'entrée et le fichier de sortie

#file:data.txt 
#data inputs 
1 1234 +0.2 23.89 6.21 
2 132 -0.03 3.22 0.1 
3 32 0.00 31.50 4.76 

Et je veux prendre les 3 premières colonnes à écrire dans un nouveau fichier en utilisant stringtreams

#include <cctype> 
#include <sstream> 
#include <iostream> 
#include <fstream> 
#include <cstdlib> 
#include <string> 
using namespace std; 
int main(){ 
    string line; 
    float curr_price, change; 
    int stock_number; 
    ifstream fin("data3.txt"); 
    istringstream iss; 
    ostringstream oss; 
    if(!fin){ 
    cerr<<"Can't open a file"; 
    } 
    ofstream outfile("data2.txt"); 
    while (getline(fin,line)){ 
    iss.clear(); 
    iss.str(line); 
    iss>>stock_number>>curr_price>>change; 
    while(isspace(iss.peek())) 
     iss.ignore(); 
    while(iss.str() == "#") 
     iss.ignore(); 
    if(iss.str()==""){ 
     break; 
    } 
    oss<<stock_number<<"\t"<<curr_price<<"\t"<<change<<"\n"; 
    outfile<<oss.str(); 
    } 
} 

mais je mon fichier de sortie a l'air méchant:

0 0 0 
0 0 0 
0 0 0 
0 0 0 
0 0 0 
1 1234 0.2 
0 0 0 
0 0 0 
1 1234 0.2 
2 132 -0.03 
0 0 0 
0 0 0 
1 1234 0.2 
2 132 -0.03 
3 32 0 

Je ne sais pas d'où vient zéros viennent, un nd si je mets l'ofstream en dehors de la boucle while alors il imprimera seulement la dernière ligne de données

+0

Les zéros semblent provenir des lignes de commentaires, mais je ne sais pas pourquoi les lignes sont répétées –

Répondre

2

Un problème est que vous sortez toujours des nombres, même si vous obtenez un commentaire. En outre, le coup d'oeil et ignorer les choses ne devrait pas être nécessaire. Pour vérifier si les chiffres ont été lus avec succès, simplement d'évaluer le flux comme un booléen après la lecture, comme je le fais dans cet exemple:

#include <fstream> 
#include <sstream> 
using namespace std; 

int main(int argc, char ** argv) 
{ 
    ifstream in(argv[1]); 
    ofstream out(argv[2]); 
    string line; 
    while(getline(in,line)) 
    { 
     if(line.empty() || line[0] == '#') continue; 
     double number, price, change; 
     stringstream ss(line); 
     if(ss >> number >> price >> change) 
      out << number << "\t" << price << "\t" << change << "\n"; 
    } 
    return 0; 
} 

Ceci est, par ailleurs, un exemple de cas où en utilisant une C fonctions rendrait les choses à la fois plus simples et plus jolies:

#include <stdlib.h> 
#include <stdio.h> 
#include <iostream> 
using namespace std; 

int main(int argc, char ** argv) 
{ 
    string line; 
    int number; 
    double price, change; 
    while(getline(cin,line)) 
     if(sscanf(line.c_str(), "%d %lf %lf", &number, &price, &change)==3) 
      printf("%3d %8.2f %8.2f\n", number, price, change); 
    return 0; 
} 

Cet exemple utilise des entrées et des sorties standard au lieu de fichiers. Ceux-ci sont appelés "standard" pour une raison: Ils sont très flexibles, et peuvent être redirigés vers/depuis des fichiers et d'autres processus très simplement. Mais le programme serait très similaire avec les fichiers.

+0

merci beaucoup qui a été très utile –

+0

Je viens de recevoir une question comment cette première utilisation implemenetation ostringstream et istringstream? –

+0

Ce n'est pas le cas, donc si c'était critique je suppose que ce n'est pas ce que vous cherchiez. L'ostringstream n'est pas nécessaire pour ce que vous faisiez, donc je ne l'ai pas utilisé. Le flux istrings était utile en raison de ses propriétés de segmentation. J'ai utilisé une chaîne de caractères simple, mais elle aurait pu être remplacée par un flux istrings sans aucun changement. – amaurea

1

Vous devez toujours vérifier que votre entrée a réussi! En outre, vous avez rarement besoin de recourir à des techniques de lecture basées sur des personnages étranges. Par exemple, il existe un manipulateur pour ignorer les espaces de début: std::ws. Voici une version qui ne fait pas beaucoup d'hypothèses sur les types de valeurs. Si la première valeur sur une ligne doit être un nombre entier, vous pouvez utiliser int au lieu de std::string et vous pouvez même passer la vérification de la ligne de commentaire! Vous vérifiez simplement que la lecture de trois valeurs a réussi.

#include <sstream> 
#include <fstream> 
#include <string> 

int main() 
{ 
    std::ifstream  in("input.txt"); 
    std::ofstream  out("output.txt"); 
    std::istringstream lin; 
    std::string  tmp0, tmp1, tmp2; 
    for (std::string line; std::getline(in, line);) { 
     lin.clear(); 
     lin.str(line); 
     if ((lin >> std::ws).peek() != '#' 
      && lin >> tmp0 >> tmp1 >> tmp2) { 
      out << tmp0 << '\t' << tmp1 << '\t' << tmp2 << '\n'; 
     } 
    } 
} 
Questions connexes