output problem

i have an address book program, and whenever i use a function to view the contact list (the information is the first name, last name, phone #, e-mail, and age), the output, which should just be:
first last
1112223333
email@email.com
20
instead looks like this:
first����<last`!@1112223333email@email.com����<20L��<�

here is the function to view the list:

1
2
3
4
5
6
7
8
9
int AddressBook::Total()
{
    ifstream inFile;
    inFile.open("Book1.txt");
    inFile.seekg(0, ios::end);
    int n;
    n = inFile.tellg()/sizeof(var);
    return n;
}
Last edited on
Are you sure that is
the function to view the list
?
I don't think so.
So, post that function, possibly with a compilable piece of code that shows the problem.
oh, wait. that's just the function to calculate total contacts. here is the view all function:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void AddressBook::All()
{
    string line;
    ifstream inFile("Book1.txt");
    if (inFile.is_open())
	{
	    while (getline (inFile, line))
		{
		    cout << line << endl;
		}
	    inFile.close();
	}
    else
	{
	    cout << "Unable to open file.";
	}
}
I have created a file "Book1.txt" and pasted the following content:
first last
1112223333
email@email.com
20
and the output is like you expected.
So, the problem is not in the function All.
Are you sure the file content is ok?
lemme just show you the whole function, see if you can find anything wrong:
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
#include <iostream>
#include <cstring>
#include <cstdio>
#include <fstream>
using namespace std;

char Continue();
char Exit();

struct ab
{

    char Fname[15];
    char Lname[15];
    char Number[10];
    char Email[30];
    char Age[3];
    char Fax[10];

};

class AddressBook
{
    ab var;

public:
    void AddContact();
    void ContactInfo();
    int Total();
    void Show1();
    void SearchContact();
    void All();
    void Delete();

};

void AddressBook::AddContact()
{
    ofstream outFile;
    outFile.open("Book1.txt", ios::app);
    ContactInfo();
    outFile.write((char*)&var,sizeof(var));
    outFile.close();
    Continue();
}

void AddressBook::ContactInfo()
{
    char info;
    char type;
    cout << "Will you be adding a personal or business contact? (p/b)\n";
    cin >> type;
    cout << "Enter your new contact's first name: ";
    cin >> var.Fname;
    cout << "\nLast name: ";
    cin >> var.Lname;
    cout << "\nNumber (without spaces): ";
    cin >> var.Number;
    cout << "\nE-mail: ";
    cin >> var.Email;
    cin.get(info);

    if (type == 'p'||type == 'P')
	{
	    cout << "\nAnd the age: ";
	    cin >> var.Age;
	    cout << "Your contact has been created!\n";
	    var.Fax == "personal contact: no fax number stored\n";
	}

    else if (type == 'b'||type == 'B')
	{
	    cout << "\nAnd the fax number: ";
	    cin >> var.Fax;
	    cout << "Your contact has been created!" << endl;
	    var.Age == "business contact: no age stored\n";
	}
}

int AddressBook::Total()
{
    ifstream inFile;
    inFile.open("Book1.txt");
    inFile.seekg(0, ios::end);
    int n;
    n = inFile.tellg()/sizeof(var);
    return n;
}

void AddressBook::Show1()
{
    cout << "\nContact name: " << var.Fname << " " << var.Lname << "\n";
    cout << "\nContact phone number: " << var.Number << "\n";
    cout << "\nContact e-mail: " << var.Email << "\n";
    cout << "\nContact age: " << var.Age << "\n";
    cout << "\nContact fax number: " << var.Fax << "\n";
}

void AddressBook::SearchContact()
{
    char find[15];
    ifstream inFile;
    inFile.open("Book1.txt");
    cout << "Enter the last name of the contact to search: ";
    cin >> find;
    int n = Total();//Total() calculates total number of contacts
    for (int i = 0; i < n; i++)
	{
	    inFile.read((char*)&var,sizeof(var));
	    if (find == var.Lname)
		{
		    Show1();
		    return;
		}
	    else
		{
		    cout << "Contact was not in the address book.";
		}
	}
    inFile.close();
    Continue();
}

void AddressBook::All()
{
    string line;
    ifstream inFile("Book1.txt");
    if (inFile.is_open())
	{
	    while (getline (inFile, line))
		{
		    cout << line << endl;
		}
	    inFile.close();
	}
    else
	{
	    cout << "Unable to open file.";
	}
    Continue();
}

void AddressBook::Delete()
{
    char find[15];
    int n,i;
    ifstream inFile;
    ofstream outFile;
    inFile.open("Book1.txt");
    outFile.open("Book2.txt");
    n = Total();
    for (i = 0; i < n; i++)
	{
	    inFile.read((char*)&var,sizeof(var));
	    outFile.write((char*)&var,sizeof(var));
	}
    inFile.close();
    outFile.close();
    outFile.open("Book1.txt",ios::trunc);
    inFile.open("Book2.txt");
    cout << "\nPlease enter the last name of the contact to be deleted:\n";
    cin >> find;
    for (i = 0; i < n; i++)
	{
	    inFile.read((char*)&var,sizeof(var));
	    if (find != var.Lname)
		outFile.write((char*)&var,sizeof(var));
	}
    outFile.close();
    inFile.close();
    cout << find << " has been deleted.";
}


int main()
{

    AddressBook Book;
    ab var;    
    char choice;
    cout << "=========================ADDRESS BOOK=========================\n";
    cout << "What would you like to do?\n\n";
    cout << "1. Create New Contact\n\n";
    cout << "2. Search for an Existing Contact\n\n";
    cout << "3. View All Contacts\n\n";
    cout << "4. Delete a Contact\n\n";
    cout << "5. Exit\n\n";
    cout << "Please enter a choice from 1 - 5 : \n\n" << endl;
    cin >> choice;

    if (choice == '1')
	Book.AddContact();
    else if (choice == '2')
	Book.SearchContact();
    else if (choice == '3')
	Book.All();
    else if (choice == '4')
	Book.Delete();
    else if (choice == '5')
	Exit();

    return 0;
}

char Continue()
{
    char answer;
    cout << "\nDo you want to continue using the program? (y/n)\n";
    cin >> answer;
    if (answer == 'y'||answer == 'Y')
	{
	    return main();
	}
}

char Exit()
{
    char answer;
    cout << "Are you sure you want to exit? (y/n) ";
    cin >> answer;
    if (answer == 'n'||answer == 'N')
	{
	    return main();
	}
}
I skimmed, and stopped as soon as I saw this:

outFile.write((char*)&var,sizeof(var));

This performs a binary dump of the data in your 'var' structure to the file. You then proceed to open the file in a text editor expecting it to be neat and orderly. It's not going to be... opening a binary file in a text editor is going to show garbage.


For example... your FName member is 15 characters in size. If the user has the name "first" that only uses 5 of those characters. The 6th character is going to be a null character to mark the end of the string (in a text editor this will often display as a garbage character... like that square box thing you're seeing). And the remaining characters after that will be filled with garbage.

But because you're doing a binary dump rather than printing text... All 15 characters will be written to the file, even though you're only interested in 5 of them.

This doesn't even account for the possibility of padding in between members of your struct.



TL;DR

If you want to make a text file.. .don't use write(). Instead, use the << and >> stream operators.

And don't read/write the struct as a whole. Do one string at a time.
would while (getline, line) work instead?
Well that's not really legal syntax, so no =P

I would start by getting rid of the char arrays. C++ is much easier when you use C++ abstractions. So favor std::string over char arrays.

1
2
3
4
5
6
7
8
9
struct ab
{
    std::string Fname;
    std::string Lname;
    std::string Number;
    std::string Email;
    std::string Age;
    std::string Fax;
};


Then, I would override the << and >> operators for this struct so that you can save/load it in a single command:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// << operator to write the data to the stream:
std::ostream& operator << (std::ostream& s, const ab& data)
{
    s << data.FName << '\n';
    s << data.LName << '\n';
    // ... etc

    return s;
}

// >> operator to read the data from the stream:
std::istream& operator >> (std::istream& s, ab& data)
{
    std::getline(s,data.FName);
    std::getline(s,data.LName);
    // ...  etc

    return s;
}



Then, reading/writing objects can be done with a single <</>> call:

1
2
3
4
5
6
7
// bad:
inFile.read((char*)&var,sizeof(var));
outFile.write((char*)&var,sizeof(var));

// good:
inFile >> var;
outFile << var;

ok, here's what i got so far. i still can't get it to output correctly, im probably not coding it right:
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
#include <iostream>
#include <cstring>
#include <cstdio>
#include <fstream>
using namespace std;

char Continue();
char Exit();

struct ab
{

    std::string Fname;
    std::string Lname;
    std::string Number;
    std::string Email;
    std::string Age;
    std::string Fax;
};

std::ostream& operator << (std::ostream& os, const ab& data)
{
    os << data.Fname << "\n";
    os << data.Lname << "\n";
    os << data.Number << "\n";
    os << data.Email << "\n";
    os << data.Age << "\n";
    os << data.Fax << "\n";
    return os;
}

std::istream& operator >> (std::istream& is, ab& data)
{
    std::getline(is,data.Fname);
    std::getline(is,data.Lname);
    std::getline(is,data.Number);
    std::getline(is,data.Email);
    std::getline(is,data.Age);
    std::getline(is,data.Fax);
    return is;
}

class AddressBook
{
    ab var;

public:

    void AddContact();
    void ContactInfo();
    int Total();
    void Show1();
    void SearchContact();
    void All();
    void Delete();

};

void AddressBook::AddContact()
{
    ofstream outFile;
    outFile.open("Book1.txt", ios::app);
    ContactInfo();
    outFile << var;
    Continue();
}

void AddressBook::ContactInfo()
{
    char info;
    char type;
    cout << "Will you be adding a personal or business contact? (p/b)\n";
    cin >> type;
    cout << "Enter your new contact's first name: ";
    cin >> var.Fname;
    cout << "\nLast name: ";
    cin >> var.Lname;
    cout << "\nNumber (without spaces): ";
    cin >> var.Number;
    cout << "\nE-mail: ";
    cin >> var.Email;
    cin.get(info);

    if (type == 'p'||type == 'P')
	{
	    cout << "\nAnd the age: ";
	    cin >> var.Age;
	    cout << "Your contact has been created!\n";
	    var.Fax == "personal contact - no fax number stored\n";
	}

    else if (type == 'b'||type == 'B')
	{
	    cout << "\nAnd the fax number: ";
	    cin >> var.Fax;
	    cout << "Your contact has been created!" << endl;
	    var.Age == "business contact - no age stored\n";
	}
}

int AddressBook::Total()
{
    ifstream inFile;
    inFile.open("Book1.txt");
    inFile.seekg(0, ios::end);
    int n;
    n = inFile.tellg()/sizeof(var);
    return n;
}

void AddressBook::Show1()
{
    cout << "\nContact name: " << var.Fname << " " << var.Lname << "\n";
    cout << "\nContact phone number: " << var.Number << "\n";
    cout << "\nContact e-mail: " << var.Email << "\n";
    cout << "\nContact age: " << var.Age << "\n";
    cout << "\nContact fax number: " << var.Fax << "\n";
}

void AddressBook::SearchContact()
{
    std::string find;
    ifstream inFile;
    inFile.open("Book1.txt");
    cout << "Enter the last name of the contact to search: ";
    cin >> find;
    int n = Total();//Total() calculates total number of contacts
    for (int i = 0; i < n; i++)
	{
	    inFile >> var;
	    if (find == var.Lname)
		{
		    Show1();
		    return;
		}
	    else
		{
		    cout << "Contact was not in the address book.";
		}
	}
    inFile.close();
    Continue();
}

void AddressBook::All()
{
    string line;
    ifstream inFile("Book1.txt");
    if (inFile.is_open())
	{
	    while (getline (inFile, line))
		{
		    cout << line << endl;
		}
	    inFile.close();
	}
    else
	{
	    cout << "Unable to open file.";
	}
    Continue();
}

void AddressBook::Delete()
{
    char find[15];
    int n,i;
    ifstream inFile;
    ofstream outFile;
    inFile.open("Book1.txt");
    outFile.open("Book2.txt");
    n = Total();
    for (i = 0; i < n; i++)
	{
	    inFile >> var;
	    outFile << var;
	}
    inFile.close();
    outFile.close();
    outFile.open("Book1.txt",ios::trunc);
    inFile.open("Book2.txt");
    cout << "\nPlease enter the last name of the contact to be deleted:\n";
    cin >> find;
    for (i = 0; i < n; i++)
	{
	    inFile >> var;
	    if (find != var.Lname)
		outFile << var;
	}
    outFile.close();
    inFile.close();
}


int main()
{

    AddressBook Book;
    ab var;    
    char choice;
    cout << "=========================ADDRESS BOOK=========================\n";
    cout << "What would you like to do?\n\n";
    cout << "1. Create New Contact\n\n";
    cout << "2. Search for an Existing Contact\n\n";
    cout << "3. View All Contacts\n\n";
    cout << "4. Delete a Contact\n\n";
    cout << "5. Exit\n\n";
    cout << "Please enter a choice from 1 - 5 : \n\n" << endl;
    cin >> choice;

    if (choice == '1')
	Book.AddContact();
    else if (choice == '2')
	Book.SearchContact();
    else if (choice == '3')
	Book.All();
    else if (choice == '4')
	Book.Delete();
    else if (choice == '5')
	Exit();

    return 0;
}

char Continue()
{
    char answer;
    cout << "\nDo you want to continue using the program? (y/n)\n";
    cin >> answer;
    if (answer == 'y'||answer == 'Y')
	{
	    return main();
	}
}

char Exit()
{
    char answer;
    cout << "Are you sure you want to exit? (y/n) ";
    cin >> answer;
    if (answer == 'n'||answer == 'N')
	{
	    return main();
	}
}
Last edited on
I don't know if this is related or not, but this is also problematic:

1
2
3
4
5
6
7
8
9
int AddressBook::Total()
{
    ifstream inFile;
    inFile.open("Book1.txt");
    inFile.seekg(0, ios::end);
    int n;
    n = inFile.tellg()/sizeof(var); // <- won't work
    return n;
}


This line does not account for whitespace (newlines) between entries, or that strings are of varying length.

In general... if you find yourself using sizeof for something other than raw i/o, you're probably doing something wrong. It's not as useful as newbies tend to think.



That aside... can you be more specific about what the problem is?
" i still can't get it to output correctly" isn't very descriptive. What output are you getting? vs. what are you expecting?
Topic archived. No new replies allowed.