字符串流循环失败

4

我正在阅读一个格式为:

grrr,一些文本,45.4321,54.22134

的文本文件。

我只是将我的双精度值存储在一个字符串变量中。

为什么它只给我字符串的第一个数字?

如果我重新开始,只使用一个 while 循环和一个新格式的文本文件:

21.34564

它按照预期工作。

问题在于,sLine 的值与我重新开始时的值相同。不同的是三个嵌套的 for 循环,这很可能是导致问题的原因。

这是让我得到想要结果的代码:

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

所以它在单独使用时可以正常工作。但是当我在for循环中或者我的文本文件中有多个字段时,我无法让它正常工作...

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

在第一段代码中,我没有其他字符可以循环遍历,因为我只是读取一个漂亮的双精度值。

在我的第二段代码中,我需要获取许多字符才能找到我想要的那个。但无论如何,它仍然与其他字符隔离,并且它仍然在自己的变量中。我太生病了,无法意识到问题所在:/ 尽管我认为问题出在for循环中。

我也尝试过使用atof,但小数点位置处会得到一个'0'。

而strtod很困难,因为我不是将数据读入const char * cPtr中。

3个回答

2

你的代码有些难以阅读。建议你考虑一下封装和将其拆分成函数。

此外,我建议避免读取单个字符并使用各种读取字段数据的函数和方法 - 你可以使用 >> 流提取器读取整个浮点数或整数。

最后,一个有用的技能是学习如何使用调试器。你可以逐步执行代码并检查变量的值。

话虽如此,看起来你的问题在这里:

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

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

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

在标有“****”的那一行,将恰好一个字符放入名为“sLine”的变量中。这样做后,将该字符转换为双精度变量dValue2,然后输出它。显然,这个字符被转换为你想要的数字的第一个数字。

1

使用 instream>>dvalue 绝对是正确的做法。但有时候正确并不总是最容易或者最好的选择。

我们也可以这样做:

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

或许像这样的代码,虽然不够高效,但更容易理解...

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

假设:
#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()     );
  }
}

0

两点:

  • 你可能想使用{{link1:sBuffer.find(',')}}。
  • 你将sLine设置为“,”之前的最后一个字符,这是有意为之吗?这样只能正确解析单个数字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接