Formatted file i/o C++

Dear forum members,

I am trying to read values form a file. This file contains information, which in this case are the values of a 3D array printed in consecutive row major order. I would like to do this in C++ because the file of interest contains input values for a code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
                              
OUTPUT
  0.00000E+00 0.0000  8.43491E-05 0.0250  2.94670E-04 0.0152  4.90358E-04 0.0125                                                       
  6.26345E-04 0.0114  7.74623E-04 0.0105  8.98075E-04 0.0099  9.79706E-04 0.0096                                                       
  1.45915E-03 0.0081  1.74192E-03 0.0075  1.76209E-03 0.0075  1.93559E-03 0.0073                                                       
  2.65306E-03 0.0064  3.65692E-03 0.0056  5.57118E-03 0.0048  3.71082E-03 0.0059                                                       
  2.54021E-03 0.0071  1.43419E-03 0.0093  1.16088E-03 0.0103  6.76763E-04 0.0133                                                       
  6.05615E-04 0.0140  8.52321E-04 0.0121  1.26925E-03 0.0102  2.17764E-03 0.0082                                                       
  2.21395E-03 0.0083  2.12044E-03 0.0085  8.05969E-04 0.0132  6.45110E-04 0.0145                                                       
  4.06056E-04 0.0184  2.15940E-04 0.0248  2.23400E-04 0.0242  2.18335E-04 0.0245                                                       
  2.21986E-04 0.0248  2.15700E-04 0.0243  2.10151E-04 0.0246  2.11413E-04 0.0246                                                       
  2.12557E-04 0.0246  1.12309E-03 0.0114  1.37886E-03 0.0105  3.15171E-03 0.0071                                                       
  2.04217E-03 0.0089  2.22401E-03 0.0084  1.75533E-03 0.0093  7.06136E-03 0.0048                                                       
  4.66999E-03 0.0060  4.87212E-03 0.0057  5.30643E-03 0.0055  4.72222E-03 0.0060                                                       
  7.44688E-03 0.0048  1.06316E-02 0.0041  1.12392E-02 0.0041  5.74326E-03 0.0056                                                       
  5.91508E-03 0.0056  6.08567E-03 0.0055  6.20051E-03 0.0055  6.99435E-03 0.0052                                                       
  7.37151E-03 0.0051  7.71207E-03 0.0051  8.42368E-03 0.0049  9.29420E-03 0.0047                                                       
  1.09574E-02 0.0043  1.35550E-02 0.0040  1.81639E-02 0.0035  2.04761E-02 0.0033                                                       
  3.04043E-02 0.0028  2.75128E-02 0.0029  2.96637E-02 0.0029  2.66582E-02 0.0031                                                       
  1.24927E-02 0.0046  3.04761E-03 0.0093  3.69574E-01 0.0010  0.00000E+00 0.0000                                                       
  1.49738E-04 0.0189  5.44993E-04 0.0112  8.78235E-04 0.0092  1.16637E-03 0.0083                                                       
  1.43145E-03 0.0077  1.62997E-03 0.0073  1.81273E-03 0.0070  2.68732E-03 0.0059                                                       
  3.19177E-03 0.0055  3.24833E-03 0.0055  3.53991E-03 0.0054  4.91611E-03 0.0047                                                       
  6.74385E-03 0.0042  1.02937E-02 0.0035  6.93213E-03 0.0043  4.72209E-03 0.0052     



As you can see, these values are following a regular pattern. Doing this in FORTRAN is rather simple, there you have the concept of implied loops and file formats. So the corresponding code would be:

1
2
read(FILE_NUMBER,'(4(ES13.5,F7.4))') ((REACT(i,k),DUMMY, k = 1,COL), i=1,ROW) 
write(FILE_NUMBER,'(4(ES13.5,F7.4))') ((REACT(i,k),DUMMY, k = 1,COL), i=1,ROW)


The format descriptor '(4(ES13.5,F7.4))' tells the code that the array is not on one line only, but is stored in 4 values on each row (precision 5 digits and buffer width 13), where each value is followed by uninteresting to us number red in the buffer DUMMY (precision 4 values buffer width 7).


Is it possible to do this in C++, I presume it is. However I was not able to find information about it. I tried browsing the other topics on the forum, unfortunately it seems that nobody have done such things. I would appreciate any help on the topic.
Last edited on
This looks like scientific notation.

Please read here:
http://www.cplusplus.com/reference/iostream/manipulators/scientific/
wronski123 wrote:
Is it possible to do this in C++, I presume it is.


There is no corresponding method to specify the format of a file in C++.


@pogrady:

That's for manipulating output from a stream. It doesn't have anything to do with reading from or specifying the format of a file.
Is it possible to do this in C++,
Yes, it is possible to read your file and to output a similar file in C/C++.

However I was not able to find information about it.
Reading each line into a structure, vector, or array is fairly straight forward since each item is separated by a white space character. You can use the extraction operator>> to extract each item and place it into the corresponding element. You may want to study up on basic C++ file input and output. http://www.cplusplus.com/doc/tutorial/files/

Writing the file is also fairly simple using the io manipulators. Your odd columns are in scientific notation and have a width of 13 and a precision of 5, the even columns are in a fixed format and have a width of 7 and a precision of 4.

Jim
Last edited on
So, to answer the question, yes it is possible, use ifstream to "Input from File". You will have to work out exactly how to deal with the whole scientific notation thing, but it is easy enough to make your own function that deals with that.

http://www.cplusplus.com/reference/iostream/ifstream/

on second thought, the whole scientific notation thing will complicate how you will write your code though. I don't use fortran, so is it possible to rewrite the file from there so that the numbers are stored as regular notation? that will just save you some headache in transferring from char to floating point numbers, and might save your computer some processing time.

It all depends on how much work you're willing to put in and how much experience you have in C++.
Last edited on
Hi Jim,


Can you provide sime example for this. I would be very grateful. Is it possible to use such an empty buffer like in the FORTRAN case?
Last edited on
Why do you need to transfer from char to floating point numbers. The extraction operator>> knows how to extract numbers that are stored in scientific notation format to doubles. 1.45915E-03 is a valid floating point number.
Last edited on
Did you read the link I posted about C++ file input and output?

Basically you read each column into a variable. The following example should read a single line of your file into 8 separate variables.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>

int main()
{
   std::ifstream fin("YourFileName");
   if(!fin)
   {
       std::cout << "Error opening the file" << std::endl;
       return(1);
   }
   double one, two, three, four, five, six, seven, eight;
   fin >> one >> two >> three >> four >> five >> six >> seven >> eight;

   // Now just print them.
   std::cout << one << '\t' << two << '\t' << three << '\t' << four << '\t' << five << '\t' 
                  << six  << '\t' << seven << '\t' << eight << std::endl;

   return(0);
}


You of course will probably want to use a vector, array or a structure to hold each of these items.

Last edited on
Hi,

Well i know how to do that, thanks for the feedback however. I think i am not expressing myself clear enough.

I am not much aware how things are done in C++, but in FORTRAN one needs to have an empty buffer which might be a real number. It is used to store the values which are of no interest. In my case I am not interested in the numbers written in normal format, which are trailing the values written in scientific notation. In general i am not talking about cast form char to float. I am just asking how to get rid of the trailing numbers.

In general ignore the scientific notation, what i do not understand is how to loop the array and have only fixed number of values on each line, and how to get rid of the values i do not need, and which are sitting in between.

Last edited on
In C++ you will need to read the complete line into variables, if you don't want to use some of the elements then you just ignore those elements, after reading them in.
Last edited on
I looked at this in two different ways. In a language such as COBOL, the defining of a layout to match the line of data is very easy. In C++ too it is possible, using a data structure, to match the 13 and 7 character fields, repeated four times.

However, the resulting code ended up being longer and more complex than just using the ordinary C++ formatted input.

Example code the second way:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

    using namespace std;

void getdata(istream & f, vector<double> &);

int main()
{
    char filename[] = "fortran_data.txt";

    ifstream fin(filename);
    if (!fin.good())
    {
        cout << "File not open: " << filename << endl;
        return 0;
    }

    vector<double> numbers;

    getdata(fin, numbers);

    for (int i=0; i<numbers.size(); ++i)
    {
        cout << i << " " << numbers[i] << endl;
    }

    return 0;
}

void getdata(istream & f, vector<double> & nums)
{
    string   line;

    while (getline(f, line))
    {
        stringstream ss(line);

        double n;
        double dummy;

        ss >> n >> dummy;
        while (ss.good())
        {
            nums.push_back(n);
            ss >> n >> dummy;
        }
    }
}


output (abbreviated):
0 0
1 8.43491e-05
2 0.00029467
3 0.000490358

...

84 0.00674385
85 0.0102937
86 0.00693213
87 0.00472209


The function call at line 24 reads the data into a vector of doubles.
At line 38, a whole line is read, and then a stringstream (extremely useful tool) is made from the line.

Line 45 (and 49), the required value n and unwanted value dummy are extracted.
Line 48, the wanted value is stored.

Finally, at lines 26 to 29 the contents of the vector are displayed.
Last edited on
Since you have supplied your version, here is what I came up with to read and print the file.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
#include <array>

int main()
{
   std::ifstream fin("fortran.txt");
   if(!fin)
      return(1);
   std::string line;
   // A data struture to hold the file information.
   std::vector<std::array<double, 8>> vct;
   size_t vidx = 0;
   // Read the file.
   while(getline(fin, line) )
   {
      std::istringstream sin(line);
      vct.push_back(std::array<double, 8>());
      vidx = vct.size() - 1;
      size_t i = 0; // Reset on each loop.
      while(sin >> vct[vidx][i++])
      { /*empty body */}
   }

   // Print the information, like the input file.
   for(size_t i = 0; i < vct.size();++i)
   {

      for(size_t j = 0; j < vct[0].size(); j+=2)
      {
         std::cout << std::scientific << std::setprecision(5)
                  << std::setw(13) << vct[i][j]
                  << std::fixed << std::setprecision(4)
                  << std::setw(7) << vct[i][j+1];
      }
      std::cout << std::endl;
   }
   return(0);
}

Note: This probably requires a C++11 compiler.
wronski123 wrote:
I am just asking how to get rid of the trailing numbers.


You could use the code from jlb above, and simply ignore the values you don't want:

1
2
3
4
5
double one, two, three, four, five, six, seven, eight;
fin >> one >> two >> three >> four >> five >> six >> seven >> eight;

// Now just print them.
std::cout << one << ' ' << three << ' ' << << five << ' ' << seven << std::endl;
How 'bout a data structure and some operator overloading? The code for reading from the file resides in lines 46-61.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>

struct row
{
    const static unsigned nValues = 4 ;

    double values[nValues] ;

    // for notational convenience:
    double& operator[](unsigned i) { return values[i]; }
    double operator[](unsigned i) const { return values[i]; }
};

std::ifstream& operator>>(std::ifstream& is, row& r) ;
std::ifstream& operator>>(std::ifstream& is, std::vector<row>& rows) ;
std::ifstream& skip_to_output_section(std::ifstream& is) ;

int main()
{
    std::vector<row> rows ;

    std::ifstream in("data.txt") ;

    if ( skip_to_output_section(in) )
    {
        in >> rows ;

        std::cout << "Rows: " << rows.size() << "\t Total elements: " 
                  << rows.size()*row::nValues << '\n' ;

        std::cout << std::scientific ;
        for ( unsigned i=0;  i<rows.size(); ++i )
        {
            for (unsigned j=0; j < row::nValues; ++j )
                std::cout << rows[i][j] << '\t' ;
            std::cout << '\n' ;
        }
    }
}

// extract a row from the stream.
std::ifstream & operator>>(std::ifstream & is, row & r )
{
    float dummy ;
    for ( unsigned i=0; i < row::nValues; ++i )
        is >> r.values[i] >> dummy ;
    return is ;
}

// extract all rows from the stream
std::ifstream & operator>>(std::ifstream & is, std::vector<row>& rows)
{
    row input ;
    while ( is >> input )
        rows.push_back(input) ;
    return is ;
}

std::ifstream & skip_to_output_section(std::ifstream& is)
{
    std::string token ;
    while ( is >> token && token != "OUTPUT" )
        ;
    return is ;
}}

Output:
Rows: 22         Total elements: 88
0.000000e+000   8.434910e-005   2.946700e-004   4.903580e-004
6.263450e-004   7.746230e-004   8.980750e-004   9.797060e-004
...

Hi all,


Thanks for your help. I like the answer of cire very much. However I don't understand why the overloaded >> returns ifstream. Cire can you explain tht to me pls.
Thanks,
Last edited on
Topic archived. No new replies allowed.