how to execute file related cpp program

Hello everyone,
I am trying to execute the file operation program in COODEBLOCKS editor. The program executes. The search function and display functions are going infinite loop OR something is wrong.
Could you please let me know what is wrong.
Thanks

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<stdlib.h>
#include<iostream>
#include<fstream>
#include<string.h>
using namespace std;
class student
{
	public: char name[10];
		char usn[10];
		char age[5];
		char sem[5];
		char branch[5];
		char buffer[45];
};
fstream file;
student s;
void pack()
{
int k,n;
printf("how many records\n");
	scanf("%d",&n);
	for(k=0;k<n;k++)
	{
cout<<"\nenter the student name = ";
	cin>>s.name;
	cout<<"\nenter the usn = ";
	cin>>s.usn;
	cout<<"\nenter the age = ";
	cin>>s.age;
	cout<<"\nenter the sem = ";
	cin>>s.sem;
	cout<<"\nenter the branch = ";
	cin>>s.branch;
	strcpy(s.buffer,s.name);
	strcat(s.buffer,"|");
	strcat(s.buffer,s.usn);
	strcat(s.buffer,"|");
	strcat(s.buffer,s.age);
	strcat(s.buffer,"|");
	strcat(s.buffer,s.sem);
	strcat(s.buffer,"|");
	strcat(s.buffer,s.branch);
	int count=strlen(s.buffer);
for(int k=0;k<45-count;k++)
		strcat(s.buffer,"!");
	strcat(s.buffer,"\n");
file<<s.buffer;  
}
	file.close();
}
void writerecord()
{
	file.open("p2.txt",ios::out);
	if(!file)
	{
		cout<<"cannot open the file in out mode";
		exit(1);
	}
pack();
	
}
void unpack()
{
		file.getline(s.name,10,'|');
		file.getline(s.usn,10,'|');
		file.getline(s.age,5,'|');
		file.getline(s.sem,5,'|');
		file.getline(s.branch,5,'!');
}
void search()
{
	char usn[10];
	char extra[45];
	file.open("p2.txt",ios::in);
	if(!file)
	{
		cout<<"\nunable to open the file in read mode";
		exit(0);
	}
	cout<<"\nenter the record's usn you want to search = ";
	cin>>usn;
	while(!file.eof())
	{
		unpack();
		file.getline(extra,45,'\n');
		if(strcmp(s.usn,usn)==0)
		{
			cout<<"\nrecord found";
			cout<<"\n"<<s.name<<"\t"<<s.usn<<"\t"<<s.age<<"\t"<<s.sem<<"\t"<<s.branch;
			file.close();
			
			return;
		}
	}
	cout<<"\nrecord not found";
	file.close();
	
}
void displayFile()
{
	int i;
	char extra[45];
	file.open("p2.txt",ios::in);
	if(!file)
{
		cout<<"\ncannot open the file in read mode";
		exit(1);
	}
	i=0;
	cout<<"\n\nNAME\t\tUSN\t\tAGE\t\tSEM\t\tBRANCH\n";
	cout<<"----\t\t---\t\t---\t\t---\t\t------\n";
	while(!file.eof())
	{
		unpack();
		file.getline(extra,45,'\n');
		cout<<"\n"<<s.name<<"\t"<<s.usn<<"\t"<<s.age<<"\t"<<s.sem<<"\t"<<s.branch<<"\n";
	}
	file.close();
}
void modify()
{
	char usn[10];
	char buffer[45];
	char extra[45];
	int i;
	int j;
	student s[20];
	file.open("p2.txt",ios::in);
	if(!file)
	{
		cout<<"\nunable to open the file in input mode";
		exit(1);
	}
	cout<<"\nenter the usn of the record to be modified\n";
	cin>>usn;
	cout<<"\n";
	i=0;
	while(!file.eof())
	{
		file.getline(s[i].name,10,'|');
		file.getline(s[i].usn,10,'|');
		file.getline(s[i].age,5,'|');
		file.getline(s[i].sem,5,'|');
		file.getline(s[i].branch,5,'!');
		file.getline(extra,45,'\n');
		i++;
	}
	i--;
	for(j=0;j<i;j++)
	{
		if(strcmp(usn,s[j].usn)==0)
		{
			cout<<"\nthe old values of the record with usn"<<usn<<"are";
			cout<<"\n\nNAME\t\tUSN\t\tAGE\t\tSEM\t\tBRANCH\n";
			cout<<"----\t\t---\t\t---\t\t---\t\t------\n";
	cout<<s[j].name<<"\t"<<s[j].usn<<"\t"<<s[j].age<<"\t"<<s[j].sem<<"\t"<<s[j].branch<<"\n";
			cout<<"\n\nenter the new values\n";
			cout<<"\nname = ";
			cin>>s[j].name;
			cout<<"\nusn = ";
			cin>>s[j].usn;
			cout<<"\nage = ";
			cin>>s[j].age;
			cout<<"\nsem = ";
			cin>>s[j].sem;
			cout<<"\nbranch = ";
			cin>>s[j].branch;
			break;
		}
	}
	if(j==i)
	{
		cout<<"\nthe record with usn "<<usn<<"is not present ";
		return;
	}
	file.close();
	file.open("p2.txt",ios::out);
	if(!file)
	{
		cout<<"\nunable to open the file in output mode";
		return;
	}
	for(j=0;j<i;j++)
	{
strcpy(buffer,s[j].name);
		strcat(buffer,"|");
		strcat(buffer,s[j].usn);
		strcat(buffer,"|");
		strcat(buffer,s[j].age);
		strcat(buffer,"|");
		strcat(buffer,s[j].sem);
		strcat(buffer,"|");
		strcat(buffer,s[j].branch);
		int count=strlen(buffer);
		for(int k=0;k<45-count;k++)
			strcat(buffer,"!");
		strcat(buffer,"\n");
		file<<buffer;
	}
	file.close();
}
int main()
{
	int choice;
	while(1)
	{
		cout<<"\n 0 : exit \n 1 : write to file\n 2 : display the file\n 3 : modify the file\n 4 : search \n\n enter the choice : ";
		cin>>choice;
		switch(choice)
		{
			case 1: writerecord();
				break;
			case 2: displayFile();
				break;
			case 3: modify();
				break;
			case 4: search();
				break;
			case 0: exit(0);
			default:cout<<"\ninvalid input...";
				break;
		}
	}
return 0;
}
This is C++, so why are you using char arrays instead of std::strings?

1
2
3
4
	int count=strlen(buffer);
		for(int k=0;k<45-count;k++)
			strcat(buffer,"!");
		strcat(buffer,"\n");

45 chars + "!" + "\n" + "\0" does NOT fit into 45 characters.
You're overflowing your buffers.

Mixing C and C++ isn't a good idea.
1
2
printf("how many records\n");
	scanf("%d",&n);

Also beware of mixing >> and getline() as well.



Other issues.
- None of your functions have parameters or return results.
- You have a single global variable 's' for all internal communication between functions.

Your use of eof() is wrong as well, because it leads to this kind of code.
1
2
3
	i++;
	}
	i--;

eof() is a state (the result of a past event), not a prediction (of a future).
If you have a 10 line file, then calling getline 10 times does NOT make eof() true. You have to try and read the file for the 11th time to make eof() become true. That's why you have the i-- "oops, one too many" bodge.


Instead, this will loop as many times as required.
1
2
3
4
5
6
i=0;
while(file.getline(s[i].name,10,'|'))  // will exit the loop on the failure to read
{
	// your remaining getlines
	i++;
}



Hello newbeeindia,

In addition to what salem chas said do not use "exit()" this is a C function that causes an unconditional termination of the program. It does not know about C++ classes and anything else that needs cleaned up when the program ends. "exit()" does have its uses, but they are rare.

Your program should return to "main" and terminate properly.

Your include files:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdlib.h>  // <--- Should use "<cstdlib>" and "<cstdio>", but neither has a place in this program.
#include <iostream>
#include <fstream>
#include <string.h>  // <--- Should be "<cstring>", but you should be using "<string>" for the std::string class.

using namespace std;  // <--- Best not to use.

class Student
{
    public: 
        char name[10]{};
        char usn[10]{};
        char age[5]{};
        char sem[5]{};
        char branch[5]{};
        char buffer[45]{};
};

fstream file;     // <--- Define in functions where needed.
Student student;  // <--- Define in "main" and pass to functions when needed. 

Makes me wonder if you want to write a C program or a C++ program. There are times when mixing C and C++ code can not be avoided, but most of what you can do with C code can be done with C++ code.

Your class is not being used the way it should be. You could just as easily use a "struct" here.

Try to avoid using global variables. Any line of code that follows can change the global variable and that can be hard to track down. It is better to define the object in "main" and pass it to the functions that would need it.

I will jump ahead a bit. The "writerecord" function is unnecessary. It is only used for 1 purpose and that can be done in the "pack" function where it is used.

For the "pack" function, a better name would be GetUserInput" more descriptive for what it does, start by defining the file stream and opening the file. The better way would be std::ofstream file(("p2.txt"); followed by the is statement to check that the file stream is open and usable.

The code that you have:
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
void pack()
{
    int /*k,*/ numRecords;  // <--- ALWAYS initialize all your variables.

    printf("how many records: ");

    scanf("%d", &numRecords);

    for (int k = 0; k < numRecords; k++)
    {
        cout << "\nEnter the student name = ";
        cin >> student.name;

        cout << "\nEnter the usn = ";
        cin >> student.usn;

        cout << "\nEnter the age = ";
        cin >> student.age;

        cout << "\nEnter the sem = ";
        cin >> student.sem;

        cout << "\nEnter the branch = ";
        cin >> student.branch;

        strcpy(student.buffer, student.name);
        strcat(student.buffer, "|");
        strcat(student.buffer, student.usn);
        strcat(student.buffer, "|");
        strcat(student.buffer, student.age);
        strcat(student.buffer, "|");
        strcat(student.buffer, student.sem);
        strcat(student.buffer, "|");
        strcat(student.buffer, student.branch);

        int count = strlen(student.buffer);

        //for (int k = 0; k < 45 - count; k++)
        //    strcat(student.buffer, "!");

        strcat(student.buffer, "\n\0");

        file << student.buffer;
    }

    file.close();  // <--- Not required as the dtor will close the file when the function looses scope.
}

The variable "k" is never used and is better defined in the for loop, which you do not need, where it is a local variable to the for loop.

A good variable like "numRecords" is much better than "n". At least you know what you are using it for.

Lines 5 and 7 should be replaced with "std::cout" and "std::cin" and follow the "std::cin" with "std::cin.ignore()" to clear the new line (\n) from the input buffer.

Inside the for loop you do not need to use the class or a struct here just define those variables in the function.

Lines 26 - 34 are doing more work than you need.

Lines 36 along with 38 and 39 are filling the complete array with "!"s leaving no room for the "\n\0" that you need at the end of the array. Without the "\0" to mark the end when you try to output the Buffer array it does not know when to stop. Also filling the array with "!"s when you go to add the "\n\0" to the end of the array it is beyond the size of the array and you do not know what memory you are writing to and the program crashes.

By creating local variables for input your output would be:
file << name + pipe + usn + pipe + ... + branch + "\n";. This can be achieved with just 1 line of code without all that extra work and C code. The "pipe" would be defined as std::string pipe{ "|" };.

Looking ahead when you read the file using your file.getline(student.name, 10, '|'); This works fine until the last line which would be file.getline(student.branch, 5); // <--- Remove delimiter. . This takes whatever is left + the "\n", which it discards, and leaves the file pointer at the beginning of the next record.

I have tested this and it works for what you need:
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
int GetuserInput()
{
    std::ofstream file("p2.txt");

    if (!file)
    {
        cout << "cannot open the file in out mode";
        //std::cout << "\n     File \"p2.txt\" did not open!\n\n";

        return 1;  // <--- Do not use "exit". Return works better along with the function returning an "int".
    }

    int numRecords;  // <--- ALWAYS initialize all your variables.
    std::string name, usn, age, sem, branch, pipe{ "|" };

    std::cout << "how many records: ";

    std::cin >> numRecords;
    std::cin.ignore();

    for (int k = 0; k < numRecords; k++)
    {
        cout << "\nEnter the student name = ";
        std::getline(std::cin, name);

        cout << "\nEnter the usn = ";
        std::getline(std::cin, usn);

        cout << "\nEnter the age = ";
        std::getline(std::cin, age);

        cout << "\nEnter the sem = ";
        std::getline(std::cin, sem);

        cout << "\nEnter the branch = ";
        std::getline(std::cin, branch);

        file << name + pipe + usn + pipe + age + pipe + sem + pipe + branch + "\n";
    }

    return 0;

    //file.close();  // <--- Not required as the dtor will close the file when the function looses scope.
}

For what little bit you are doing here this works better than trying to make use of the class or a struct.

Before I run out of room, this is what I did for "main":
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
int main()
{
    bool done{};  // <--- ALWAYS initialize all your variables.
    int choice{}, result{};

    while (!done)
    {
        cout <<
            "\n"
            " 0 : Exit\n"
            " 1 : Write to file\n"
            " 2 : Display the file\n"
            " 3 : Modify the file\n"
            " 4 : Search\n"
            "  Enter the choice: ";
        cin >> choice;

        switch (choice)
        {
            case 1:
                if (result = GetuserInput())
                    return result;

                break;
            case 2:
                displayFile();

                break;
            case 3:
                modify();

                break;
            case 4:
                search();

                break;
            case 0:
                done = true;
            default:
                cout << "\n    Invalid input...!\n\n";
                break;
        }
    }

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


I will look at the "display" function next.

Andy
Topic archived. No new replies allowed.