sorting for strings (putting a list in alphabetical order)

Pages: 12
Line 100: You're passing tmp by value, which means you're passing a copy. Any changes made to the local copy are lost at line 105 when the local copy goes out of scope. You should be passing by reference.

Line 45: You need to copy tmp to student[item], then increment item. Or you could just pass student[item] and get rid of tmp.


I really don't understand how to do this, I have tried many thing(below is one), but I just don't get the logic on how to save the input and output it in the file.

1
2
3
4
5
6
7
8
9
10
void addcontact(persons& tmp,persons& student[],int& item,ifstream& file){
	cout<<"enter first name"<<endl;
	cin>>tmp.first_name;
	for(int i=0;i<item+1;i++)
		file<<getline(cin,tmp.first_name);
	cout<<"enter last name"<<endl;
	cin>>tmp.last_name;
	for(int i=0;i<item+1;i++)
			file<<getline(cin,tmp.last_name);
}

I think you are trying to do too much in a single function, as a result it has a long list of parameters and complex code.

I would suggest a function:
void addcontact(persons student[], int& item)

The things which the function will need to update are
 
student[item].first_name
 
student[item].last_name

and add 1 to item afterwards.

As for writing the data to the file, I'd make that into a separate function. It would be a design decision as to whether to save the file at this point, or wait until the end of the program and save the file before terminating the program.


save the file at this point
- how do you do this? i'm under the impression the program only writes to file when main() returns but please correct me if o/wise
At the moment the program doesn't write to the file at all.
It would need to open an ofstream, loop through the array (much like when displaying on the screen) and write the data to the file instead of to std::cout.
So after a lot of online surfing, I have learned a few things how files work. Apparently you cannot write into a ifstream file. So i was successfully able to output the names into another file and sort the names in that file. But I still am not able to add a name to the new file. I have played around with the code for hours, but after every attempt i get an error upon errors. Please give me some important tips(i am not saying give me the answer). The following is the most recent version of my code.
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
#include<iostream>
#include<string>
#include<fstream>
using namespace std;


struct persons{
	string first_name;
	string last_name;
};

void openfile(persons student[], int& item,ifstream&file,ofstream& outfile);
void swappersons(persons& name1, persons& name2);
void sortbyfirstname(persons student[], int& item);
void output(persons student[], int& item,ofstream&outfile);
void closefile(ifstream& file,ofstream&outfile);
void sortbylastname(persons student[],int& item);
//void addcontact(persons& tmp,persons& student[],int& item,ofstream& outfile);
int main(){
	int item,choice;
	persons student[1000],tmp;
	ifstream file;
	ofstream outfile;
	string info;
	openfile(student, item,file,outfile);
	while(choice!=4){
	cout<<"MAIN MENU- please select an option"<<endl;
		cout<<"select 1 to sort names by first name"<<endl;
		cout<<"select 2 to sort names by last name"<<endl;
		cout<<"select 3 to add a name"<<endl;
		cout<<"select 4 to end program"<<endl;
		cin>>choice;
		switch(choice)
		{
		case 1:
			cout<<"*****************************"<<endl;
		    sortbyfirstname(student,item);
	            output(student, item,outfile);
	            cout<<endl;
	            break;
		case 2:
			cout<<"*****************************"<<endl;
		    sortbylastname(student,item);output(student, item,outfile);
		    cout<<endl;
		    break;
		case 3:
		    //addcontact(tmp,student,item,outfile);
			cout<<"cant do it yet"<<endl;
		    break;
		case 4:
			cout<<"program has ended"<<endl;
			return 0;
		 default:
		    cout << "Invalid input, Terminating Program" << endl;
		    break;
		}
	closefile(file,outfile);
}
}
void openfile(persons student[], int& item,ifstream&file,ofstream& outfile)
{
    file.open("students");
    if (!file)
    {
        cout << "file open error" <<endl;
    }
    item = 0;
    	    while (file >> student[item].first_name >> student[item].last_name)
    	    {
    	        item++;
    	    }


}

//void read_infile(ifstream&file,int&item,persons student[]){
/*void addcontact(persons& tmp,persons& student[],int& item,ofstream& outfile){
		cout<<"enter first name"<<endl;
		cin>>tmp.first_name;
		for(int i=0;i<item+1;i++){
			outfile<<getline(cin,tmp.first_name);
		item++;}
		cout<<"enter last name"<<endl;
		cin>>tmp.last_name;
		for(int i=0;i<item+1;i++){
				outfile<<getline(cin,tmp.last_name);
				item++;}
}
*/

void swappersons(persons& name1, persons& name2){
	persons temp;
	temp=name1;
	name1=name2;
	name2=temp;
}

void sortbyfirstname(persons student[], int& item){
	for(int a=0; a<item-1; a++)
	{
		for(int i=0; i<item-1; i++)
			if(student[i].first_name > student[i+1].first_name)
				swappersons(student[i],student[i+1]);


	}

}

void sortbylastname(persons student[],int& item){
	for(int a=0; a<item-1; a++)
		{
			for (int i=0; i<item-1; i++)
				if(student[i].last_name>student[i+1].last_name)
					swappersons(student[i],student[i+1]);
	}
}


void output(persons student[], int& item,ofstream&outfile){
	outfile.open("studentstmp");
	for(int i=0; i<item; i++){
		outfile<< student[i].first_name<<" "<<student[i].last_name<<" "<<endl;
	cout<< student[i].first_name<<" "<<student[i].last_name<<" "<<endl;}
	outfile.close();
}

void closefile(ifstream& file,ofstream&outfile){
		file.close();
		//outfile.close();
		cout<<"********************************"<<endl;
}


EDIT...
I have edited my function add contacts to be as follows(this one does not give me any errors).
Now i'm trying to save this in a array.
Am I on the right track, or am I completely wrong with the way i'm solving this problem?


1
2
3
4
5
6
7
8
9
10
11
12
13
void addcontact(persons& tmp,int& item,ofstream& outfile){

cout<<"enter first name"<<endl;
cin>>tmp.first_name;
getline(cin,tmp.first_name);
outfile<<tmp.first_name;
cout<<"enter last name"<<endl;
cin>>tmp.last_name;
getline(cin,tmp.last_name);
outfile<<tmp.last_name;
item++;

}

or
1
2
3
4
5
6
7
8
9
10
11
12
13
void addcontact(persons& tmp,int& item,ofstream& outfile,persons student[]){
	char input;
	string newname;
cout<<"enter first name and last name followed by a return"<<endl;
cin>>input;
while(input!='\n'){
	for(int i=0;i<student[item];i++){   //error on this line
			cin>>newname;
			getline(cin,newname);
			outfile<<newname;
	}
}
}

or
1
2
3
4
5
6
7
8
9
10
11
12
13
14
void addcontact(persons& tmp,int& item,ofstream& outfile,persons student[]){
	char input;
	string newname;
	cout<<"enter first name and last name followed by a return"<<endl;
	cin>>input;
while(input!='\n'){

			cin>>newname;
			getline(cin,newname);
			student[item+1]=newname;//error here
			item++;
			outfile<<newname;
	}
}
Last edited on
OP: this could put you out of your misery if you're willing to learn a few new things. Even if you aren't, two things to bear in mind (a) cin and getline are mortal enemies, so be very careful when you are mixing the two and (b) the following point that Chervil makes is extremely important:
It would be a design decision as to whether to save the file at this point, or wait until the end of the program and save the file before terminating the program ...

As the number of names in your program is not large I went for the first option which enables you to add a name and read it back real time while the program is still running but it involves opening and closing the file several times during the course of the program and may not be feasible as the file size grows in which case you'd have to go for the second option.
That would imply reading the file once at the start of the program, saving it into the vector, doing stuff, adding a name if you wish but first saving this name in the vector itself and then, at the very end, writing this vector back to the file. In that case (a) you'd not open ofstream in append mode and (b) new names added during the course of a program run will not appear under the sort results. Good luck!
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
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;

struct persons
{
	string first_name;
	string last_name;
};
struct fnameSort
{
    bool operator()(const persons& lhs, const persons& rhs)
    {
        return (lhs.first_name < rhs.first_name);
    }
};
struct lnameSort
{
    bool operator()(const persons& lhs, const persons& rhs)
    {
        return (lhs.last_name < rhs.last_name);
    }
};
ifstream& operator >> (ifstream& is, persons& p)
{
     is >> p.first_name >> p.last_name;
     return is;
}
ostream& operator << (ostream& os, const persons& p)
{
    os << p.first_name << " " << p.last_name;
    return os;
}
int main()
{
    bool fQuit = false;
    bool name_add = false;
    while(!fQuit)
    {
        cout << "1. Sort by first name \t2. Sort by last name \t3. Add name \t4. Quit\n";
        string choice;
        getline (cin, choice);
        stringstream stream(choice);
        int int_choice;
        if(!(stream>>int_choice) || stream.peek() != std::char_traits<int>::eof())
        {	
        cout<<"Incorrect entry, try again\n";
        }
        else
        {
            switch (int_choice)
            {
                case 1:
                {
                    ifstream infile("D:\\test.txt");
                    vector<persons> names;
                    while(infile)
                    {
                        persons dummy;
                        infile >> dummy;
                        if(infile)
                        {
                            names.push_back(move(dummy));
                        }
                    }
                    sort(names.begin(), names.end(), fnameSort());
                    for (auto& elem : names)
                    {
                        cout << elem << '\n';
                    }
                }
                break;
                case 2:
                {
                    ifstream infile("D:\\test.txt");
                    vector<persons> names;
                    while(infile)
                    {
                        persons dummy;
                        infile >> dummy;
                        if(infile)
                        {
                            names.push_back(move(dummy));
                        }
                    }
                    sort(names.begin(), names.end(), lnameSort());
                    for (auto& elem : names)
                    {
                        cout << elem << '\n';
                    }
                }
                break;
                case 3:
                {
                    cout<< "Enter name to add: \n";
                    string temp;
                    if(getline( cin >> ws, temp))
                    {
                        istringstream stream(temp);
                        persons dummy;
                        while (stream)
                        {
                            stream >> dummy.first_name >> dummy.last_name;
                        }
                        ofstream fout("D:\\test.txt", ios_base::app);
                        fout << '\n' << dummy;
                    }
                }
                break;
                case 4:
                {
                    cout << "Goodbye \n";
                    fQuit = true;
                }
                break;
                default:
                    cout << "Incorrect option, try again \n";
                break;
            }
        }
    }
}

(edit) PS: ofstream inherits the operator << overload from ostream
Also, you could have a second vector just for the added names and then you could write only this vector to the file in which case ofstream would be in append mode
Last edited on
Please give me some important tips(i am not saying give me the answer).

Here's one - it can apply in general, not just here.

Try to write small simple functions which do just one task, and do it well.

Now, going back to my previous post I quote
Chervil wrote:
I think you are trying to do too much in a single function, as a result it has a long list of parameters and complex code.

I would suggest a function:
 
void addcontact(persons student[], int& item)

The things which the function will need to update are
 
student[item].first_name
 
student[item].last_name
and add 1 to item afterwards.

As for writing the data to the file, I'd make that into a separate function.
http://www.cplusplus.com/forum/beginner/204577/2/#msg970798

Here are the two functions:
1
2
3
4
5
6
7
8
9
void addcontact(persons student[], int& item)
{
    cout << "enter first name" << endl;
    cin >> student[item].first_name;
    cout << "enter last name" << endl;
    cin >> student[item].last_name;
    
    item++;
}


1
2
3
4
5
6
7
void savefile(persons student[], int& item)
{
    ofstream file("students.txt");
    
    for (int i=0; i<item; i++)
        file << student[i].first_name << " " << student[i].last_name << '\n';
}


And the menu code would look like this:
1
2
3
4
    case 3:
        addcontact(student, item);
        savefile(student, item);
        break;

Last edited on
I'd also do the main menu as a loop:
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
int main()
{
    int item = 0;
    persons student[1000];
    openfile(student, item);

    char choice = ' ';
    while (choice != '0')
    {
        cout << "please select an option\n"
                "select 1 to sort names by first name\n"
                "select 2 to sort names by last name\n"   
                "select 3 to add a name\n"
                "select 4 to list names\n"
                "select 0 to end the program\n";
                
        cin >> choice;
        switch (choice)
        {
            case '1':
                sortbyfirstname(student, item);
                output(student, item);
                break;
                
            case '2':
                sortbylastname(student, item);
                output(student, item);
                break;
                
            case '3':
                addcontact(student, item);
                savefile(student, item);
                break;
                
            case '4':
                output(student, item);
                break;
         
            case '0':
                cout << "Program is Ending. Goodbye\n";
                break;
                       
            default:
                cout << "Invalid input, try again" << endl;
                break;
        }    
    }
}
Last edited on
@gunnerfunner Your response looks rather good, and though I didn't try to run it, I'm sure it makes sense.

One area where I prefer to do things differently is that you've placed largish chunks of code within the main() function. As a matter of preference, I like to keep the overall picture easily visible, a bit like the contents page of a book, the main structure is clearly visible, and if the reader wants to know more about a particular topic, one goes to that chapter, rather than finding the text pasted in the middle of the contents page. These are design decisions, But I too often find beginners code with a main() two or three hundred lines long and lots of nested structures, so that it becomes impossible to gain any sort of view of the overall picture. (I'm not suggesting you are a beginner - I was alluding to some of the code found elsewhere on these forums).
Chervil - this is constructive feedback, I appreciate it. Thanks
Thank you so much guys, the program runs successfully. You guys helped me a lot!
Topic archived. No new replies allowed.
Pages: 12