2009-01-26 6 views
4

Je lis un fichier texte avec ce format:boucle stringstream échoue

grrr, texte, 45.4321,54.22134

Je viens de mon double Valued stocké dans une variable de chaîne. Pourquoi ne me donne-t-il seulement que le premier chiffre de la chaîne?

Pourquoi?

Si je commence sur un seul en boucle et un fichier texte de ce nouveau format:

21,34564

il fonctionne comme il se doit.

La chose est, sLine a la même valeur que celle lorsque j'ai recommencé. Ce qui est différent, ce sont les trois boucles imbriquées qui causent probablement le problème.

Voici le code qui me fait ce que je veux:

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

using namespace std; 

int main() 
{ 
    string usrFileStr, 
    fileStr = "test.txt", // declaring an obj string literal 
    sBuffer, 
    sLine, 
    str; 

    double dValue ; 

    int lineCount = 1; 
    int nStart; 
    istringstream issm; 

    fstream inFile;     // declaring a fstream obj 
    // cout is the name of the output stream 
    cout << "Enter a file: "; 
    cin >> usrFileStr; 

    inFile.open(usrFileStr.c_str(), ios::in); 
    // at this point the file is open and we may parse the contents of it 


    while (getline (inFile, sBuffer) && inFile.eof()) 
    { 
      cout << "Original String From File: " << sBuffer << endl; 

      cout << "Modified Str from File: " << fixed << setprecision(2) 
      << dValue << endl; 
    } 

    fgetc(stdin); 
    return 0; 
}  

Il y a cela fonctionne comme il se doit. Mais je ne peux pas le faire fonctionner à l'intérieur d'une boucle ou quand j'ai plusieurs feilds dans mon fichier texte ...

With this code, why is it taken off the decimal? 

#include <iostream> 
#include <fstream> 
#include <string> 
#include <vector> 
#include <iomanip> 
#include <cstdlib> 
#include <sstream> 
#include <errno.h> 

using namespace std; 

int main() 
{ 
    string usrFileStr, 
    myFileStr = "myFile.txt", // declaring an obj string literal 
    sBuffer, 
    sLine = ""; 


    istringstream inStream; 

    int lineCount = 1; 
    int nStart; 
    double dValue = 0, 
    dValue2 = 0; 
    float fvalue; 

    fstream inFile;     // declaring a fstream obj 
    // cout is the name of the output stream 
    cout << "Enter a file: "; 
    cin >> usrFileStr; 


    inFile.open(usrFileStr.c_str(), ios::in); 
    // at this point the file is open and we may parse the contents of it 

    if (!inFile) 
    { 
     cout << "Not Correct " << endl; 
    } 


    while (getline (inFile, sBuffer)) 
    { 
      nStart = -1 ; 

      for (int x = nStart + 1; x < sBuffer.length(); x++) 
      { 
       if (sBuffer[ x ] == ',') 
       { 
        nStart = x; 
        break; 
       } 

       cout << sBuffer[ x ]; 
      } 

      for (int x = nStart + 1; x < sBuffer.length(); x++) 
      { 

       if (sBuffer[ x ] == ',') 
       {  
        nStart = x; 
        break; 
       } 

       cout << sBuffer[ x ]; 
      } 


      for (int x = nStart + 1; x < sBuffer.length(); x++) 
      { 

       if (sBuffer[ x ] == ',') 
       { 
        nStart = x; 
        break; 
       } 

       sLine = sBuffer[ x ]; 
       inStream.clear(); 
       inStream.str(sLine); 

       if (inStream >> dValue) 
       cout << setprecision(1) << dValue; 

      } 


      for (int x = nStart + 1; x < sBuffer.length(); x++) 
      { 
       if (sBuffer[ x ] == ',') 
       { 
        nStart = x; 
        break; 
       } 

       sLine = sBuffer[ x ];  
       inStream.clear(); 
       inStream.str(sLine); 

       if (inStream >> dValue2) 
        cout << setprecision(1) << dValue2;  
      } 

      cout << ") \n"; 
      lineCount++; 
    } 


    cout << "There are a Total of: " << lineCount -1 << " line(s) in the file." 
    << endl; 

    inFile.clear();   // clear the file of any errors 
    inFile.close(); // at this point we are done with the file and may close it 

    fgetc(stdin); 
    return 0; 
} 

Je n'ai pas d'autres personnages à boucle sur dans le premier code, car im simple lecture une belle petite valeur double.

Dans mon deuxième code, j'ai beaucoup de caractères à atteindre avant celui que je veux. Mais quoi qu'il en soit, il est encore isolé des autres personnages et il est toujours dans son propre varaible. Je suis malade de se rendre compte quel est le problème:/bien que je pense que c'est le pour les boucles.

J'ai également essayé atof mais j'obtiens un '0' où la décimale devrait être. et strtod est difficile parce que je n'ai pas besoin de lire les données dans un const const * cPtr

Répondre

1

En utilisant instream >> dValue est certainement le droit façon de faire les choses. Mais parfois ce qui est juste n'est pas toujours le plus facile ou nécessairement le meilleur.

Nous pourrions faire quelque chose comme ceci:

int 
main() 
{ 
    string s = "grrr,some text,45.4321,54.22134"; 
    double a,b; 

    ASSERT_IS(2, sscanf(s.c_str(), "%*[^,],%*[^,],%lf,%lf", & a, & b)); 

    cout << setprecision(8); 
    SHOW(a); 
    SHOW(b); 
} 

Ou peut-être quelque chose comme ça, alors que moins efficace, peut-être plus facile à comprendre ...

int 
main() 
{ 
    string s = "grrr,some text,45.4321,54.22134"; 
    vector<string> v; 

    StringSplit(& v, s, ","); 

    cout << setprecision(8); 
    SHOW(v); 
    SHOW(atof( v[2].c_str())); 
    SHOW(strtod(v[3].c_str(), (char**)NULL)); 
} 

En supposant:

#define SHOW(X) cout << # X " = " << (X) f << endl 


    /* A quick & easy way to print out vectors... */ 
template<class TYPE> 
inline ostream & operator<< (ostream & theOstream, 
           const vector<TYPE> & theVector) 
{ 
    theOstream << "Vector [" << theVector.size() << "] {" 
      << (void*)(& theVector) << "}:" << endl; 

    for (size_t i = 0; i < theVector.size(); i ++) 
    theOstream << " [" << i << "]: \"" << theVector[i] << "\"" << endl; 

    return theOstream; 
} 


inline void 
StringSplit(vector<string> * theStringVector, /* Altered/returned value */ 
      const string & theString, 
      const string & theDelimiter) 
{ 
    UASSERT(theStringVector, !=, (vector<string> *) NULL); 
    UASSERT(theDelimiter.size(), >, 0); 

    size_t start = 0, end = 0; 

    while (end != string::npos) 
    { 
    end = theString.find(theDelimiter, start); 

     // If at end, use length=maxLength. Else use length=end-start. 
    theStringVector -> push_back(theString.substr(start, 
        (end == string::npos) ? string::npos : end - start)); 

     // If at end, use start=maxSize. Else use start=end+delimiter. 
    start = ( (end > (string::npos - theDelimiter.size())) 
       ? string::npos : end + theDelimiter.size() ); 
    } 
} 
2

Votre code est un peu difficile à lire. Vous voulez probablement réfléchir à l'encapsulation et la décomposer en fonctions. De plus, j'essaierais d'éviter de lire en caractères uniques et d'utiliser les différentes fonctions et méthodes pour lire les données dans les champs - vous pouvez lire un nombre entier ou un nombre entier en utilisant les extracteurs de flux >>. Enfin, une compétence utile à apprendre est comment utiliser un débogueur. Vous pouvez parcourir le code et inspecter les valeurs des variables au fur et à mesure.

Cela dit, il semble que votre problème est ici:

  if (sBuffer[ x ] == ',') 
      { 
       nStart = x; 
       break; 
       } 

      **** sLine = sBuffer[ x ];  
      inStream.clear(); 
      inStream.str(sLine); 

      if (inStream >> dValue2) 
      cout << setprecision(1) << dValue2; 

Sur la ligne marquée « **** », vous placez exactement un caractère dans la variable appelée « sLine ». Cela fait, vous convertissez ce caractère en une variable double précision dValue2 et ensuite le sortir. Il devrait être évident pourquoi ce caractère est converti en le premier chiffre du nombre que vous voulez.

0

Deux points:

  • Vous pouvez utiliser sBuffer.find(',')
  • Vous définissez sLine le dernier caractère avant "" Est-ce destiné à être ainsi? Vous n'analysez les nombres à un chiffre que de cette manière.