tags:

views:

585

answers:

3

Hi,

Im reading a text file with this format:

grrr,some text,45.4321,54.22134

Ok so I just have my double valued stored in a string varaible..

Why is it only giving me the first digit of the string?

If i start over with just one while loop and a text file of this new format:

21.34564

it works as it should. The thing is, is that my sLine varaible has the the same value as the one when i started over. Whats different is the three nested for loops that most likely is causing the problem.

Heres the code that gets me what i want:

#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;
}

So there it works just like it should. But i cant get it to work inside a for loop or when i have multiple feilds in my text file...

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;
}

I don't have any other characters to loop over in the first code because im just reading a nice little double value.

In my second code, i have many characters to get to before the one that i want. But regardless, it is still isolated from the other characters and it is still in its own varaible. im to sick to realize what the problem is :/ although i think its the for loops.

I have also tried atof but i get a '0' where the decimal should be. and strtod is hard because i need im not reading data into a const char *cPtr

+2  A: 

Your code is a little tough to read. You probably want to think some point about encapsulation and breaking it up into functions.

Additionally, I would try to avoid reading in single characters and use the various functions and methods for reading data in fields - you can read a whole floating point or integer number using the >> stream extractors.

Finally, a useful skill to learn is how to use a debugger. You can step through the code and inspect the values of variables as you go.

That said, it looks like your problem is here:

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

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

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

On the line marked with "****", you place exactly one character into the variable called "sLine". Having done so, you convert that one character into a double precision variable dValue2 and then output it. It should be obvious why this one character is converted into the first digit of the number you want.

1800 INFORMATION
A: 

Two points:

  • You might want to use sBuffer.find(',')
  • You set sLine to the last character before ",", is this intended to be so? You only parse single digit numbers correctly this way.
sth
+1  A: 

Using instream>>dvalue is certainly the right way to do things. But sometimes what's right isn't always easiest or necessarily best.

We could do something like this:

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);
}

Or perhaps something like this, while less efficient, might be easier to understand...

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));
}

Assuming:

#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()     );
  }
}
Mr.Ree