Sorting an array of strings from a txt file.

Pages: 12
Hey for my code I need it to sort an array of strings in alphabetical order. The strings are stored in a text file and can be loaded to be written in. I cannot seem to get my program to sort the strings and am currently stuck.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//the prototype
void bubbleSort(musicRecord list[], int size);

//this is my function to sort
 void bubbleSort(musicRecord list[], int size) 
{ 
 	string temp;
    for (int i=0; i<size; i++)
    {
        for (int j=0; j < size-i; j++)
        {
            if (strcmp(list[j],list[j+1])) 
            {
            	temp = list[j];
            	list[j] = list[j+1];
            	list[j+1] = temp;
            }
        }
    }

}
Last edited on
For your code to work, it needs to have inherited from string class aka basic_string<char>. What does your class/struct musicRecord look like?
Last edited on
struct musicRecord
{
string name;
string album;
string artist;
string genre;
};

This is the struct I have.
What property of music record are you trying to use to sort the record? If you are sorting by name then your bubblesort should look something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include  <algorithm>

void bubbleSort(musicRecord list[], int size) 
{ 
    for (int i=0; i<size; i++)
    {
        for (int j=0; j < size-i; j++)
        {
            if (strcmp(list[j].name,list[j+1].name) < 0) 
            {
            	std::swap(list[j], list[j + 1]);
            }
        }
    }
}
Last edited on
Hi I was trying to compare it to list[].name sorry about the ambiguity. Using your code I get the error:

[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'

I am not quite sure what the problem here is.
The problem is that strcmp requires a char array rather than basic_string<char>. So to fix, do this in the strcmp:

strcmp(list[j].name.c_str(),list[j+1].name.c_str())
Hey there the code compiles now but I have encountered another problem unfortunately. I have a txt document written as shown:

Fury;FuryOhFury;NicoVega;Rock
;One For The Road;AM;ArcticMonkeys;Rock
;Half Light II;TheSuburbs;ArcadeFire;IndieRock
;Knee Socks;AM;ArcticMonkeys;Rock
;Tighten Up;Brothers;TheBlackKeys;Rock
;Battles;Lost;HudsonTaylor;Indie

When I want add to the following list I use this function:

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
void addTrack(musicRecord list[], int &size)
{
	musicRecord tmp;
	char save;
	char song[256], album[256], artist[256], genre[256];
	if ( size <= MAX_SIZE) {
			while (true)
			{
			
			system("cls");
            cout << "*Type 'quit' to exit on any entry.*" << endl;
            cout << "\n";
		    cout << "Enter the name of the song: ";
		    cin.getline(song, 256);
			cout << "Track: ";
		    if ( strcmp(song, "quit") ==0) 
            {
            	system("cls");
            	break;
            }
		    tmp.name = song;
		    cout << tmp.name << endl;
			cout << "\n";
		    	
	    	cout << "What album is the song in: ";
            cin.getline(album, 256);
			cout << "Album:	" ;
			if ( strcmp(album, "quit") ==0) 
            {
            	system("cls");
            	break;
            }
			tmp.album = album;
			cout << tmp.album << endl;
            cout << "\n";
		
		    cout << "The artist of the song: ";
			cin.getline(artist, 256);
			cout << "Artist: ";
			if ( strcmp(artist, "quit") ==0) 
            {
            	system("cls");
            	break;
            }
	     	tmp.artist = artist;
	     	cout << tmp.artist << endl;
			cout << "\n";		
			
		    cout << "The song's genre: ";
	    	cin.getline(genre, 256);
			cout << "Genre:	 ";
			if ( strcmp(genre, "quit") ==0) 
            {
            	system("cls");
            	break;
            }
        	tmp.genre = genre;
        	cout << tmp.genre << endl;
        	cout << "\n";
        	
	     	cout << "Do you want to store these records? (y/n)" << endl;
	        cin >> save;
           	cin.ignore(256, '\n');
           	
	        if( save == 'y') 
            {
	        	list[size] = tmp;
                size++;
            }
        }
      }
}


Then I save the new entries into the txt document but it becomes saved as:

Fury;NicoVega;FuryOhFury;Rock
;One For The Road;ArcticMonkeys;AM;Rock
;Half Light II;ArcadeFire;TheSuburbs;IndieRock
;Knee Socks;ArcticMonkeys;AM;Rock
;Tighten Up;TheBlackKeys;Brothers;Rock
;Battles;HudsonTaylor;Lost;Indie
;Yeah;Noway;Hippies;Great //new entry from my program
;;;; // not sure where these are coming from
; //

Save function:

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
void saveData(const musicRecord list[], int size)
{
	//remove("Tracks.txt");
	ofstream outfi("Tracks.txt");
  	if (!outfi.fail()) 
	{  
   		cout << "The tracks are being added to the list! \n";
    
   		for(int i = 0; i <= size; i++) 
		{
    		outfi << list[i].name << ";";
      		outfi << list[i].album << ";";
     		outfi << list[i].artist << ";";
     		outfi << list[i].genre << "\n;";
		}
    	cout << endl << size << " tracks have been saved to the file. \n" << endl;
   		outfi.close();
   		system("PAUSE");
	} 
	else 
	{
    	cout << "ERROR: cannot save to file!" << endl;
    	system("PAUSE");
	}
	system("cls");
}


Forgive me for the questions I am still new to this.

Change your line 9 of the save function to this:

for(int i = 0; i < size; i++)
Thank you so much for all the help thus far!

Going back to the sort function, when I execute the sort and then save to the text document, the text file is changed from:


Fury;FuryOhFury;NicoVega;Rock
;One For The Road;AM;ArcticMonkeys;Rock
;Half Light II;TheSuburbs;ArcadeFire;IndieRock
;Knee Socks;AM;ArcticMonkeys;Rock
;Tighten Up;Brothers;TheBlackKeys;Rock
;Battles;Lost;HudsonTaylor;Indie

to

// after executing the sort and saving
;;;
;Battles;HudsonTaylor;Lost;Indie
;Tighten Up;TheBlackKeys;Brothers;Rock
;Knee Socks;ArcticMonkeys;AM;Rock
;Half Light II;ArcadeFire;TheSuburbs;IndieRock
;One For The Road;ArcticMonkeys;AM;Rock
;

It would seem that the sort only moves one of the song names and not the rest. It would seem that the extra semi colons also return. This leaves me to believe that it is due to my save function but I am not sure.

This is my current save function:
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
void saveData(const musicRecord list[], int size)
{
	//remove("Tracks.txt");
	ofstream outfi("Tracks.txt");
  	if (!outfi.fail()) 
	{  
   		cout << "The tracks are being added to the list! \n";
    
   		for(int i = 0; i < size; i++) 
		{
    		outfi << list[i].name << ";";
      		outfi << list[i].album << ";";
     		outfi << list[i].artist << ";";
     		outfi << list[i].genre << "\n;";
		}
    	cout << endl << size << " tracks have been saved to the file. \n" << endl;
   		outfi.close();
   		system("PAUSE");
	} 
	else 
	{
    	cout << "ERROR: cannot save to file!" << endl;
    	system("PAUSE");
	}
	system("cls");
}


The sort function is the same:
1
2
3
4
5
6
7
8
9
10
11
12
13
void bubbleSort(musicRecord list[], int size) 
{ 
    for (int i=0; i<size; i++)
    {
        for (int j=0; j < size-i; j++)
        {
            if (strcmp(list[j].name.c_str(),list[j+1].name.c_str()))
            {
            	swap(list[j], list[j + 1]);
            }
        }
    }
}
What value does strcmp return? In what order are you trying to sort the names in? Ascending or descending?

http://www.cplusplus.com/reference/cstring/strcmp/

To sort in Descending order i.e. A, B, C, D, E, F,...

if (strcmp(list[j].name.c_str(),list[j+1].name.c_str()) > 0)

To sort in Ascending order i.e. ...,F, E, D, C, B, A

if (strcmp(list[j].name.c_str(),list[j+1].name.c_str()) < 0)
Hi again I wanted to sort in descending order and your line of code fixed the problem. I am having a problem where when I want to save the sorted array into the text document, the text is saved as:

;;;
;Battles;HudsonTaylor;Lost;Indie
;Fury;NicoVega;FuryOhFury;Rock
;Half Light II;ArcadeFire;TheSuburbs;IndieRock
;Knee Socks;ArcticMonkeys;AM;Rock
;One For The Road;ArcticMonkeys;AM;Rock
;

instead of :

Battles;HudsonTaylor;Lost;Indie
;Fury;NicoVega;FuryOhFury;Rock
;Half Light II;ArcadeFire;TheSuburbs;IndieRock
;Knee Socks;ArcticMonkeys;AM;Rock
;One For The Road;ArcticMonkeys;AM;Rock

I would also like the program to be able to edit a particular struct in the array if this is possible. I understand that to be able to do this I have to search the array for a particular name, access the struct then change it's contents. Is this possible? Thank you for all the help you have been wonderful I have been stuck for days!
How do you call the function:

void addTrack(musicRecord list[], int &size)

Post the line you use to call the function.

If you are not worried about speed, you can use a simple linear search of the list and at each iteration, you can use:

1
2
3
4
if (strcmp(list[i].name.c_str(), searchName.c_str()) == 0)
{
    //...change contents of list[i]
}
Last edited on
I used a switch in main to call the function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
 
 while (run == true)
    {
    	switch (opMenu()) 
		{
			case 'A': addTrack(list, size); break;
			//case 'e': editTrack(list, MAX_SIZE); break;
			case 'F': findTrack(list, MAX_SIZE); break;
			case 'S': saveData(list, size); break;
			case 'B': bubbleSort(list, size); break;
			case 'D': displayTracks(list, size); break;
			case 'O': openData(list, size); break;
			//case 'T': saveData(list, size); break;
			case 'Q': run = false; break;
			default : cout << "You did not make a valid selection!";
   		}
	}
 


Thanks for the suggestion I will definitely give it a shot!
What is initial size of list and what is the initial value of size? Post them here. I have a feeling the problem is coming from the way you post increment size
I am sorry I am not sure how to to find the initial size and initial value of size. I have the array set at size = 9 and have that globally declared as

 
const int MAX_SIZE = 9;


and in main

 
musicRecord list[MAX_SIZE];


Ok initial size of the array is MAX_SIZE, but where did you first declare the variable size? I see you used it in main, where was it first declared?

If this is sounding repetetive, this is the size I am refering to now:

case 'A': addTrack(list, size); break;
Last edited on
In main as:

1
2
3
4
5
6
int main()
{
	intro();
	bool run = true;
	int size = 0;
	musicRecord list[MAX_SIZE];


Hopefully this is what you were looking for.
Ok, I'm gonna use the hackish solution here.

In main, declare size as int size = -1.

In addTrack, find this if statement
if( save == 'y')

Change the code below it to:
1
2
3
{
    list[++size] = tmp;
}


In saveData, change line 14 to:
outfi << list[i].genre << ";\n";
Last edited on
I have a line of code that shows how many elements are filled and if I declare
 
int size = -1;


It displays it as -1. Is there a possible fix so that changing the initialization is not necessary?

Also the text document after saving is now:

;;;
Battles;HudsonTaylor;Lost;Indie
Fury;NicoVega;FuryOhFury;Rock
Half Light II;ArcadeFire;TheSuburbs;IndieRock
Knee Socks;ArcticMonkeys;AM;Rock
One For The Road;ArcticMonkeys;AM;Rock

I require the semi colons in front of each name so that when I open the text document for reading the display is correct, otherwise I get certain strings in the wrong places in my display.

What I need the text document to be saved as:

Battles;HudsonTaylor;Lost;Indie
;Fury;NicoVega;FuryOhFury;Rock
;Half Light II;ArcadeFire;TheSuburbs;IndieRock
;Knee Socks;ArcticMonkeys;AM;Rock
;One For The Road;ArcticMonkeys;AM;Rock

Could this be a problem in my display function?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
void displayTracks(musicRecord list[], int &size)
{
	 if (size < 1) {
	 	system("cls");
		cout << "There are no records to display!" << endl;
 	 } else {
 	 	system("cls");
		cout << "These are the songs found in the file: \n" << endl;

		for(int i = 0; i < size; i++) {
    		cout << "Title:  " << list[i].name << endl;
    		cout << "Album:  " << list[i].album << endl;
    		cout << "Artist: " << list[i].artist << endl;
    		cout << "Genre:  " << list[i].genre << endl;
	 }
	 system("pause");
	 system("cls");
}


This is my open file function:

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
void openData(musicRecord list[], int &size)
{
	system("cls");
    ifstream doc("Tracks.txt");
  	string str;
  	stringstream strstrm;

      if (!doc.fail()) 
      { 
		size = 0; 
    	while(!doc.eof() && size < MAX_SIZE) 
		{
       		getline(doc, str, ';');
			strstrm.str(""); strstrm.clear();
			strstrm << str; 
       		list[size].name = str;
       		
       		getline(doc, str, ';');
       		strstrm.str(""); strstrm.clear(); 
       		strstrm << str; 
       		strstrm >> list[size].artist;   		
       		
       		getline(doc, str, ';'); 
       		strstrm.str(""); strstrm.clear(); 
       		strstrm << str; 
       		strstrm >> list[size].album;   		
       		
       		getline(doc, str, ';'); 
       		strstrm.str(""); strstrm.clear(); 
       		strstrm << str;
            strstrm >> list[size].genre;
                   
            size++;
      	}
    	cout << endl << size << " records were loaded into the program." << endl;
   		system("PAUSE");
      }
      else 
	  { 
    	cout << "ERROR: problem with file" << endl;
    	system("PAUSE");
    	system("cls");
  	  }
}


Thank you so much for the help forgive my ignorance.
Last edited on
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
struct musicRecord
{
    string name, album, artist, genre;
};

void addTrack(musicRecord list[], int &size)
{
    musicRecord tmp;
    char save;
    while (size < MAX_SIZE)
    {

	system("cls");
	cout << "*Type 'quit' to exit on any entry.*" << endl << endl;

	cout << "Enter the name of the song: ";
	getline(cin, tmp.name);

	if ( strcmp(tmp.name.c_str(), "quit") ==0)
	{
	    system("cls");
	    break;
	}
	cout << "Track:\t";
	cout << tmp.name << endl << endl;

	cout << "What album is the song in: ";
	getline(cin, tmp.album);

	if ( strcmp(tmp.album.c_str(), "quit") == 0)
	{
	    system("cls");
	    break;
	}
	cout << "Album:\t" ;
	cout << tmp.album << endl << endl;

	cout << "The artist of the song: ";
	getline(cin, tmp.artist);

	if ( strcmp(tmp.artist.c_str(), "quit") == 0)
	{
	    system("cls");
	    break;
	}
	cout << "Artist:\t";
	cout << tmp.artist << endl << endl;

	cout << "The song's genre: ";
	getline(cin, tmp.genre);

	if ( strcmp(genre, "quit") ==0)
	{
	    system("cls");
	    break;
	}
	cout << "Genre:\t";
	cout << tmp.genre << endl << endl;

	cout << "Do you want to store these records? (y/n)" << endl;
	cin >> save;
	cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

	if( (save | 32) == 'y')
	{
	    list[++size] = tmp;
	}
    }
}

void bubbleSort(musicRecord list[], int size)
{
    for (int i=0; i<size; i++)
    {
	for (int j=0; j < size-i; j++)
	{
	    if (strcmp(list[j].name.c_str(),list[j+1].name.c_str()) > 0)
	    {
		swap(list[j], list[j + 1]);
	    }
	}
    }
}

void displayTracks(const musicRecord list[], int size)
{
    if (size < 1) {
	system("cls");
	cout << "There are no records to display!" << endl;
    }
    else {
	system("cls");
	cout << "These are the songs found in the file: \n" << endl;

	for(int i = 0; i < size; i++) {
	    cout << "Title:  " << list[i].name << endl;
	    cout << "Album:  " << list[i].album << endl;
	    cout << "Artist: " << list[i].artist << endl;
	    cout << "Genre:  " << list[i].genre << endl;
	}
	system("pause");
	system("cls");
    }
}


void openData(musicRecord list[], int &size)
{
    system("cls");
    ifstream doc("Tracks.txt");
    string str;
    stringstream strstrm;

    size = 0;
    if (!doc.fail())
    {
	while(!doc.eof() && size < MAX_SIZE)
	{
	    getline(doc, str, ';');
	    strstrm.str(""); strstrm.clear();
	    strstrm << str;
	    list[size].name = str;

	    getline(doc, str, ';');
	    strstrm.str(""); strstrm.clear();
	    strstrm << str;
	    strstrm >> list[size].artist;

	    getline(doc, str, ';');
	    strstrm.str(""); strstrm.clear();
	    strstrm << str;
	    strstrm >> list[size].album;

	    getline(doc, str, ';');
	    strstrm.str(""); strstrm.clear();
	    strstrm << str;
	    strstrm >> list[size].genre;

	    ++size;
	}
	cout << endl << size << " records were loaded into the program." << endl;
	system("PAUSE");
    }
    else
    {
	cout << "ERROR: problem with file" << endl;
	system("PAUSE");
	system("cls");
    }
}


void saveData(const musicRecord list[], int size)
{
    //remove("Tracks.txt");
    ofstream outfi("Tracks.txt");
    if (!outfi.fail())
    {
	cout << "The tracks are being added to the list! \n";

	for(int i = 0; i < size; i++)
	{
	    outfi << list[i].name << ";";
	    outfi << list[i].album << ";";
	    outfi << list[i].artist << ";";
	    outfi << list[i].genre << ";\n";
	}
	cout << endl << size << " tracks have been saved to the file. \n" << endl;
	outfi.close();
	system("PAUSE");
    }
    else
    {
	cout << "ERROR: cannot save to file!" << endl;
	system("PAUSE");
    }
    system("cls");
}
Last edited on
Pages: 12