I want to read an input file in C++ which includes the following lines
- numberOfStates
- numberOfSymbols
- numberOfFinalStates
- list of final states (one per line)
- numberOfTransitions
- listOfTransitions (one per line. The transitions include two ints and one char)
It's important to say that the numbers are different in each input file. I have to read a different amount of lines for each file.
This is an example inputFile
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
How can I declare each variable while reading the input file?
This is where I'm stuck.. don't really know what to do
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;
}
I'd like to work with vectors if possible.
doing
while (fin >> name >> var1 >> var2 >> var3) { cout << name << var1 << var2 << var3 << endl; }
you rewrite all the time on the same variables, you need to put the value in a vector as you say in your question
you need also to check if each input is correct, currently you do not detect the invalid input
and of course you need to check you open the file
Example :
#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;
}
Compilation and execution :
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
The error comes because the file contains only 10 transitions rather than 12 expected, modifying the file to expect 10 transitions :
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 $