简体   繁体   English

来自文件的简单C ++输入…如何?

[英]Simple C++ input from file…how to?

I have a file: 我有一个文件:

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
.
.
.

When I read in 'P' I know that 3 floats will follow. 当我读“ P”时,我知道将跟随3个浮点数。 That will be followed by a finite number of X and Y coordinates. 然后是有限数量的X和Y坐标。 The number will vary until a 'T' is reached which I have to recognize. 该数字将一直变化,直到达到我必须识别的“ T”为止。 Then there could be an 'r', 's' or 't' followed by some values. 然后可能会有一个“ r”,“ s”或“ t”,后跟一些值。

Anyways I know how to recognize 'P' and then take in the 2 floats but then I know I have to have a while loop for the X and Y coordinates which will stop when I get to a 'T'. 无论如何,我知道如何识别“ P”,然后接受2个浮点数,但是我知道我必须有一个X和Y坐标的while循环,当我到达“ T”时,它将停止。 I do not know enough about C++ to make the loop stop and recognize the 'T' and then do something else. 我对C ++的了解不足,无法使循环停止并识别“ T”,然后执行其他操作。

An example to explain would be appreciated. 一个例子来解释将不胜感激。 Thanks in advance! 提前致谢!

I'll show you what I think it's the proper C++ way of doing this. 我将向您展示我认为这是正确的C ++方式。 First define a class for representing your first line and for doing its IO: 首先定义一个类来表示您的第一行并执行其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;
    }    
};

I've added some basic error checking with assert, you'll probably want something more robust in your final program. 我用assert添加了一些基本的错误检查,您可能希望在最终程序中提供更强大的功能。

Now a class for middle lines: 现在是中线类:

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

When we reach the end of the section where the middle lines are we are supposed to encounter a "T". 当我们到达中间线所在部分的末尾时,我们应该遇到一个“ T”。 In that case we raise the fail bit of the stream, which will tell client that there are no more middle lines to read. 在这种情况下,我们提高流的失败位,这将告诉客户端没有更多的中间行可供读取。

Finally a class for the last lines: 最后是最后一行的类:

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

Last lines are more complicated becase we don't know how many values are in each, so we just read as many as we can. 如果我们不知道每个值中有多少个值,则最后一行会更复杂,因此我们只读取尽可能多的值。

That was the tricky part. 那是棘手的部分。 Now our main function will simply read one first line, then an unknown number of middle lines, and finally an unknown number of last lines: 现在,我们的main函数将只读取第一行,然后读取未知数量的中间行,最后读取未知数量的最后一行:

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

This is the output you'll get:: 这是您将得到的输出:

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

I've used a string as the source of my data but you'll probably want to read from a file. 我使用字符串作为数据源,但您可能希望从文件中读取。

And that's all, you can see that I didn't write a single loop. 仅此而已,您可以看到我没有编写任何循环。

Here's the code in codepad. 这是键盘中的代码

  • Keep a kind of 'global state' 保持一种“全球状态”
  • Write a loop that reads a line from the file until end-of-file. 编写一个循环,从文件中读取一行直到文件结束。
  • Read the line into a buffer 将行读入缓冲区
  • Check the first character of the buffer, if it is P or T or r or s or t, change the global state of the application 检查缓冲区的第一个字符,如果它是P或T或r或s或t,则更改应用程序的全局状态
  • If the first character was a T, use a sscanf(Buffer+1,"%lf %lf %lf",&first,&second,&third) to read the rest of the line. 如果第一个字符是T,请使用sscanf(Buffer + 1,“%lf%lf%lf”,&first,&second,&third)读取其余的行。
  • Do something similar if the first character is r, s or t. 如果第一个字符是r,s或t,请执行类似的操作。
  • If the application is in the 'P-state' just scan the buffer using sscanf(Buffer,"%lf %lf",&first,&second) 如果应用程序处于“ P状态”,则只需使用sscanf(Buffer,“%lf%lf”,&first,&second)扫描缓冲区

I think you can use standard streams 我认为您可以使用标准流
to check "P" and "T" 检查“ P”和“ T”
use get(char &ch); 使用get(char&ch);
and putback(ch) to push it back to stream 然后放回(ch)将其推回流
and
yourstream >> x >> y >> endl; yourstream >> x >> y >> endl;

http://www.cplusplus.com/reference/iostream/istream/putback/ 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;  
}

user to read text file line by line and then run string word; 用户逐行阅读文本文件,然后运行字符串单词;

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM