open a thousand .dat files for input operations

Hi!
I would like a piece of advice about a program that I'm writing:
First part (that I can manage myself):
I've to call an input file.dat, a column of int numbers, find the maximum int among them and write it in another .dat file.
Second part:
I've to repeat the first part with other thousand input file of the same kind and print each found maximum in sequence in the same output dat file.
My input files have the same root and they're numbered from one to 1000.
I've tried to use that in my favor but so far my loops had been unsuccessful.
Suggestions are welcome:)
you could have a for loop to handle this. using the fstream library, open the file number and then proceed with your calculation function. once done close the fstream and repeat using a new number


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


int main()
{
    std::fstream fileinput;
    std::fstream fileoutput;
    fileoutput.open("input.dat");
    for(int i = 0; i <= 1000; ++i)
    {
        fileinput.open((dynamic_cast<std::ostringstream &>((std::ostringstream() << std::dec << i)).str()) + ".dat");
        //call to calculation function
        int x; //set this to whatever the maximum number is from the function you called
        fileoutput << x << '\n';
        fileinput.close();
    }
    fileoutput.close();
    return 0;
}


i like using that dynamic_cast call to convert an integer to string since Mingw is notorious for not supporting functions that convert integers to strings.

is that what you needed? opens a file called "1.dat" all the way up to "1000.dat" then gets that maximum int value you talked about and writes it to "input.dat"
Last edited on
 
fileinput.open(std::to_string(i) + ".dat");


? http://www.cplusplus.com/reference/string/to_string/
if it works for you sure you can use that. but i cant because every version of mingw i tried it never works. its a known bug.
first of all thank you for your attention!
unfortunately i can't use both to_string and dynamic_cast.
I've tried using instead :


1
2
3
4
5
6
7
8
9
10
std::fstream fileinput;
std::fstream fileoutput;
fileoutput.open("Z.dat",ios::out);
std::string rootName("auto_200_");
std::string extension(".dat");
    for(int i = 0; i<=999; i++)
{
std::stringstream ss(rootName);
ss<<i<<extension;
fileinput.open(ss.str().c_str(), ios::in);


but Z.dat results empty (the program works except for the for loop above), and i can't find why . (Please be patient, I don't use C++ often).
In any case thanks a lot for your suggestions.
considering you are using std::, ios::out should also be std::ios::out unless your compiler is ignoring it

the problem is how youre calling the stringstream.
the loop executes fine but it never opens the files due to incorrect naming.

after calling std::stringstream ss(rootName); when you insert new strings into it, they all ram up at the beginning and start erasing "auto_200_" so you need to add this after it;
ss.seekp(0, std::ios_base::end);
this tells the stringstream you want to append things to the end of it.
let me make an example. running the code you have there. because of how you called the stringstream, it would try to open a file called this 1.dat200_ all the way up to 999

another suggestion is calling fileinput.close(); at the end of the loop.

also is that your whole loop? the fstream fileoutput never gets called. enjoy :-)
Last edited on
if it works for you sure you can use that. but i cant because every version of mingw i tried it never works. its a known bug.

You could just write your own really then.

1
2
3
4
5
6
7
template<typename T>
std::string to_string(const T& value)
{
    std::ostringstream stream;
    stream << value;
    return stream.str();
}


Then you don't have that giant mess.

another suggestion is calling fileinput.close(); at the end of the loop.

The file stream's destroy calls close, so there is no point including that. Should put the std::fstream into the loop scope so that it is constructed and destroyed for each iteration.
Last edited on
Add a line to clear the filestream at the beginning of the loop.

fileinput.clear()

The first time through the loop this would not be necessary, but on all additional passes through the loop it is. This is because after reading in the input file the failbit will be set because of hitting end of file. The next time through the loop the call to fileinput.open() will fail unless you first clear the stream. The call to fileinput.close() at the bottom of the loop simply closes the stream but does not clear the failed state.

You get no output results because your files are suppose to be 1-1000 but your loop runs from 0 to 999. Consequently, the first time through the loop the call to fileinput.open() will fail because the file 0.dat does not exist. The remaining times through the loop fail because of not clearing the stream as described above. Change your for loop to:

ffor(int i = 1; i<=1000; i++)

Also, since you are only reading the input files and only writing to the output file, I would use ifstream and ofstream instead of fstream. That is,

1
2
    std::ifstream fileinput;
    std::ofstream fileoutput;


sorry for the late reply.
the program i wrote is a bit redundant but the problem is that if i call the fstream fileoutput inside the for loop (including the if statement) then i get ./a.out :
*** glibc detected *** ./a.out: double free or corruption (out):(...).
Else i have only one correct output ( the first maximum).
here the program with some of your suggestions:
(in this condition i get from it the first correct value)


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
#include <fstream>
#include <sstream>
#include<iostream>
#include<string>
#include<new>
#include <stdio.h>
#include <stdlib.h>
using namespace std;
int main()
{
std::ifstream fileinput;
std::ofstream fileoutput;
fileoutput.open("Z.dat",std::ios::out);
std::string rootName("auto_200_");
std::string extension(".dat");
std::stringstream ss(rootName);
    for(int i=0; i<=999; i++)//labels of my files are from 0 to 999
//it reads only the input file i=0,the output has only the first (correct) maximum
{
std::stringstream ss(rootName);
ss.seekp(0, std::ios_base::end);
ss<<i<<extension;
fileinput.open(ss.str().c_str(),std::ios::in);
fileinput.clear();//if i keep it at the beginning of the loop the output results a small group of nonsense values in one row;
}
int n, max;
int m=200;//each file has a column of 200 int in it.
int*p= new int[m];
if (fileinput.is_open()){
max=p[0];
for (n=0; n<=m; n++)
{
fileinput>>p[n];
}
for (n=0; n<=m; n++)
{
if (p[n]>max)
{
max=p[n];
}
}
fileoutput<<max<< endl;
fileinput.close();
delete[] p;
}
//} if i put here the parenthesis (instead that  at line 25):./a.out Aborted (core dumped)
fileoutput.close();
return 0;
}


I really appreciate any help you can provide to make it work properly.


Proper formatting goes a long way to making your code more readable.

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
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
#include <new>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

int main()
{
    std::ifstream fileinput;
    std::ofstream fileoutput;
    fileoutput.open("Z.dat",std::ios::out);
    std::string rootName("auto_200_");
    std::string extension(".dat");
    std::stringstream ss(rootName);
    for(int i=0; i<=999; i++)//labels of my files are from 0 to 999
    //it reads only the input file i=0,the output has only the first (correct) maximum
    {
        std::stringstream ss(rootName);
        ss.seekp(0, std::ios_base::end);
        ss<<i<<extension;
        fileinput.open(ss.str().c_str(),std::ios::in);
        fileinput.clear();//if i keep it at the beginning of the loop the output results a small group of nonsense values in one row;
    }

    int n, max;
    int m=200;//each file has a column of 200 int in it.
    int*p= new int[m];

    if (fileinput.is_open())
    {
        max=p[0];
        for (n=0; n<=m; n++)
        {
            fileinput>>p[n];
        }
        for (n=0; n<=m; n++)
        {
            if (p[n]>max)
            {
                max=p[n];
            }
        }
        fileoutput<<max<< endl;
        fileinput.close();
        delete[] p;
    }

    //} if i put here the parenthesis (instead that  at line 25):./a.out Aborted (core dumped)

    fileoutput.close();
    return 0;
}


You only get one output cause the code that does the output only runs for one iteration of the for loop, the last one. All it does is open files for 1000 loops.
Last edited on
(I'm sorry to bother again)
Maintaining the call of the fstream output outside the loop is simply the only way in which i get at least one of my values, otherwise, from
(the beginning is still the same a part from std::ifstream fileinput; that i put inside the for loop)


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
for(int i=0; i<=999; i++)
    
{       std::ifstream fileinput;
        fileinput.clear();
        std::stringstream ss(rootName);
        ss.seekp(0, std::ios_base::end);
        ss<<i<<extension;
        fileinput.open(ss.str().c_str(),std::ios::in);
     
   if (fileinput.is_open())
{
        int m=199;\\ a column of 200 int in each file   
        int*p= new int[m]; 
        int max=p[0];

        for (int n=0; n<=m; n++)
        {
            fileinput>>p[n];
        }
        for ( int n=0; n<=m; n++)
        {
            if (p[n]>max)
            {
                max=p[n];
            }
        }

        delete [] p;
        fileoutput<<max<< '\n';
        fileinput.close();

}
 
}   
    fileoutput.close();
    return 0;
}



i get stuck , after compiling and running, on
*** glibc detected *** ./a.out: double free or corruption (out): 0x084e3778 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb7507ee2]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdlPv+0x1f)[0xb770451f]
/usr/lib/i386-linux-gnu/libstdc++.so.6(_ZdaPv+0x1b)[0xb770457b]
./a.out[0x8049151](...)
I don't know why you keep clumping the input and output files together, they are different objects and you are using them differently. You want the output for the 1000 files to go into 1 file, so the output stream needs to exist for most of the processing. The input file though, you only need 1 open at a time per iteration so there is no point putting it with the output file as it has different conditions for when it needs to be opened. Just seems like you are guessing at this point instead of thinking it through.
Last edited on
p.s. the program (finally) works,
the problem was the memory freeing (that needed to be done at the beginning of the if statement to consent the following for loop to iterate).
thank you all for your precious help and patience.
Registered users can post here. Sign in or register to post.