I want to write several lines to a file. Each line has an index (running index). My code is:
ofstream outputFile;
int index = 0;
outputFile << ++index << ") FirstLine" <<endl
<< ++index << ") SecondLine" <<endl
...
<< ++index << ") LastLine" <<endl;
Problem is that I get no running index. That is, all lines has the same index (which is the total lines number). So my questions are firstly, how does ofstream work (meaning why do I get the described result). Secondly, what should I do to get it work?
Firstly, how does ofstream work (meaning why do I get the described result)?
According to the C++ standard (section 1.9, clause 15):
Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced.
If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, and they are not potentially concurrent, the behavior is undefined.
Applied to your case:
The evaluation of the ++index
statements (which are operands to the <<
operator) is unsequenced.
++index
modifies the value of index
, and therefore has a side effect on a scalar object.
As such, the behavior is undefined.
Secondly, what should I do to get it work?
One simple option would be to split the single large output expression into multiple lines, such that each ++index
statement is on a separate line.
Alternatively, you could both solve the problem and reduce repetition by using a loop.
For example:
#include <array>
#include <iostream>
#include <string>
int main () {
static const std::array<std::string, 3> lines = {
"First line",
"Second line",
"Last line",
};
for (int i = 0; i < lines.size(); ++i) {
std::cout << i + 1 << ") " << lines[i] << std::endl;
}
}
Save this as example.cc
, and compile using:
clang++ -std=c++14 example.cc -o example
Then run the example:
$ ./example
1) First line
2) Second line
3) Last line
Note that this prints to standard output to simplify the example, but std::cout
can be easily replaced with an instance of std::ofstream
depending on your use case.