在 C++ 中读取输入文件

Reading an input file in C++

我想读取包含以下行的 C++ 输入文件

- numberOfStates
- numberOfSymbols
- numberOfFinalStates
- list of final states (one per line)
- numberOfTransitions
- listOfTransitions (one per line. The transitions include two ints and one char)

重要的是要说每个输入文件中的数字是不同的。我必须为每个文件读取不同数量的行。

这是一个示例输入文件

10 
3 
1 
9 
12 
0 1 f 
0 3 f 
1 2 a 
2 9 f 
3 4 f 
3 8 f 
4 5 b 
5 6 f 
6 7 a 
8 9 f 

如何在读取输入文件时声明每个变量?

这就是我卡住的地方..真的不知道该怎么办

ifstream fin("inputFile.txt");

    int numberOfStates;
    int numberOfSymbols;
    int numberOfFinalStates;
    // I'm not sure how to declare the next variables because they will vary in size each time 


    while (fin >> numberOfStates >> numberOfSymbols >> numberOfFinalStates)
    {
        cout << numberOfStates << numberOfSymbols << numberOfFinalStates << endl;
    }

如果可能的话,我想使用向量。

正在做

while (fin >> name >> var1 >> var2 >> var3)
{
    cout << name << var1 << var2 << var3 << endl;
}

你一直在相同的变量上重写,你需要把值放在一个向量中,就像你在问题中说的那样

您还需要检查每个输入是否正确,目前您没有检测到无效输入

当然你需要检查你是否打开了文件


示例:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

int main()
{
  std::ifstream fin("inputFile.txt");

  if (!fin.is_open()) {
    std::cerr << "cannot open inputFile.txt" << std::endl;
    return -1;
  }

  int numberOfStates, numberOfSymbols, numberOfFinalStates;

  if ((! (fin >> numberOfStates >> numberOfSymbols >> numberOfFinalStates))
      || (numberOfStates < 0)
      || (numberOfSymbols < 0)
      || (numberOfFinalStates < 0)) {
    std::cerr << "invalid file" << std::endl;
    return -1;
  }

  // final states are int, so memorize them in a vector of int
  // because their number is known I can size it rather than 
  // to 'push_back' each value
  std::vector<int> finalStates(numberOfFinalStates);

  for (int & ft : finalStates) {
    if (! (fin >> ft)) {
      std::cerr << "invalid file reading final states" << std::endl;
      return -1;
    }
  }

  int numberOfTransitions;

  if (!(fin >> numberOfTransitions) || (numberOfTransitions < 0))  {
    std::cerr << "invalid file reading the number of transitions" << std::endl;
    return -1;
  }

  // you say a transition contains 2 int and a char,
  // I define a structure for
  // i1 i2 and c are 'poor' names but I don't know their goal
  struct Transition {
    int i1, i2; 
    char c;
  };

  // the transitions saved in a vector
  std::vector<Transition> transitions(numberOfTransitions);

  for (Transition & tr : transitions) {
    if (!(fin >> tr.i1 >> tr.i2 >> tr.c)) {
      std::cerr << "invalid file reading transitions" << std::endl;
      return -1;
    }
  }

  // print to check

  std::cout << "numberOfStates=" << numberOfStates << std::endl;
  std::cout << "numberOfSymbols=" << numberOfSymbols << std::endl;
  std::cout << "numberOfFinalStates=" << numberOfFinalStates << "\nfinalStates:";
  for (int ft : finalStates) 
     std::cout << ' ' << ft;
  std::cout << std::endl;
  std::cout << "numberOfTransitions=" << numberOfTransitions
    << "\ntransitions:" << std::endl;
  for (const Transition & tr : transitions)
    std::cout << '\t' << tr.i1 << ' ' << tr.i2 << ' ' << tr.c << std::endl;

  return 0;
}

编译与执行:

pi@raspberrypi:/tmp $ g++ -pedantic -Wextra -Wall a.cc
pi@raspberrypi:/tmp $ cat inputFile.txt
10 
3 
1 
9 
12 
0 1 f 
0 3 f 
1 2 a 
2 9 f 
3 4 f 
3 8 f 
4 5 b 
5 6 f 
6 7 a 
8 9 f 
pi@raspberrypi:/tmp $ ./a.out
invalid file reading transitions

出现错误是因为文件仅包含 10 个转换而不是预期的 12 个,修改文件以预期有 10 个转换:

pi@raspberrypi:/tmp $ ./a.out
numberOfStates=10
numberOfSymbols=3
numberOfFinalStates=1
finalStates: 9
numberOfTransitions=10
transitions:
    0 1 f
    0 3 f
    1 2 a
    2 9 f
    3 4 f
    3 8 f
    4 5 b
    5 6 f
    6 7 a
    8 9 f
pi@raspberrypi:/tmp $ 

如果你有可变数量的东西(在运行时定义)你使用数组:

std::vector<Type>   store;

要向矢量添加内容,您可以使用 push_back()(还有其他方法,但让我们为初学者保持简单)。

store.push_back(value);

要读取多个内容并将它们存储在向量中,只需使用循环即可。

for(int loop = 0; loop < numberOfThings; ++loop) {
    Type  temp;
    fin >> temp;
    store.push_back(temp);
}

那么这个神秘的东西是什么Type?您在这里使用适当的类型名称。对于 "Finale State",它将是一个整数 (int),但对于 "Transition",它将是一个匹配 (int/int/char).[=18= 的 class 类型]

 std::vector<int>   finalState;
 for(int loop = 0; loop < finalState; ++loop) {
     int nextFinal;
     find >> nextFinal;
     finalState.push_back(nextFinal);
 }

 ......
 std::vector<Transition>  Transitions;
 ... Just like above.

有点晚了,但我还是会 post 展示如何创建自己的流运算符并在创建复合时使用它们 类。

#include <iostream>
#include <fstream>
#include <vector>

struct transition {
    // rename the variables into something meaningful
    int int1;
    int int2;
    char a_char;

    friend std::istream& operator>>(std::istream&, transition&);
    friend std::ostream& operator<<(std::ostream&, const transition&);
};
// input stream function for reading one transition
std::istream& operator>>(std::istream& is, transition& t) {
    is >> t.int1 >> t.int2 >> t.a_char;
    return is;
}
// output stream function for writing one transition
std::ostream& operator<<(std::ostream& os, const transition& t) {
    os << t.int1 << " " << t.int2 << " " << t.a_char;
    return os;
}
//-----------------------------------------------------------------------------
struct entity {
    int numberOfStates;
    int numberOfSymbols;
    std::vector<int> finalStates;
    std::vector<transition> transitions;

    friend std::istream& operator>>(std::istream&, entity&);
    friend std::ostream& operator<<(std::ostream&, const entity&);
};
// read one entity from a stream
std::istream& operator>>(std::istream& is, entity& e) {
    int numberOfFinalStates, numberOfTransitions;
    int value;

    if(is >> e.numberOfStates >> e.numberOfSymbols >> numberOfFinalStates) {
        // read to value and put it in its vector
        while(numberOfFinalStates-- && is >> value) e.finalStates.push_back(value);

        if(is >> numberOfTransitions) {
            transition ttmp;
            // read to the temporary transition and put it in its vector
            while(numberOfTransitions-- && is >> ttmp) e.transitions.push_back(ttmp);
            // check that we got the number of values we wanted
            // and set the failbit if we didn't (should check size() of the vectors
            // instead)
            if(numberOfFinalStates != -1 || numberOfTransitions != -1)
                is.setstate(std::ios_base::failbit);
        }
    }
    return is;
}
// write one entity to a stream
std::ostream& operator<<(std::ostream& os, const entity& e) {
    os << e.numberOfStates << "\n" << e.numberOfSymbols << "\n" << e.finalStates.size() << "\n";
    for(const int fs : e.finalStates) os << fs << "\n";
    os << e.transitions.size() << "\n";
    for(const transition& t : e.transitions) os << t << "\n";
    return os;
}
//-----------------------------------------------------------------------------
int main() {
    std::ifstream fs("inputfile.txt");
    if(fs) {
        entity e;
        // stream the opened file into the entity 
        if(fs >> e) {
            std::cout << "loaded these values:\n";
            std::cout << e;
        } else {
            std::cerr << "failed loading file\n";
        }
    } else {
        std::cerr << "failed opening file\n";
    }
}