从文件中输入简单的C ++ ...怎么样?

时间:2010-02-22 07:30:52

标签: c++ file-io while-loop conditional-statements

我有一个文件:

P 0.5 0.6 0.3
30 300
80 150
160 400
200 150
250 300
T
r  45 0 0
s 0.5 1.5 0 0
t 200 –150
.
.
.

当我读到'P'时,我知道会有3个花车。接下来是有限数量的X和Y坐标。数字会有所变化,直到达到“T”,我必须承认。然后可能会有一个'r','s'或't'后跟一些值。

无论如何我知道如何识别'P'然后接收2个浮点数然后我知道我必须有一个X和Y坐标的while循环,当我到达'T'时它会停止。我不太了解C ++使循环停止并识别'T'然后做其他事情。

一个解释的例子将不胜感激。提前谢谢!

4 个答案:

答案 0 :(得分:9)

我会告诉你我认为这是正确的C ++方式。首先定义一个用于表示第一行和执行IO的类:

struct FirstLine
{
    double x, y, z;
    friend std::istream & operator>>(std::istream & is, FirstLine & data)
    {
        std::string line, ignore;
        std::getline(is, line);
        std::istringstream iss(line);
        iss >> ignore >> data.x >> data.y >> data.z;
        assert(ignore == "P" && iss);
        return is;
    }
    friend std::ostream & operator<<(std::ostream & os, FirstLine const & data)
    {
        return os << "P " << data.x << " " << data.y << " " << data.z;
    }    
};

我在assert中添加了一些基本的错误检查,你可能希望在最终的程序中有更强大的功能。

现在是中间线的一个类:

struct MiddleLine
{
    double x, y;
    friend std::istream & operator>>(std::istream & is, MiddleLine & data)
    {
        std::string line;
        std::getline(is, line);
        if(line == "T")
            is.clear(std::ios::failbit);
        else
        {
            int n = sscanf(line.c_str(), "%lf %lf", &data.x, &data.y);
            assert(n == 2);
        }
        return is;
    }
    friend std::ostream & operator<<(std::ostream & os, MiddleLine const & data)
    {
        return os << data.x << " " << data.y;
    }    
};

当我们到达中间线的部分的末尾时,我们应该遇到“T”。在这种情况下,我们引发流的失败位,这将告诉客户端没有更多的中间行要读取。

最后一行为最后一行:

struct LastLine
{
    std::string identifier; // r, s or t
    std::vector<double> values;
    friend std::istream & operator>>(std::istream & is, LastLine & data)
    {
        std::string line;
        std::getline(is, line);
        std::istringstream iss(line);
        iss >> data.identifier;
        assert(data.identifier == "r" || data.identifier == "s" 
               || data.identifier == "t");
        std::copy(std::istream_iterator<double>(iss), 
                  std::istream_iterator<double>(), std::back_inserter(data.values));
        return is;
    }
    friend std::ostream & operator<<(std::ostream & os, LastLine const & data)
    {
        os << data.identifier << " ";
        std::copy(data.values.begin(), data.values.end(),
                  std::ostream_iterator<double>(os, " "));
        return os;
    }      
};

由于我们不知道每个值有多少,所以最后一行更复杂,所以我们尽可能多地阅读。

这是棘手的部分。现在我们的主要功能只是读取第一行,然后是未知数量的中间行,最后是未知数量的最后一行:

int main()
{
    std::string const data = "P 0.5 0.6 0.3\n
                             "30 300\n"
                             "80 150\n"
                             "160 400\n"
                             "200 150\n"
                             "250 300\n"
                             "T\n"
                             "r  45 0 0\n"
                             "s 0.5 1.5 0 0\n"
                             "t 200 –150";

    std::istringstream iss(data);

    FirstLine first_line;
    iss >> first_line;

    std::vector<MiddleLine> middle_lines;
    std::copy(std::istream_iterator<MiddleLine>(iss), 
              std::istream_iterator<MiddleLine>(), 
              std::back_inserter(middle_lines));
    iss.clear();

    std::vector<LastLine> last_lines;
    std::copy(std::istream_iterator<LastLine>(iss), 
              std::istream_iterator<LastLine>(), 
              std::back_inserter(last_lines));
    assert(iss.eof());       

    std::cout << first_line << "\n";
    std::copy(middle_lines.begin(), middle_lines.end(),
              std::ostream_iterator<MiddleLine>(std::cout, "\n"));
    std::copy(last_lines.begin(), last_lines.end(),
              std::ostream_iterator<LastLine>(std::cout, "\n"));
    return 0;
}

这是你得到的输出::

P 0.5 0.6 0.3
30 300
80 150
160 400
200 150
250 300
r 45 0 0
s 45 0 0 0.5 1.5 0 0
t 45 0 0 0.5 1.5 0 0 200

我使用了一个字符串作为我的数据源,但您可能想要从文件中读取。

就是这样,你可以看到我没有写一个循环。

在键盘中

Here's the code

答案 1 :(得分:0)

  • 保持一种“全球状态”
  • 编写一个循环,从文件中读取一行直到文件结尾。
  • 将该行读入缓冲区
  • 检查缓冲区的第一个字符,如果是P或T或r或s或t,则更改应用程序的全局状态
  • 如果第一个字符是T,请使用sscanf(Buffer + 1,“%lf%lf%lf”,&amp; first,&amp; second,&amp; third)来读取该行的其余部分。
  • 如果第一个字符是r,s或t,请执行类似的操作。
  • 如果应用程序处于'P状态',只需使用sscanf扫描缓冲区(Buffer,“%lf%lf”,&amp; first,&amp; second)

答案 2 :(得分:0)

我认为你可以使用标准流 检查“P”和“T”
使用get(char&amp; ch);
和putback(ch)将其推回流中 和
yourstream&gt;&gt; x&gt;&gt; y&gt;&gt; ENDL;

http://www.cplusplus.com/reference/iostream/istream/putback/

// Example
// istream putback
#include <iostream>
using namespace std;

int main () {  
  char c;  
  int n;  
  char str[256];  

  cout << "Enter a number or a word: ";
  c = cin.get();  

  if ( (c >= '0') && (c <= '9') )
  {  
    cin.putback (c);
    cin >> n;
    cout << "You have entered number " << n << endl;
  }  
  else
  {  
    cin.putback (c);
    cin >> str;
    cout << " You have entered word " << str << endl;
  }  

  return 0;  
}

答案 3 :(得分:0)

用户逐行读取文本文件然后 运行字符串字;

ifstream fin(your file)
while(! fin.eof())
{
    string line = fin.getline();
    istringstream iss(line, istringstream::in);
    string token;
    while( iss >> token)     
    {
      if (token.compare("T")) {
        ...
      } else {
        float f = atof(token.c_str());
     }
    }
}