txt file to struct, or struct to txt file?

Having issues. I have the below code. I am to prompt the user for 3 file names and then push the data to those 3 txt files and then display the first 50 to verify the data is good. Then I have to print some data relating to clicks and such. Right now I can prompt for each file name, and then push the correct data to each file name however, I think it would be better to push the data into the struct, and then print from the struct as then I can also go back and print the data related to clicks and such. I know I am missing something, but I can't seem to get my data into the structs.

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#include <iostream>
#include <string>
#include <fstream>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <iomanip>
#include <string>

using namespace std;
double random(double minprice, double maxprice);
string printRandomString(int n);
bool coinToss();
int clicks();
int runme();
int createfiles(int z);

struct Things{
Things();

    int id;
    string name;
    string category;
    double price;
    bool two_day_shipping;
    int numclicked;
};

int main()
{

    for(int z=0; z<3; z++)
   {
    createfiles(z);
    }
}

int createfiles(int z)
{
string file_out;
ofstream fout;
cout << "Please enter name of output file ending in .txt :" ;
cin >> file_out;
cout  << "\n\n";
ofstream outfile(file_out,ios::out);

fout.open(file_out.c_str( ) );

bool two_day_shipping;

srand(time(NULL));
 outfile << left << setw(7) << "id"
            << left << setw(15) << "name"
            << right << setw(15)<< "price"
            << "     "
            << right  << setw(15)<< "category"
            << "     "
            << left << setw(15) << "2D ship"
            << left << setw(15) << "number of clicks" << endl;

for(int j=0; j<1000; j++)
    {
    string category;
    double price;
    int id;
    int click;
    int cat;
    cat = rand() % 6 +1;
    double minprice;
    double maxprice;
    cout << fixed << setprecision(2);
    id = j;
    int n;
    string name;
    switch (cat){

    case 1:
        category = "Electronics";
        minprice = 35;
        maxprice = 1500;
        price = random (minprice,maxprice);
        n= 5 + (rand()%4);
        name = printRandomString(n);
        two_day_shipping= coinToss();
        click = clicks();
        outfile << left << setw(7) << id
            << left << setw(15) << name
            << right << setw(15)<< price
            << "     "
            << right  << setw(15)<< category
            << "     "
            << left << setw(15) << two_day_shipping
            << left << setw(15) << click << endl;

        break;

    case 2:
        category = "Clothing";
        minprice = 45;
        maxprice = 550;
        price = random (minprice,maxprice);
        n= 5 + (rand()%4);
        name = printRandomString(n);
        two_day_shipping= coinToss();
        click = clicks();
        outfile << left << setw(7) << id
            << left << setw(15) << name
            << right << setw(15)<< price
            << "     "
            << right  << setw(15)<< category
            << "     "
            << left << setw(15) << two_day_shipping
            << left << setw(15) << click << endl;
        break;

    case 3:
        category = "Footwear";
        minprice = 99;
        maxprice = 399;
        price = random (minprice,maxprice);
        n= 5 + (rand()%4);
        name = printRandomString(n);
        two_day_shipping= coinToss();
        click = clicks();
        outfile << left << setw(7) << id
            << left << setw(15) << name
            << right << setw(15)<< price
            << "     "
            << right  << setw(15)<< category
            << "     "
            << left << setw(15) << two_day_shipping
            << left << setw(15) << click << endl;
        break;

    case 4:
        category = "Books";
        minprice = 7;
        maxprice = 45;
        price = random (minprice,maxprice);
        n= 5 + (rand()%4);
        name = printRandomString(n);
        two_day_shipping= coinToss();
        click = clicks();
        outfile << left << setw(7) << id
            << left << setw(15) << name
            << right << setw(15)<< price
            << "     "
            << right  << setw(15)<< category
            << "     "
            << left << setw(15) << two_day_shipping
            << left << setw(15) << click << endl;
        break;

    case 5:
        category = "Appliances";
        minprice = 150;
        maxprice = 600;
        price = random (minprice,maxprice);
        n= 5 + (rand()%4);
        name = printRandomString(n);
        two_day_shipping= coinToss();
        click = clicks();
        outfile << left << setw(7) << id
            << left << setw(15) << name
            << right << setw(15)<< price
            << "     "
            << right  << setw(15)<< category
            << "     "
            << left << setw(15) << two_day_shipping
            << left << setw(15) << click << endl;
        break;

    case 6:
        category = "Apps";
        minprice =.5;
        maxprice = 4.99;
        price = random (minprice,maxprice);
        n= 5 + (rand()%4);
        name = printRandomString(n);
        two_day_shipping= coinToss();
        click = clicks();
        outfile << left << setw(7) << id
            << left << setw(15) << name
            << right << setw(15)<< price
            << "     "
            << right  << setw(15)<< category
            << "     "
            << left << setw(15) << two_day_shipping
            << left << setw(15) << click << endl;
        break;
}
}

};


double random(double minprice, double maxprice)
{
    double price;
    price = ((double)rand()/RAND_MAX)* (maxprice-minprice)+minprice;
    return price;
}


string printRandomString(int n)
{
    const int MAX = 26;
    char alphabet[MAX] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
                          'h', 'i', 'j', 'k', 'l', 'm', 'n',
                          'o', 'p', 'q', 'r', 's', 't', 'u',
                          'v', 'w', 'x', 'y', 'z' };

    string res = "";
    for (int i = 0; i < n; i++)
        res = res + alphabet[rand() % MAX];
    return res;
}

bool coinToss()
{
    return rand() % 2;
}


int clicks()
{
    int x;
    x = rand()%10000;
    return x;
}

Hello spelledwrong,

A few thing to start with although I have not fully tested the program.

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
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
//#include <string.h>  // <--- Should be "cstring", but it is not needed in the first place.
#include <cstdlib>// <--- Should be "cstdlib".
#include <ctime>// <--- Should be "ctime".
//#include <string>  // <--- Duplicate

using namespace std;

double random(double minprice, double maxprice);
string printRandomString(int n);
bool coinToss();
int clicks();
int runme();
int createfiles(int z);

struct Things
{
	//Things();  // <--- Not needed as the compiler will create a default ctor. Also missing the function definition.

	int id{};
	string name;
	string category;
	double price{};
	bool two_day_shipping{};
	int numclicked{};
};


1
2
3
int main()
{
	srand(static_cast<size_t>(time(nullptr)));  // <--- This only needs done once. 

"size_t" is an alais for "unsigned int".

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int createfiles(int z)
{
	string file_out;
	ofstream fout;

	cout << "Please enter name of output file ending in .txt :";
	cin >> file_out;

	cout << "\n\n";

	ofstream outfile(file_out/*, ios::out*/);  // <--- The "o" in "ofstream" already implies an output stream

	fout.open(file_out/*.c_str()*/);  // <--- The ".c_str()" not needed from C++11 on, but OK if you use it.

	bool two_day_shipping;

	//srand(time(NULL));  // <--- Should be done in "main". Not everytime the function is called. 


Just the small things I noticed that should help.

Some quick thoughts I have. In "main" create a vector of strings for the file names and pass this to "createfiles" as a reference. This way you have the file names stored for later use when you create the print function to print the first 50.

Now you will have to create a function to open and read each file. Be sure to close the stream when finished with it before you open the next file.

Andy
thank you, Ill get on this...
Hello spelledwrong,

I have been working on the program.

Some more minor things I have found.

You wrote:
1
2
3
4
5
6
7
8
outfile << left << setw(7) << id
	<< left << setw(15) << name
	<< right << setw(15) << price
	<< "     "
	<< right << setw(15) << category
	<< "     "
	<< left << setw(15) << two_day_shipping
	<< left << setw(15) << click << endl;


And this is all you need:
1
2
3
4
5
6
7
8
9
outfile
	<< left << setw(7) << id
	<< setw(15) << name
	<< right << setw(15) << price
	<< "     "
	<< setw(15) << category
	<< "     "
	<< left << setw(15) << two_day_shipping
	<< setw(15) << click << endl;

When the program starts the default justification for "setw" is right unless you change it. Line 2 changes the justification to left and this will stay in effect until it is changed.

Line 4 changes to right and this stays in effect until it is changed.

The extra "left"s and "right"s are OK if you leave them, but it is unnecessary typing for something you do not need.

I added this: constexpr size_t MAXOUTPUT{ 5 }; before the prototypes to use in the print function. Although it could just as easily reside in the print function. I shortened it for testing. Add a zero when finished testing. I am also thinking you might need to create 1 or 2 more of these. I was not thinking about that when I started working.

In all my work I did not find any need for the struct. Trying to use it would be more a waste of time, but may have a future use.

"main" now looks like this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
int main()
{
	std::vector<std::string> fileNames
	{                    // <--- Setup for testing. Remove the {}s and everything inbetween when finished.
		"File 1.txt",
		"File 2.txt",
		"File 3.txt"
	};

	srand(static_cast<size_t>(time(nullptr)));

	//for (int z = 0; z < 3; z++)
	//{
	//	createfiles(z, fileNames);
	//}

	for (size_t index = 0; index < fileNames.size(); index++)
	{
		if (PrintFiles(fileNames[index]))
			return 1;
	}

	return 0;  // <--- Not required, but makes a good break point.
}

By initializing the vector you can comment out the for loop and skip creating the files each time you test the program. That is after you have created the first set of files. You may need to change the file names to what you are using.

In the "createfiles" function I made these changes:
1
2
3
4
5
6
7
8
9
10
11
12
13
int createfiles(int z, std::vector<std::string>& fileNames)
{
	string file_out;
	ofstream fout;

	cout << "Please enter name of output file no extension needed: ";
	std::getline(std::cin, file_out);

	file_out += ".txt";

	fileNames.push_back(file_out);

	cout << "\n\n";

I used "std::getline" in case the file name has a space in it. The formatted input std::cin >> file_out would stop at the first white space it finds and you would not get the full file name.

To cut down user typing I added the ".txt" to what is entered. This is optional, but you do make sure that the file name ends in ".txt". You could get more involved and check for the extension, but I thought this might be easier.

What I did with the function I added:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool PrintFiles(std::string fileName)
{
	std::string heading;
	std::ifstream inFile;

	inFile.open(fileName);

	if (!inFile)
	{
		std::cout << "\n    File " << std::quoted(fileName) << " did not open\n";

		return true;
	}

	std::getline(inFile, heading);

By reading the headings into a variable you can use it later.

When you open a file for input you need to check that it worked. If the stream is not open the if statement will let you know and return to "main".

That is why the if statement in "main" is for.

Andy
Thank you for the suggestions....i've been learning a ton!!!
I have one hiccup I could use help with.
I keep getting this error on line 235...any ideas?
|235|error: no matching function for call to 'std::basic_ifstream<char>::open(std::__cxx11::string&)'|

I have the three files being created with the .txt extension. I am trying to push the data into the struct so I can manipulate data after it is in the struct. (I need to output data based on clicks and such).

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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
#include <iostream> //For input, output funcitons...
#include <stdlib.h> //For rand function
#include <iomanip> //for setw function
#include <fstream> //for file related functions...
#include <stdio.h>
#include <string.h>
#include <time.h>
using namespace std;

double random(double minprice, double maxprice);
string printRandomString(int n);
bool coinToss();
int clicks();
int runme();
int createfiles(const char *);
void LoadArray(const char *);

struct things{
int id;
string name;
string category;
double price;
bool two_day_shipping;
int numclicked;
} thingDetails[1000];

int main()
{
srand(time(NULL));

for(int z=0; z<3; z++)
{
char filename[20];
cout << "Please enter a filename for file #" << z << " :" ;
cin >> filename;
strcat(filename,".txt");
createfiles(filename);
}
}

int createfiles(const char *filename)
{

ofstream fileout; //open file
fileout.open(filename); //convert open file to output stream....
bool two_day_shipping;


fileout << left << setw(7) << "id"
<< left << setw(15) << "name"
<< right << setw(15)<< "price"
<< " "
<< right << setw(15)<< "category"
<< " "
<< left << setw(15) << "2D ship"
<< left << setw(15) << "number of clicks" << endl;

for(int j=0; j<1000; j++)
{
string category;
double price;
int id;
int click;
int cat;
cat = rand() % 6 +1;
double minprice;
double maxprice;
fileout << fixed << setprecision(2);
id = j;
int n;
string name;
switch (cat){

case 1:
category = "Electronics";
minprice = 35;
maxprice = 1500;
price = random (minprice,maxprice);
n= 5 + (rand()%4);
name = printRandomString(n);
two_day_shipping= coinToss();
click = clicks();
fileout << left << setw(7) << id
<< left << setw(15) << name
<< right << setw(15)<< price
<< " "
<< right << setw(15)<< category
<< " "
<< left << setw(15) << two_day_shipping
<< left << setw(15) << click << endl;


break;

case 2:
category = "Clothing";
minprice = 45;
maxprice = 550;
price = random (minprice,maxprice);
n= 5 + (rand()%4);
name = printRandomString(n);
two_day_shipping= coinToss();
click = clicks();
fileout << left << setw(7) << id
<< left << setw(15) << name
<< right << setw(15)<< price
<< " "
<< right << setw(15)<< category
<< " "
<< left << setw(15) << two_day_shipping
<< left << setw(15) << click << endl;
break;

case 3:
category = "Footwear";
minprice = 99;
maxprice = 399;
price = random (minprice,maxprice);
n= 5 + (rand()%4);
name = printRandomString(n);
two_day_shipping= coinToss();
click = clicks();
fileout << left << setw(7) << id
<< left << setw(15) << name
<< right << setw(15)<< price
<< " "
<< right << setw(15)<< category
<< " "
<< left << setw(15) << two_day_shipping
<< left << setw(15) << click << endl;
break;

case 4:
category = "Books";
minprice = 7;
maxprice = 45;
price = random (minprice,maxprice);
n= 5 + (rand()%4);
name = printRandomString(n);
two_day_shipping= coinToss();
click = clicks();
fileout << left << setw(7) << id
<< left << setw(15) << name
<< right << setw(15)<< price
<< " "
<< right << setw(15)<< category
<< " "
<< left << setw(15) << two_day_shipping
<< left << setw(15) << click << endl;
break;

case 5:
category = "Appliances";
minprice = 150;
maxprice = 600;
price = random (minprice,maxprice);
n= 5 + (rand()%4);
name = printRandomString(n);
two_day_shipping= coinToss();
click = clicks();
fileout << left << setw(7) << id
<< left << setw(15) << name
<< right << setw(15)<< price
<< " "
<< right << setw(15)<< category
<< " "
<< left << setw(15) << two_day_shipping
<< left << setw(15) << click << endl;
break;

case 6:
category = "Apps";
minprice =.5;
maxprice = 4.99;
price = random (minprice,maxprice);
n= 5 + (rand()%4);
name = printRandomString(n);
two_day_shipping= coinToss();
click = clicks();
fileout << left << setw(7) << id
<< left << setw(15) << name
<< right << setw(15)<< price
<< " "
<< right << setw(15)<< category
<< " "
<< left << setw(15) << two_day_shipping
<< left << setw(15) << click << endl;
break;
}
LoadArray(filename);
}

};


double random(double minprice, double maxprice)
{
double price;
price = ((double)rand()/RAND_MAX)* (maxprice-minprice)+minprice;
return price;
}


string printRandomString(int n)
{
const int MAX = 26;
char alphabet[MAX] = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
'h', 'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't', 'u',
'v', 'w', 'x', 'y', 'z' };

string res = "";
for (int i = 0; i < n; i++)
res = res + alphabet[rand() % MAX];
return res;
}

bool coinToss()
{
return rand() % 2;
}


int clicks()
{
int x;
x = rand()%10000;
return x;
}

void LoadArray(string filename)
{
//string filename;
ifstream infile;
infile.open(filename);

for(int i=0; i<1000; i++)
{
infile>>thingDetails[i].id;
infile>>thingDetails[i].name;
infile>>thingDetails[i].category;
infile>>thingDetails[i].price;
infile>>thingDetails[i].two_day_shipping;
infile>>thingDetails[i].numclicked;
}

infile.close();
int a=0;
for(int a=0; a<50; a++)
cout<<thingDetails[a].id;
cout<<thingDetails[a].name;
cout<<thingDetails[a].category;
cout<<thingDetails[a].price;
cout<<thingDetails[a].two_day_shipping;
cout<<thingDetails[a].numclicked;
}
Last edited on
Hello spelledwrong,

First off your code need improvement on indenting. It is very hard to read.

Looking back at your OP is where you should have mentioned what IDE/Compiler you are using.

I suspect that your IDE and compiler are not set to use the C++11 standards.

Prior to 2011 the open statement needs a C string to work properly. from the 2011 stands on a std::string will work.

I suspect that what you are using is not up to the 2011 standards and it is possible that could be fixed without having to install a newer version.

You could try infile.open(filename.c_str()); and see if that fixes the problem.

At a minimum I suggest that you use the C++ 2011 standards.

Andy
Hello spelledwrong,

My bad, sorry.

It was not until I tried to compile your code that I realized what you are doing.

My first question is if this is a C++ or a C program?

Mixing C and C++ is not always a good idea. Using "srand" and "rand" is not a problem, but when you mix C strings and C++ strings it can be confusing.

The header files "string.h", for C strings, and "string", for C++ std::strings, they are 2 different header files and interchangeable.

Since you are using both types of strings in your program you need both header files.

You would be better to use the "std::string" from the "string" header and if you need it use filename.c_str() to change it to a C string when needed. Less confusing that way.

Andy
Topic archived. No new replies allowed.