1

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?

AnR
  • 81
  • 7
  • Without answering your question: just put an `outputFile` at the beginning of each codeline, and a `;` at the end of each code-line (right after the `endl`), and you're done. – barak manos May 30 '16 at 12:01
  • 1
    It is undefined behaviour to use `++` on the same variable in the same statement (roughly speaking, there are a bunch of special cases too big to fit in a comment). To avoid this use more semicolons, or write `index + 1`, `index + 2` etc. – M.M May 30 '16 at 12:30

1 Answers1

0

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.

Binary Birch Tree
  • 15,140
  • 1
  • 17
  • 13