FILE I/0 going from string struct to char struct

OK, so I have an address book that uses a struct with strings in it. I need to convert, for the purposes of writing to a file, that string information into chars with a set size, say 100. As far as the file i/o goes, I'm pretty sure I have the figured out, and I can search and do all the things I need to do with that. My problem is that I have no idea how to temporarily convert the strings to chars for the purpose of writing to and viewing the files I need to create. Does anybody know how to do this, or can you at least point me somewhere to find out how this is done. I've been searching for day with no luck anywhere. I'll pop in my header file so you can see what I'm working with concerning the struct's

Header 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
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
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK
#include <fstream>
#include <vector>
#include<string>
using std::string;
#include <iostream>
using namespace std;

using std::istream;
using std::ostream;
namespace CJ
{
	const int MAXADDRESS =25;

	struct PERSON
	{
		string fName;
		string lName;
		string Address;
	};

	struct PERSONTEMP
	{
		char fName[100];
		char lName[100];
		char Address[100];
	};

	class addressBook
	{
	private:

		vector<PERSON> people;

		int head;
		int tail;

	public:

		addressBook();

		addressBook(const PERSON &p);
		addressBook(const PERSON p[], int size);
		addressBook(char *fName, char *lName, char *address);
		bool addPerson(const PERSON &p);
		bool sortcomp(const PERSON& p1, const PERSON& p2);
		bool getPerson(PERSON &p);
		bool findPerson(const string& lastName, PERSON& p);
		bool findPerson(const string& lastName, const string& firstName, PERSON& p);
		void bubbleSort(int *array,int length);
		void printBook();
		void sort();
		void waitKey();
		void writeRecord();
		void showRecord();
		static addressBook *newbookInst();
		static addressBook *tempNew;
		static PERSON *p();
		static PERSON *temPerson;

		friend ostream &operator << (ostream &, addressBook &);
		addressBook operator =(const string& str);
		addressBook &operator +=(const PERSON &p); 
		addressBook operator [](int x); 

	};
}
#endif


If somebody could help me figure this out I would really appreciate it.
Last edited on
std::string::c_str() //returns a null terminated char array
1) std::string can be written to a file just fine
2) you can use something like:
1
2
3
char cstring[100];
std::string original("hello");
std::strncpy(cstring, original.c_str(), 99);
Yeah, I messed up. I think I misunderstood the assignment. I have to take my string filled structs, copy them into a vector, then print from there, and be able to call up (seekg I assume), from any point in the file I create. Somehow, I think I'm going to need sort out more than what I thought I had to. I have no idea why I even though otherwise. Here's the assignment, if anyone interested:


Since last semester we have been working on a simple address book. The major problem with it at this point is that we lose all of our information when the program ends. It would be nice to store all of this information to a file. That way, the data will always be there for us.

Your mission is to write all of the entries of your address book to a random access file. It would be nice to use the seekp and seekg functions to search for a particular person in the address book. Lets just simplify our lives by reading all of the contents of the address book into the vector, and write the contents of the vector back out to the file.

In your constructors you should have functionality to load the address book from file and put the contents into your vector. You should also have a save method that will save the entire contents of the vector to the file.

You may want to investigate the idea of writing everything out inside a destructor. This is not required here, only something to think about.



NOTE:

Records in the file have to be a fixed length. This is the only way to know where one record ends and another begins. Unfortunately all of your records contain the string class which is not a fixed length. You are going to have to come up with a mechanism to create a fixed length record for writing. One possible solution is to create a filePerson record that is fixed length. You would only need to use this record when you are reading and writing to the file. Basically you would copy the data from the vector into your file record and then write the fileRecord to the file.

I know this seems like a lot of work but there are times in programming where you are simply stuck doing things like this. What I am saying is that this happens to be one of those times


I have a vector called people that I use to print out my entries in my address book to the screen. I'm guessing I can use that in much the same way to print to a file. I just have to figure out how to search it if it's not a fixed length, as my vector is not.
Is there a way to take a vector and set it to a fixed length if it's set in private inside my class? I'm going to play around with this. I know how to do this without a vector:

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
#include <fstream>
#include <iostream>
using namespace std;

struct storeName
{
	char fName[50];
	char lName[50];
};
void writeRecords();
void showRecord(int recNumber);
int main()
{
	writeRecords();
	showRecord(0);
	showRecord(1);
	showRecord(3);
}

void writeRecords()
{
	storeName p[] = { {"Bob", "Barker"}, {"John", "Doe"}, {"Plain", "Jane"} };
	ofstream outFile("people.dat", ios::binary);
		if(!outFile)
		{
			cout << "can't open file " << endl;
			return;
		}
		for(int i = 0; i < 3; i++)
		
		outFile.write(reinterpret_cast<const char *>(&p[i]), sizeof(storeName));
		
		outFile.close();
}

void showRecord(int recNumber)
{
	storeName p;
	ifstream indata("people.dat");
		if(!indata)
		{
			cout << "Problem with the file " << endl;
			exit(0);
		}
		indata.seekg(recNumber * sizeof(storeName));
		indata.read(reinterpret_cast<char *>(&p), sizeof(storeName));
		cout << p.fName << " " << p.lName << endl;
}


but how to do it with one.....hmmmm
Would something like this work?

1
2
3
4
5
6
7
8
9
10
11
	char fName1[50];
	char lName1[50];
	char Address1[50];

	addressBook::PERSON p.fName;
	addressBook::PERSON p.lName;
	addressBook::PERSON p.Address;

	p.copy(fName1, 50);
	p.copy(lName1, 50);
	p.copy(Address1, 50);
So I tried this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
	void addressBook::test()
{
	PERSON p[25];
    ofstream outTest("vectortest.dat", ios::binary);
    if(!outTest)
    {
		cout << "File vectortest.txt did not open " << endl;
        exit(1);
    }
	
    for(size_t i = 0; i < people.size(); i++)
		{		
			outTest.write(reinterpret_cast<const char *>(&p[i]), sizeof(PERSON));
		}
	outTest.close();

}


I then popped it into my print function, so that when I go to print to screen, I also call this up, in the hopes of printing to a file. I don't get any kind of errors when I run my program, but I also don't get any kind of file being written either. Anybody know why this wouldn't work?
Well, I got it to print, although this seems a bit of a lazy way to do it, but at least it works. I still have to figure out how to read from the file...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
	void addressBook::test()
{
    ofstream outTest("vectortest.txt");
    if(!outTest)
    {
		cout << "File vectortest.txt did not open " << endl;
        exit(1);
    }
	
    for(size_t i = 0; i < people.size(); i++)
		{		
			outTest << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
		}

}
Sorted it out. My problem was that I was trying to copy the vector as a whole to the struct as a whole. This was a no-no. I needed to stay along the lines of person[1].Name1 = tmp.Name1;, looping through until I got to the end of the info in the vector. Then it was just a matter of copying it all out to a file.

Since I'm done with the assignment, I'm wondering if anyone would care to explain how you go about saving the file permanently, so it's not overwritten each time, and accessing it whenever you open up then address book, so the names are always stored in the book. We don't have to do that, but it'd be nice to learn how thats done.
To get the addressBook to preload the contents of the file, you would want to create it in a constructor essentially reversing the order of how the file was written, but watch the case study video and it should help.
No, not preload, I want it to be used as a filestore, so that when you open the address book up, it calls on that file, and then when you click print, all the stored names are there, without having to had re-enter them, and whenever you add a new entry, I'd like to be able to check to see if its already there, and if not, copy it to the file and save.
http://programming.msjc.edu/cppii/videos/SequentialAccess/SequentialAccess.mp4

That is a download link to a video on reading and writing to files from the lecture. I think that should help you know how to read from a file, of course it isn't going to be verbatim and will require imagination and code manipulation.

Now as far as checking to see if something already exists in the file... That sounds like it could get hairy because of our novice abilities. Perhaps the seekg or seekp functions have the realm of this ability, but you may need to create a while loop sort of thing that would search the file using a == comparing it to a string?
Ok, I got a good one. I have this function that can scan my file and print out a predesignated record according to which one you choose to look at:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void addressBook::showRecord(int pickNum)
{
	PEOPLE2 p;
	
	ifstream indata("vectortest.dat", ios::binary);
		if(!indata)
		{
			cout << "Error opening file for reading " << endl;
			exit(0);
		}
		
		indata.seekg(pickNum * sizeof(PEOPLE2));
		indata.read(reinterpret_cast<char *>(&p), sizeof(PEOPLE2));
		cout << p.fName2 << " " << p.lName2 << " " << p.Address2 << " " << endl;
	
}


So all you have to do is pop showRecord into main, and then pick which name you want to print out. Say I want to look at the second name stored, I would put in

 
newBook->showRecord(1);


Thats all fine an dandy, and it works perfect, but what if I want to go a bit further. So I create another function that can use showRecord to print out all of the names in the address book that have been stored to my file. I tried this:

1
2
3
4
5
6
7
8
void addressBook::showAll()
{
	for(int i = 0; i < ?; i ++)
	{
		showRecord(i);
	}

}


The "?" is because I don't know what to reference for size. If I put in a set value, say 10, it will print whatever I have stored into the address book file, up to ten names. If I don't have ten names, it will print what I do have, and then print out garbage for the rest of the spots. What should I use to reference the correct number of names that are currently stored in the file so I don't go over or under? I've tried my vector, which just loops forever, and I've tried the structs, same problem. I'd like to think I can reference the file itself, but what would I use to do that?
Last edited on
Tried this:

1
2
3
4
5
6
7
8
9
10
void addressBook::showAll()
{
	ifstream indata("vectortest.dat", ios::binary);

	for(int i = 0; i < indata.end; i ++)
	{
		showRecord(i);
	}

}


and it works, but it only prints out the stuff that's hard coded into my PERSON struct from a previous assignment, which is just odd beacuse when I go into the file itself, I can see all of the names that were added.
Last edited on
I am having trouble getting my code to work. Right now it doesn't compile because of what I am trying to do in my writeRecord function (toward the bottom of addressBook.cpp). Can anyone help?

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
#ifndef _ADDRESSBOOK
#define _ADDRESSBOOK

#include <fstream>
#include <iostream>
#include <string>
#include <vector>

namespace derek
{
	using std::cin;
	using std::cout;
	using std::endl;
	using std::ostream;
	using std::istream;
	using std::vector;
	using std::string;
	using std::ofstream;
	using std::ifstream;
	using std::ios;

	struct filePerson
	{
		char firstName[50];
		char lastName[50];
		char cAddress[50];
	};

	struct PERSON
	{
	 string fName;
	 string lName;
	 string Address;
	};

	class addressBook
	{
	private:
	 std::vector<PERSON> people;
	 int tail;
	 static addressBook *pInstance;

	public:
	 friend ostream &operator<<(ostream &, addressBook &);
	 friend istream &operator >>(istream &input, addressBook &ab);
	 addressBook & operator +=(PERSON &p);
	 PERSON & operator [](int n);
	 addressBook();
	 addressBook(const PERSON &p);
	 addressBook(const PERSON p[], int size);
	 addressBook(string fName, string lName, string address);
	 bool addPerson(const PERSON &p);
	 bool getPerson(PERSON &p);
	 bool findPerson(string lastName, PERSON &p);
	 bool findPerson(string lastName, string firstName, PERSON &p);
	 void sort();
	 void printBook();
	 static addressBook *Instance();

	 void writeRecord();
	 void showRecord(int recBook);
	};
}
#endif 


//addressbook.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
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
#include "addressBook.h"

using namespace std;

namespace derek
{
	addressBook::addressBook()
		: tail(-1)
	{

	}
	addressBook::addressBook(const PERSON &p)
		: tail(-1)
	{
		addPerson(p);
	}
	addressBook::addressBook(const PERSON p[], int size)
		: tail(-1)
	{
		for(int i = 0; i < size; i++)
			addPerson(p[i]);
	}
	ostream &operator<<(ostream &output, addressBook &ab)
	{
		PERSON tmp;
		ab.getPerson(tmp);
		output << tmp.fName << "\t" << tmp.lName
			<< "\t" << tmp.Address << endl;
		ab.tail++;
		if(ab.tail > ab.people.size())
			ab.tail = 0;
		return output;
	}
	istream &operator >>(istream &input, addressBook &ab)
	{
		PERSON tmp;
		cout << "Enter First Name " << endl;
		input >> tmp.fName;
		cout << "Enter Last Name " << endl;
		input >> tmp.lName;
		cout << "Enter Address " << endl;
		input >> tmp.Address;
		ab.addPerson(tmp);
		return input;
	}
	addressBook &addressBook::operator +=(PERSON &p)
	{
		people.push_back(p);
		return *this;
	}
	PERSON &addressBook::operator [](int n)
	{
		return people[n];
	}
	addressBook::addressBook(string fName, string lName, string address)
		: tail(-1)
	{
		PERSON tmp;
		tmp.fName = fName;
		tmp.lName = lName;
		tmp.Address = address;
		addPerson(tmp);
	}
	bool addressBook::addPerson(const PERSON &p)
	{
		people.push_back(p);
		tail++;
		return true;
	}
	bool addressBook::getPerson(PERSON &p)
	{
		if(tail >=0)
		{
			if(tail >= people.size())
				tail = 0;
			p = people[tail];
			tail++;
			return true;
		}
		return false;
	}
	bool addressBook::findPerson(string lastName, PERSON &p)
	{
		for(int i = 0; i < people.size(); i++)
		{
			if(people[i].lName == lastName)
			{
				p = people[i];
				return true;
			}
		}
		return false;
	}
	bool addressBook::findPerson(string lastName, string firstName, PERSON &p)
	{
		for(int i = 0; i < people.size(); i++)
		{
			if(people[i].lName == lastName && people[i].fName == firstName)
			{
				p = people[i];
				return true;
			}
		}
		return false;
	}
	void addressBook::printBook()
	{
		for(int i = 0; i < people.size(); i++)
		{
			cout << people[i].fName << "\t" << people[i].lName << "\t" << people[i].Address << endl;
		}
	}
	void addressBook::sort()
	{
		PERSON temp;
		for(int i = 0; i < people.size() - 1; i++)
		{
			for (int j=0; j < people.size() - 1; j++)
			{
				if (people[j+1].lName > people[j].lName)      // ascending order simply changes to <
				{ 
					temp = people[j];             // swap elements
					people[j] = people[j+1];
					people[j+1] = temp;
				}
			}
		}
	}
	addressBook *addressBook::pInstance = NULL;
	addressBook *addressBook::Instance()
	{
		if(pInstance == NULL)
			pInstance = new addressBook;
		return pInstance;
	}
	void addressBook::writeRecord()
	{
		filePerson p;
		ofstream outFile("addressBook.dat", ios::binary);
		if(!outFile)
		{
			cout << "Unable to open the file for writing" << endl;
			return;
		}

		for(int i = 0; i < people.size(); i++)
		{
			strcpy(p.firstName, people[i].fName);//Should I be using this? 
			people[i].fName.copy(p[i].firstName, 50, 0);//Or using something like this?
			people[i].lName.copy(p[i].lastName, 50, 0);
			people[i].Address.copy(p[i].cAddress, 50, 0);

			outFile << p[i].firstName << ' ' << p[i].lastName << ' ' << p[i].cAddress << endl;
		}

		outFile.close();
	}
	void addressBook::showRecord(int recBook)
	{
		filePerson p;

		ifstream inData("addressBook.dat");
		if(!inData)
		{
			cout << "Unable to open file for reading" << endl;
			exit(0);
		}

		inData.seekg(recBook * sizeof(filePerson));

		inData.read(reinterpret_cast<char *>(&p), sizeof(filePerson));
		cout << p.firstName << ' ' << p.lastName <<  ' ' << p.cAddress << endl;
		
		inData.close();
	}

}


//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
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
#include <cstdlib>
#include <conio.h>
#include "addressbook.h"
#include "menu.h"

using namespace std;
using derek::Menu;
using derek::PERSON;
using derek::addressBook;

void addPerson();
void getPerson();
void searchLast();
void getPerson();
void searchBoth();
void searchLast();
void printBook();
void ExitBook();
void sortBook();

int main()
{
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();

	mnu->addMenu("1. Add To Address Book", addPerson);
	mnu->addMenu("2. Get Person ", getPerson);
	mnu->addMenu("3. Search by last name", searchLast);
	mnu->addMenu("4. Search by first & last name", searchBoth);
	mnu->addMenu("5. Print Address Book", printBook);
	mnu->addMenu("6. Sort Address Book", sortBook);
	mnu->addMenu("7. Exit Address Book " , ExitBook);
	mnu->runMenu();
	/*
	PERSON p;
	// use this to test overloaded constructor
	PERSON people[] = 
	{{"Glenn","Stevenson","123 South"},
	{"Joe","Smith","1 main st."},
	{"Bob","Black","28237 La Piedra"}
	};
	addressBook ab1(people,3);
	*/
	return 0;
}
void addPerson()
{
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();
	PERSON p;
	cin >> p.fName;
	cin >> p.lName;
	cin >> p.Address;
	ab->addPerson(p);
	mnu->waitKey();
}
void getPerson()
{
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();
	bool status;
	PERSON p;

	status = ab->getPerson(p);
	if(status)
		cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
	else
		cout << "Sorry The address book is empty " << endl;
	mnu->waitKey();
}
void searchLast()
{
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();
	bool status;
	PERSON p;
	char lName[50];

	cout << "Enter a last name " << endl;
	cin >> lName;
	status = ab->findPerson(lName,p);
	if(status)
		cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
	else
		cout << "Sorry, Name not found " << endl;
	mnu->waitKey();
}
void searchBoth()
{
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();
	bool status;
	char lName[50];
	char fName[50];
	PERSON p;

	cout << "Enter last name " << endl;
	cin >> lName;
	cout << "Enter first name " << endl;
	cin >> fName;
	status = ab->findPerson(lName, fName, p);
	if(status)
		cout << p.fName << "\t" << p.lName << " " << p.Address << endl;
	else
		cout << "Sorry, Name not found " << endl;
	mnu->waitKey();//Lab 8 related
}
void printBook()
{
	int recBook = 1;
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();
	ab->printBook();
	ab->writeRecord();
	mnu->waitKey();
}
void sortBook()
{
	Menu *mnu = Menu::Instance();
	addressBook *ab = addressBook::Instance();

	cout << "Sorting Book, Please wait" << endl;
	ab->sort();
	cout << "Address Book is sorted, press any key to continue" << endl;
	mnu->waitKey();
}
void ExitBook()
{
	cout << "Thanks for using the address book " << endl;
	exit(0);
}
Last edited on
The very top of my source code on my post above is my addressBook.h
Here is the rest of my code.

//menu.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
#include <iostream>
#include <cstdlib>
#include "menu.h"
#include <conio.h>

using namespace std;

namespace derek
{
	Menu::Menu()
	: count(0)
	{

	}
	void Menu::addMenu(char *Description, void (*f) (void))
	{
		if(count < MAXCOUNT)
		{
			this->mi[count].func = f;
			strcpy(this->mi[count].decript, Description);
			count++;
		}
	}
	void Menu::runMenu()
	{
		for(;;)
		{
			system("CLS");
			for(int i = 0; i < count; i++)
			{
				cout << this->mi[i].decript << endl;
			}
			runSelection();
		}
	}
	void Menu::runSelection()
	{
		int select;

		cin >> select;
		if(select <= count)
			this->mi[select - 1].func();
	}
	void Menu::waitKey()
	{
		cout << endl << "Press any key to continue..." << endl;
		getch();
	}
	Menu *Menu::pInstance = NULL;
	Menu *Menu::Instance()
	{
		if(pInstance == NULL)
			pInstance = new Menu;

		return pInstance;
	}
}


//menu.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
#ifndef MENU
#define MENU

const int MAXCOUNT = 20;

namespace derek
{
	struct menuItem
	{
		void (*func)();
		char decript[50];
	};

	class Menu
	{
	private:
		menuItem mi[MAXCOUNT];
		int count;
		void runSelection();
		static Menu *pInstance;
	public:
		Menu();
		void addMenu(char *Descriptioon, void (*f) ());
		void runMenu();
		void waitKey();
		static Menu *Instance();
	};
}
#endif 
It kind of depends on what your going for. Here's your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void addressBook::writeRecord()
	{
		filePerson p;
		ofstream outFile("addressBook.dat", ios::binary);
		if(!outFile)
		{
			cout << "Unable to open the file for writing" << endl;
			return;
		}

		for(int i = 0; i < people.size(); i++)
		{
			strcpy(p.firstName, people[i].fName);//Should I be using this? 
			people[i].fName.copy(p[i].firstName, 50, 0);//Or using something like this?
			people[i].lName.copy(p[i].lastName, 50, 0);
			people[i].Address.copy(p[i].cAddress, 50, 0);

			outFile << p[i].firstName << ' ' << p[i].lastName << ' ' << p[i].cAddress << endl;
		}

		outFile.close();
	}


I may be saying this wrong, but you need to pass the vector info through a reinterpret cast to switch it from a string to a char
 
outFile.write(reinterpret_cast<const char *>(&temp), sizeof(filePerson));


I went a slightly different route for my for loop, using an iterator:

for (vector<PERSON>::iterator iter = people.begin(), end = people.end(); iter != end; ++iter)

after that, I just used a stringcopy that passed through the iterator

strncpy(temp.fName2, iter->fName.c_str(), 25); // takes my string, via the iterator and copies it to my char based struct copy of fName, with a size of 25

After that I used the .write I showed you up above, (inside my for loop, it wont work outside), and everything worked fine.

As for what you have, I think the first one would work, but you'd need to use strncpy, and not strcpy. Hope that helps!
Last edited on
Thank you for the reply.

I have a question about your code.

 
strncpy(temp.fName2, iter->fName.c_str(), 25); // takes my string, via the iterator and copies it to my char based struct copy of fName, with a size of 25  


where is the variable "temp" defined? Should that just be a
 
char temp //to hold the value of the vector to char? 


also, should I have two for loops, one for copying and one for writing to the file? or can I keep these in two files?

For my read function, I get a bunch of consistent characters being outputed to the console window. they look like this....
http://imgur.com/w4aTd9w

is there something wrong with my conversion going from binary to chars? I get an output like that when there is nothing in the file and I get different characters when the file is filled with ' ' (spaces). Any idea what's going on?
I'm on my phone atm, but i'll try to answer as best I can. The temp is from my second PERSON struct, the one that contains the char versions of fName and so on, so I have it as

 
PERSON2 temp; 


same as your

filePerson p;

Before my loop, and the .write should be inside your loop, which you should only need 1.

From your image, it looks like your printing out an empty spot in memory, which means it's probbably pulling the info from an empty char that didn't have any info from the vector transfered into it.

Hope that helps.
Last edited on
Here's what I ended up doing:

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
	void addressBook::writeRecord()
{
	
	PEOPLE2 temp;
	ofstream outFile("addressbook.dat", ios::binary);
		if(!outFile)
		{
			cout << "Error opening file for writing " << endl;
			return;
		}

			for (vector<PERSON>::iterator iter = people.begin(), end = people.end(); iter != end; ++iter)
			{
			strncpy(temp.fName2, iter->fName.c_str(), 25);
			strncpy(temp.lName2, iter->lName.c_str(), 25);
			strncpy(temp.Address2, iter->Address.c_str(), 25);
			outFile.write(reinterpret_cast<const char *>(&temp), sizeof(PEOPLE2));
			}		
		outFile.close();
}


/*void addressBook::showRecord(int pickNum)  //test function for grabing file info based on where it is located in the file
{
	PEOPLE2 p;
	
	ifstream indata("addressbook.dat", ios::binary);
		if(!indata)
		{
			cout << "Error opening file for reading " << endl;
			exit(0);
		}
		
		indata.seekg(pickNum * sizeof(PEOPLE2));
		indata.read(reinterpret_cast<char *>(&p), sizeof(PEOPLE2));
		cout << p.fName2 << " " << p.lName2 << " " << p.Address2 << " " << endl;

		indata.close();	
}

void addressBook::showAll()  //trying to see if I can loop into the previous function that looks up file info from location, 
{                              //and print all records saved to file from that.

	ifstream indata("addressbook.dat", ios::binary);
	string line;
	while(indata >> line)
	{
	for(int i = 0; i  < indata.end; i ++)
	{
		showRecord(i);  //only prints up what is stored in PERSON = {... ,(from main), when program loads, (still no clue why).
	}
	}

} */

void addressBook::showAll2()
{	
	ifstream indata("addressbook.dat", ios::binary);
	string file;

	if(indata.is_open())
	{
		while(indata >> file)
		{
			cout << file << "\n" << endl;
		}
	}
	else
	{
		cout << "Sorry, file did not open for reading " << endl;
	}
	indata.close();
}
And apparently I did this incorrectly:

You are not reading the records from the file properly. You are simply outputting them to the screen. You are also supposed to read the records from your constructor.


Since it's already been graded (I got 48%, ouch!), can somebody show me what I did wrong, and how to correct the mistake? It doesn't really matter for the class anymore, but I'd like to know how to do this the correct way for future reference, and I have no clue apparently, what the correct way is. Just when you think you've got it figured out.....
Topic archived. No new replies allowed.