help with ofstream

Hi all!
I have been trying to correctly run the program since yesterday evening but still no progress yet.
My problem is actually related to the stream output of a vector onto a file.
It is wierd because my program streams to two different files and only one of them is streamed correctly, although I'm using the same syntax.
Basically, my program asks the user to write on screen the name of a file which stores some numbers data, it lets you choose how many numbs to analyze and first of all prints on screen and on ("before.dat") those numbers, then it sorts them from the lowest to the highest and prints again the sorted data on screen and on ("after.dat"). What does not work is the output stream on ("before.dat"), which remains empty at the end of the prog.

I'll show you right here my two codes, main.cpp and Vettore.h:


Vettore.h
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#ifndef __Vettore_h__
#define __Vettore_h__	
#include <fstream>

using namespace std;

struct Vettore{
	unsigned int size;
	double* v;
};

struct Vettore read(unsigned int size, const char* filename){
	struct Vettore vec;
	vec.size = size;
	vec.v = new double [size];
	ifstream input(filename);
		for(unsigned int i=0;i<size;i++){
			input>>vec.v[i];
		}
    return vec;
};


void scambia(double *, double *); 


bool sortcheck(int* a, int n){   
    for (int i = 0; i < n - 1; i++{         
        if (a[i] == a[i + 1])
		return true;
    }
    return false;
}



void print(struct Vettore vec){
	int* a=new int[vec.size];
	
	std::ofstream before("before.dat");
	std::ofstream after("after.dat");
	//std::ofstream before.open("before.dat");    I've tried this way but still no result
	//std::ofstream after.open("after.dat");
		for(int k=0;k<vec.size;k++){
			for(int h=k+1;h<vec.size;h++){
				if(vec.v[k]<vec.v[h]||vec.v[k]==vec.v[h])     //state if numbers on vector have already been sorted
					a[k]=0;
				else
					a[k]=1;
			}	
		}

			if(sortcheck(a,vec.size) == true){             //condition to stream on ("before.dat") or ("after.dat")
					for(int j=0;j<vec.size;j++){
						after<<vec.v[j]<<endl;
						std::cout<<vec.v[j]<<endl;
					}
			after.close();
			}
			
			
			else{
					for(int d=0;d<vec.size;d++){
						before<<vec.v[d]<<endl;
						std::cout<<vec.v[d]<<endl;
				}
			before.close();
			}
	delete[] a;
	
	
}


void sort(struct Vettore vec){
	for(int k=0;k<vec.size;k++){
    		for(int h=k+1;h<vec.size;h++){
        		if(vec.v[k]>vec.v[h])
            		scambia(&vec.v[k],&vec.v[h]);   
		
        	}
	}

}


void scambia(double *a, double *b){ 
    double c;
     c= *a;
    *a = *b;
    *b = c;  
    return;
}




#endif 




main.cpp
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

#include <iostream>
#include <fstream>
#include <cmath>
#include "Vettore.h"

using namespace std;


void sort(struct Vettore);

void print(struct Vettore);


int main(){
Vettore carica;
int a;
unsigned int size=pow(10,6);
char nomefile[20];
cout<<"Inserisci il nome del file da leggere: "<<endl;	
cin>>nomefile;
ifstream in(nomefile);
	if(!in){
		cout<<"Il file non è stato caricato correttamente.. "<<endl;
		return -1;
	}
	else{
		cout<<"Il file è stato caricato correttamente! "<<endl;	
	}
cout<<endl;
cout<<"Vi sono 10E6 valori. Quanti se ne vogliono analizzare? "<<endl;
cin>>a;
double *vet=new double[a];
carica.size=a;
carica.v=vet;
carica=read(a,nomefile);
cout<<"I dati prima dell'odinamento sono: "<<endl;   //data stream before sorting
print(carica);
sort(carica);
cout<<"I dati dopo l'ordinamento sono: "<<endl;   //data stream after sorting, overloading the same func.
print(carica);

return 0;
}


Ask me if you need other infos.
Any help would be really appreciated!
Have a good day!
Last edited on
In function print() both files are opened for output, which means any previous contents is deleted, and an empty file is created.
1
2
	std::ofstream before("before.dat");
	std::ofstream after("after.dat");


Try to open only the file you will actually use - do it further down in the function after you have decided which one.

Hi, thanks for the reply!

you mean smthg like this?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
if(sortcheck(a,vec.size) == true){             
                                       std::ofstream after("after.dat");
					for(int j=0;j<vec.size;j++){
						after<<vec.v[j]<<endl;
						std::cout<<vec.v[j]<<endl;
					}
			after.close();
			}
			
			
			else{
                                     std::ofstream before("before.dat");
					for(int d=0;d<vec.size;d++){
						before<<vec.v[d]<<endl;
						std::cout<<vec.v[d]<<endl;
				}
			before.close();
			}



"before.dat" is still empty at the end!
Last edited on
Yes, that looks like what I meant.

There may be a problem somewhere else in the code.
Perhaps here:
1
2
3
4
5
6
7
8
9
bool sortcheck(int* a, int n)
{   
    for (int i = 0; i < n - 1; i++)
    {         
        if (a[i] == a[i + 1])
		return true;
    }
    return false;
}

It might work better like this:
1
2
3
4
5
6
7
8
9
bool sortcheck(int* a, int n)
{   
    for (int i = 0; i < n - 1; i++)
    {
        if (a[i] > a[i + 1])
            return false;
    }
    return true;
}

It worked mate, thanks!

What was wrong with the previous bool statement I made?
What was wrong with the previous bool statement I made?

The original version of sortcheck() was searching the array to find if any two consecutive elements were equal. If the aim was to check for duplicates, that might be useful - provided the array has already been sorted. But finding a pair of duplicated values has nothing to do with testing whether or not the array has been sorted.

Last edited on
Actually at the beginning of my print() func I create a generic dynamic array:

 
int* a=new int[vec.size]


whose aim is to be filled with 0 and 1 in relation with the order of vec.v[k] :

1
2
3
4
5
6
7
8
for(int k=0;k<vec.size;k++){
			for(int h=k+1;h<vec.size;h++){
				if(vec.v[k]<vec.v[h]||vec.v[k]==vec.v[h])  
					a[k]=0;
				else
					a[k]=1;
			}	
}


and sortcheck() is applied to that very a[k] array. So if every a[k] element is 0, it is meaning that my numbers has been sorted, otherwise it turns false. Anyway applying sortcheck() as you said directly onto vec.v[k] it is more efficient. I was so focused sorting out what was the problem with ofstream I didn't think about that!

So the program is working fine with your variation of sortcheck(), even if it is still applied to a[k] . IMHO the problem is related to returning values of sortcheck().. I will play on this thing and see what happens.
Thanks.
Actually I didn't examine the functioning of every part of the program. However, if the sole aim is to get the print function to output to the "before" and "after" files, why not use a single bool variable which will indicate which file is to be used, rather than having multiple arrays and loops? There is a lot of merit in keeping things simple.
Hi Chervil,
just want to update you with something new which is actually a bit curious:

Now print() function works like a charm and has been thinned out a lot since your suggestion:

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
void print(struct Vettore vec){

		if(sortcheck(vec.v, vec.size) == true){
				
			std::ofstream after("after.dat");

					for(int j=0;j<vec.size;j++){
						after<<vec.v[j]<<endl;
						std::cout<<vec.v[j]<<endl;
					}
			after.close();
		}
			
			
		else{
			std::ofstream before("before.dat");

					for(int d=0;d<vec.size;d++){
						before<<vec.v[d]<<endl;
						std::cout<<vec.v[d]<<endl;
					}
			before.close();
		}
	
	
}


and sortcheck() has been made a function of double*, which is:

1
2
3
4
5
6
7
bool sortcheck(double* a, int n){   
    for (int i = 0; i < n - 1; i++){         
        if (a[i] > a[i + 1])
		return false;
    }
    return true;
}


With this setting main.x works fine, printing properly all it has to print.

What is intriguing is reversing return values of sortcheck(). In fact, setting this one like:

1
2
3
4
5
6
7
bool sortcheck(double* a, int n){   
    for (int i = 0; i < n - 1; i++){         
        if (a[i] < a[i + 1] || a[i] == a[i+1])
		return true;
    }
    return false;
}


This create no "before.dat" file after the execution. It would be interesting finding out why this particular codification doesn't print anything on "before.dat" but prints only on screen (anyway "after.dat" is printed fine), like in the beginning.

Have a good day!

What is intriguing is reversing return values of sortcheck().

This create no "before.dat" file after the execution. It would be interesting finding out why


To get a return value of 'true', it would require only two consecutive values in the entire file to be in ascending order or to be identical. The only way it would give 'false' would be:
it is already sorted, but in descending order AND all the values are different.

On the other hand, in the 'correct' version, if the file supplied by the user is already sorted in ascending order, there would be no output in the "before.dat".

This dependence on the data may not be what is needed, if all you want is before and after, there may be other ways.

I created a modified version of the program, where I passed values by reference rather than by value or pointer where appropriate. References are useful either when the object is to be modified, or it is large, and creating a copy (which pass by value does) would be wasteful.

Vettore.h
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
#ifndef __Vettore_h__
#define __Vettore_h__   

struct Vettore {
    unsigned int size;
    double* v;
    bool sorted;
};

void init(Vettore& vec);


Vettore read(unsigned int size, const char* filename);


void scambia(double &, double &); 


void print(const Vettore& vec);


void sort(Vettore& vec);


#endif  


Vettore.cpp
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
70
71
72
73
#include "Vettore.h"
#include <fstream>
#include <iostream>

using namespace std;

void init(Vettore& vec)
{
    vec.size   = 0;
    vec.v      = nullptr;
    vec.sorted = false;
}


Vettore read(unsigned int size, const char* filename)
{
    Vettore vec;
    init(vec);
    
    vec.size = size;
    vec.v    = new double [size];
    
    ifstream input(filename);
    
    unsigned int i;
    for (i = 0; i<size && input>>vec.v[i] ; )
    {
        i++;
    }
    
    // not ideal, loses track of capacity
    
    if (i < vec.size)
        vec.size = i;
    
    return vec;
}

void print(const Vettore& vec)
{
    const char * fname = vec.sorted ? "after.dat" : "before.dat";
    std::ofstream fout(fname);
    
    for (unsigned int j=0; j<vec.size; j++)
    {
        fout << vec.v[j] << endl;
        std::cout <<vec.v[j] << endl;
    }
}



void sort(Vettore& vec)
{
    for (unsigned int k=0; k<vec.size; k++)
    {
        for (unsigned int h=k+1; h<vec.size; h++)
        {
            if (vec.v[k] > vec.v[h])
                scambia(vec.v[k], vec.v[h]);   
        }
    }
    
    vec.sorted = true;
}


void scambia(double & a, double & b)
{
    double c = a;
    a = b;
    b = c;  
}


main.cpp
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
#include <iostream>
#include <fstream>
#include "Vettore.h"

using namespace std;

int main()
{
    char nomefile[80];
    cout << "Inserisci il nome del file da leggere: \n";    
    cin >> nomefile;
    ifstream in(nomefile);
    if (!in)
    {
        cout << "Il file non è stato caricato correttamente.. \n";
        return 1;
    }
    else
    {
        cout << "Il file è stato caricato correttamente! \n\n"; 
    }
    
    cout << "Vi sono 10E6 valori. Quanti se ne vogliono analizzare? \n";
    
    unsigned int a;
    cin >> a;
    

    Vettore carica = read(a, nomefile);
    cout << "I dati prima dell'odinamento sono: \n"; // data stream before sorting
    print(carica);
    
    sort(carica);
    cout << "I dati dopo l'ordinamento sono: \n";    // data stream after sorting.
    print(carica);

}


This may at least give you some ideas to think about.
Last edited on
Topic archived. No new replies allowed.