Problem with this file

Pages: 12
HI. I wrote these codes to add, search and delete student information. It works but with some problems: First of all this program shows some number (RAM numbers) instead of real information on monitor but it saves the correct information on file! Why?!

and second after running the program for second time, this time program crashes!
I don't know why this happens.
Could anyone help me with this program?
Thank you.

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
#include <iostream>
#include<fstream>
#include<istream>
#include <string> 
using namespace std; 
struct Student{
	int id;
	string a;
};
void main()
{
	int r;
	Student a;  
	ofstream fout("a.txt",ios::out|ios::app); 
	cout<<"How many student do you want to add?\n";
	cin>>r;
	for(int i=0 ; i<r; i++)
	{
		cout<<"shomare daneshjuee?\n";
		cin>>a.id;
		cout<<"name?";
		cin>>a.a;
		fout.write( reinterpret_cast< const char * >( &a ),sizeof( a ) );
		cout<<"\n\n";
	}
	fout.close();
	cout<<"*****************************************\n\n";
	ifstream fin("a.txt", ios::in);
	Student *es, t, z;///////////////
	es = new Student [r+1];
	cout<<"enter your ID and name: \n";
	cin>>t.id>>t.a;
	cout<<"******************************************\n\n";
	for(int i=0; !fin.eof() ; i++)
	{
		fin.read(reinterpret_cast< char * >( &es[i] ),sizeof( es[i] ) ); 
		if(t.id==es[i].id){
			cout<<"\t\t enter your new id and name:";
			cin>>z.id>>z.a;
			es[i].id=z.id;
			es[i].a=z.a;
		}
		cout<<es[i].id<<"\t"<<es[i].a<<endl;
	}
	fin.close();
	ofstream ffout("a.txt",ios::out);
	for(int j=0 ; j<r ; j++)
	{
		ffout.write( reinterpret_cast< const char * >( &es[j] ),sizeof( es[j] ) );
	}
}
Well i worked on your program for a little bit and just couldn't seem to make that bit of code work. I ended up just dumbing down the program a bit and rewriting it.

For some reason i still see a ram number but its just at the bottom of the save file and doesn't make the program crash from the times i ran it. Hope this helps

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
#include <fstream>
#include <iostream>
#include <string>

using namespace std;



struct Student
{
	int id;
	string name;
};

const int SIZE = 52;

int main()
{
	Student roster[SIZE];
	Student search[SIZE];
	int ENROLLED = 0;
	int i, j, k;
	fstream outfile;
	outfile.open("roster.txt" , ios::out);
	cout<<"Enter the amount of students you would like to add"<<endl;
	cin>>ENROLLED;
	cout<<"-----------------------------------------------------"<<endl;
	for(i=0; i<ENROLLED;i++)
	{
		cout<<"Enter the Student ID:"<<endl;
		cin>>roster[i].id;
		cout<<"Enter the Name of the Student:"<<endl;
		cin>>roster[i].name;
		cout<<"*****************************************************"<<endl;
		outfile<<roster[i].id<<" "<<roster[i].name<<endl;
	}

	outfile.close();

	fstream infile;
	infile.open("roster.txt", ios::in);
	Student t;
	Student z;

		cout<<"Enter your Student ID and Name in format ID Name:"<<endl;
		cin>>t.id>>t.name;
	cout<<"*****************************************************"<<endl;


	for(j=0; !infile.eof(); j++)
	{
		infile>>search[j].id>>search[j].name;

		if(t.id==search[j].id)
		{
			cout<<"Enter your new Student ID and Name in Format ID Name:"<<endl;
			cin>>z.id>>z.name;
			search[j].id=z.id;
			search[j].name=z.name;
		}
	cout<<"-----------------------------------------------------"<<endl;
	
	cout<<search[j].id<<"\t"<<search[j].name<<endl;
	}
	infile.close();
	outfile.open("roster.txt" , ios::out);

	for(k=0; k <= ENROLLED; k++)
	{
		outfile<<search[k].id<<" "<<search[k].name<<endl;
	}

	return 0;
}
@Popasquat
Your code is completely different from Esmaeil's code, I guess OP is trying to do binary serialization. There is a big difference with write() and <<
Also, we don't take too well to people posting full solutions to any problem, just so you know.

reinterpret_cast< char * >( &es[i] )
This is a very dangerous feature of C++, and I hope you know what you're doing...

-Albatross

EDIT: 7*5*5*2 Posts and counting.
Last edited on
Sorry won't do it again, just trying to challenge myself as well. Wasn't trying to go against the forum guidelines or anything.

I am a new coder as well and figured the best way I would learn is by researching and try and fix other people's problems as my teacher in college isn't that wonderful but gives us phenomenal tests.

The reason I went with the solution I did is because I don't believe this is a school project but I could be wrong.

Sorry for the trouble just trying to pass CSC 1253 :(

Let me give my thoughts.

First of all this program shows some number (RAM numbers) instead of real information on monitor but it saves the correct information on file! Why?!
I tried to compile the code but it's the other way around for me, RAM bytes on the file and correct values (strings) on the standard output.


and second after running the program for second time, this time program crashes!
I believe the cause of that is the string member of you struct.

The program crashes on the second time you run the program since you completely copy the representation of the string member of your struct on the memory the first time it is run which is preserve using the file. That means the pointer of the string the first time it is run is pointing the same location the second time the program runs, which most probably that memory is not available anymore that causes the crash.


Well that is just my thoughts, I do not have resources to prove my correctness. Though to give a little evidence try not to print the string member (student.a) and print only the int member (student.id) on line 43
Thank you all, but the problem is still there.

@Popasquat
Your code have some error like mine. In second or more execution it doesn't work correctly and I think that's because of that RAM number saved in the end of file.
How can I fix this problem?

and really working with files is that hard that after seven posts the problem is still working!
Actually, I think what's messing you both up is that your codes are far too complex, and you have all these pointers you don't need. Try rereading the string library reference and more on iostream and call me in the morning.

http://cplusplus.com/reference/string/string/find/
http://cplusplus.com/reference/iostream/istream/getline/
http://cplusplus.com/reference/string/string/c_str/
http://cplusplus.com/reference/iostream/ostream/write/

-Albatrocter

EDIT: The number of degrees in a circle posts, and counting.
Last edited on
I read these before but I read again and nothing to hit the problem.
When using my code, after running it for second time the crash massage is about stack overflow I think.

And when using the Popasquat's code, and for fixing the problem, I add ios::app to first outfile.open and program doesn't work.
I really don't know what to do anymore.
Stack overflow? No way... Segmentation Fault, maybe...

First, delete everything you have. Either that, or put the file in the trash bin without emptying it. Just... don't... look... at... what... you... have.

Read out your whole file into a string. Use getline(), with a delimiting character being an EOF. Then, with everything in the buffer, mess about with it, find()ing stuff as needed. Print as needed as well from either that buffer or an originally identical one that you modified later, just remember to turn the contents of the C++ string into a c_str()ing.

-Albatross
Last edited on
Let us break the rules to learn from each other ok.


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

struct Student
{
    int id;
    char name[64];
};

int main()
{
    Student info;
    int r;
    ofstream fout("data.txt", ios::binary|ios::app);

    cout << "How many student do you want to add? ";
    cin >> r;
    for (int i=0 ; i<r; i++)
    {
        cout << "Enter ID: ";
        cin >> info.id;
        cin.get();
        cout << "Enter Name: ";
        cin.getline(info.name, 64);
        fout.write( (char*)(&info), sizeof(Student) );
        fout.flush();
        cout<<"\n\n";
    }
    fout.close();


    ifstream fin("data.txt", ios::binary);
    Student search_key;
    int pos = -1;

    cout<<"*****************************************\n\n";
    cout<<"Enter ID and name to search: \n";
    cin >> search_key.id;
    cin.get();
    cin.getline(search_key.name, 64);
    cout<<"******************************************\n\n";


    for (int i=0; !fin.eof() ; i++)
    {
        fin.read( (char*)(&info), sizeof(Student) );
        if ( info.id==search_key.id && strcmp(info.name, search_key.name)==0 )
        {
            cout << "\tEnter your new id and name:";
            cin >> info.id;
            cin.get();
            cin.getline(info.name, 64);
            pos = fin.tellg();
            break;
        }
        fin.peek();
    }
    fin.close();

    if ( pos>=0 )
    {
        fout.open("data.txt", ios::binary|ios::in);
        fout.clear();
        fout.seekp( pos-sizeof(Student) );
        fout.write( (char*)&info, sizeof(Student) );
        fout.close();
    }
    else
    {
        cout << "Data not found. . .\n\n";
    }

    cout<<"******************************************\n\n";
    fin.open( "data.txt", ios::binary );
    fin.clear();

    for (int i=0; !fin.eof() ; i++)
    {
        fin.read( (char*)(&info), sizeof(Student) );
        cout << i+1 << "\t\t" << info.id << "\t\t" << info.name << "\n\n";
        fin.peek();
    }
    fin.close();
    return 0;
}
First Run

How many student do youw want to add? 3
Enter ID: 9898
Enter Name: bill gates

Enter ID: 7878
Enter Name: steve jobs

Enter ID: 5555
Enter Name: michael jackson

******************************************

Enter ID and name to search:
-1 null
******************************************

Data not found. . .

******************************************
1		9898		bill gates

2		7878		steve jobs

3		5555		michael jackson



Second Run--------------------------------------------

How many student do youw want to add? 1
Enter ID: 7777
Enter Name: bjarne stroustrup


******************************************

Enter ID and name to search:
5555 michael jackson
******************************************

	Enter your new id and name:1234 james gosling
******************************************

1		9898		bill gates

2		7878		steve jobs

3		1234		james gosling

4		7777		bjarne stroustrup

Thank you all. Problem fixed and now I know that I really must read again and again all about strings and casting.
Thank you so very much.
How did you do it? I wanna know..
Just with thinking about my code, your code and comparison. and two other question:

Why do we need cin.get() in the following code?

1
2
3
cout << "Enter ID: ";
        cin >> info.id;
        cin.get();


and can you please explain how and what is casting in the line:

fout.write( (char*)(&info), sizeof(Student) );

I mean I always have problem with this type of casting and it would be so nice if you get me understand it now and forever.

Thank you so much.
Last edited on
Why do we need cin.get() in the following code?
1
2
3
cout << "Enter ID: ";
        cin >> info.id;
        cin.get();

Remember that when you input a number, you also input the enter key also know as line feed. get() will read one character from the stream, in our case the line feed. We do this to ensure that the stream is clear when getline() is called.



and can you please explain how and what is casting in the line:
fout.write( (char*)(&info), sizeof(Student) );
I believe the tutorial here can explain this better than me.
http://www.cplusplus.com/doc/tutorial/typecasting/

You can read this type of casting from right to left.
1
2
double d = 65.1654;
cout << (char)(int)(d); //convert d to int, convert that int to char 

Thank you.

I read the link above, So in this case fout.write does this:?
casts the address of info into char pointer and then all of data that now have been cast will be written to the file with the size of Student?

Again thank you so much.
casts the address of info into char pointer
Yes

and then all of data that now have been cast
No, only the reference to info will be casted.

will be written to the file with the size of Student?
Yes, write a number of bytes (size of Student) which starts from what the casted the location the pointer is pointing to (points to info)
Thank you again.

Now I have a final question but I myself do some coding and then if I could't solve the problem come here again!

Thank you.
Is any code in C++ to delete a number or string?

For example if I want to delete an ID and a name of a student I know that something like this will work:

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
ifstream fin("data.txt", ios::binary);
Student search_key;
int pos = -1;

cout<<"*****************************************\n\n";
cout<<"Enter your ID to search for deletion: ";
cin >> search_key.id;
cin.get();
cout<<"\nEnter your name to search for deletion: ";
cin.getline(search_key.name, 64);
cout<<"\n\n*****************************************\n\n";


for (int i=0; !fin.eof() ; i++)
{
	fin.read( (char*)(&info), sizeof(Student) );
	if ( info.id==search_key.id && strcmp(info.name, search_key.name)==0 )
	{
		
		info.id=null;
		
		info.name=null;
		break;
	}
	fin.peek();
}
fin.close();

if ( pos>=0 )
{
	 
	ofstream fout;
	fout.open("data.txt", ios::binary|ios::in);
	fout.clear();
	fout.seekp( pos-sizeof(Student) );
	fout.write( (char*)&info, sizeof(Student) );
	fout.close();
	cout<<"\n\nRecord was deleted\n\n";
}
else
{
	cout << "Data not found. . .\n\n";
}


but what can I put into the code instead of NULL to make the program works?

Thank you.
I know that I must do sth 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
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
ifstream fin("data.txt", ios::binary);
Student search_key;
int pos = -1;

cout<<"*****************************************\n\n";
cout<<"Enter your ID to search for deletion: ";
cin >> search_key.id;
cin.get();
cout<<"\nEnter your name to search for deletion: ";
cin.getline(search_key.name, 64);
cout<<"\n\n*****************************************\n\n";


for (int i=0; !fin.eof() ; i++)
{
	fin.read( (char*)(&info), sizeof(Student) );
	if ( info.id==search_key.id && strcmp(info.name, search_key.name)==0 )
	{
		
		pos = fin.tellg();
                                break;
	}
	fin.peek();
}
fin.close();

if ( pos>=0 )
{
	 
	ofstream fout;
	fout.open("data.txt", ios::binary|ios::in);
	fout.clear();
	fout.seekp( pos-sizeof(Student) );
	fout.write( (char*)&info, sizeof(Student) );
	fout.close();
	cout<<"\n\nRecord was deleted\n\n";
}
else
{
	cout << "Data not found. . .\n\n";
}



and in this line:

fout.write( (char*)&info, sizeof(Student) );


nothing must be written but how?



Pages: 12