Baby names assignment using structs strings and files

Pages: 1234
kemort,

I keep running into errors like these:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 template argument deduction/substitution failed:
..\nameApp1.cpp:240:31: note:   mismatched types 'const _CharT*' and 'Name'
   if (aList[j] < aList[pos_min])
                               ^
..\nameApp1.cpp:248:23: error: cannot convert 'Name' to 'int' in assignment
                  temp = aList[i];
                       ^
..\nameApp1.cpp:250:33: error: no match for 'operator=' (operand types are 'Name' and 'int')
                  aList[pos_min] = temp;
                                 ^
..\nameApp1.cpp:17:8: note: candidate: Name& Name::operator=(const Name&)
 struct Name{
        ^
..\nameApp1.cpp:17:8: note:   no known conversion for argument 1 from 'int' to 'const Name&'



This is what I 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
48
49
50
51
52
53
54
55
56
57
void doMenu(Name aList[],  int actual_no,int index)
{

		bool again = true;
		do
		{

			cout << "\ta - Print histogram for a name\n";
			cout << "\tb - Compare two names in a decade\n";
			cout << "\tc - Print top ten names for a decade\n";
			cout << "\td - Quit(write anomalies)\n";

			char userChoice = ' ';
			cout << "\n\tYour selection : ";
			cin >> userChoice;
			cin.get();

			switch (userChoice)
			{
			case 'a':
				displayPersonHistogram(aList, actual_no,index);
				again = true;
				break;
			case 'b':
			  {
			                int index_1 = findName(aList, actual_no);
			                cout << "Name 1: " << aList[index_1].name << " found\n";

			                int index_2 = findName(aList, actual_no);
			                cout << "Name 2: " << aList[index_2].name << " found\n";

			                int decade = getDecadeNo();
			                displayDecade(decade);

			                displayPersonBar(aList, actual_no, index_1, decade);
			                displayPersonBar(aList, actual_no, index_2, decade);



				again=true;
				break;
			  }

			case 'c':
				selectSort(aList, aSize);
				again = true;
				break;
			case 'd':
				// do d stuff
				again = false;
				break;
			default:
				cout << "Wrong choice of character. Must be a, b, c or d\n";
				break;
			}
		} while (again);
	}
Last edited on
hello Dmtg93,
I have not tested your code but your sort function is for sorting an integer array.
Try this. Maybe our elders here can correct you(and me).
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
void selectSort(Name aList[], int aSize)
{
	char left[NAME_LEN];
	char right[NAME_LEN];

	int pos_min;

	for (int i = 0; i < aSize - 1; i++)
	{
		pos_min = i;

		for (int j = i + 1; j < aSize; j++)
		{
			strcpy(right, aList[i].name); // get the name to the right
			convertToUpperCase(right); // convert to upper case

			strcpy(left, aList[pos_min].name); // get the name to the left
			convertToUpperCase(left);		// convert to uppper case

			if (right < left) { // compare both left and right names
				pos_min = j;  // if left <right, let i and j swap places
			}
		}

		if (pos_min != i)
		{
			strcpy(right, aList[i].name); // get the name to the right
			convertToUpperCase(right); // convert to upper case

			strcpy(left, aList[pos_min].name); // get the name to the left
			convertToUpperCase(left);		// convert to uppper case

			swap(right, left);  // swap is a library function. It will swap the places
                        // test of swap  http://cpp.sh/2oqz
                       
                  }
	}
}


NB: I have not tested this if it works but it feels logical
Last edited on
Thanks blongho, I'll test it and see what happens.
A small code snippet to display the decades as your sample code here
http://www.cplusplus.com/forum/beginner/218976/2/#msg1009582

1
2
3
4
5
6
7
8
9
10
11
12
13
14
void showDecades()
{
	int lowerLimit = 1900;
	int decadeInterval = 9;
	cout << endl;

	for (int i = 0; i < 11; lowerLimit += 10)
	{
		if (i == 10) decadeInterval = 5; // change delta to 5 to so that we have 2005 instead of 2009
		
		cout << setw(5) << right << ++i << " - " << lowerLimit << "-" << lowerLimit + decadeInterval  << endl;
	}
	cout << endl;
}
This is what I have updated and testing right now..I dont understand what im doing 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
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
const int SIZE = 5000;
const int NAME_LEN = 21;
const int NUM_RANKS = 11;

struct Name{
    char name[NAME_LEN];
    int rank[NUM_RANKS];
};

int loadNames(Name [], int);
void displayOneHistogramBar(int);
void displayPersonHistogram(Name [], int, int);
void displayPersonBar(Name [], int, int, int);
void displayNames(Name [], int);
void selectSort(Name[], int );
int findName(Name [], int);
void convertToUpperCase(char []);
void doMenu(Name [], int,int );
void displayAllHistograms(Name [], int);
void displayDecade(int);
int getDecadeNo();

int main()
{
	int number_of_names = 0;
		Name list[SIZE];
		number_of_names = loadNames(list, SIZE);

		displayNames(list, number_of_names);
		displayAllHistograms(list, number_of_names);


		int found_index = findName(list, number_of_names);
		if (found_index != -1)
			displayPersonHistogram(list, number_of_names, found_index);
		else
			cout << "Name not found\n";




		return 0;
}


int loadNames( Name aList[], int aSize )
{
    ifstream nameList;
    nameList.open("names.txt");

    int count = 0;

    if(nameList.is_open())
    {
        while(nameList >> aList[count].name )
        {
            for(int i = 0; i < NUM_RANKS; ++i)
            {
                nameList >> aList[count].rank[i];
            }
            ++count;
        }
        nameList.close();
    }
    else
        cout << "Unable to open file\n";

    return count;
}


void displayAllHistograms(Name aList[], int actual_number_names) {
	for (int i = 0; i < actual_number_names; ++i) {
		cout << "Histogram for name, " << aList[i].name << '\n';
		displayPersonHistogram(aList, actual_number_names, i);
	}
}


void displayOneHistogramBar(int aRankValue)
{
    char bar[200]={0};
    int no_stars = 0;

    if(aRankValue > 0)
    {
        no_stars = (1000 - aRankValue) / 10 + 1;

        for(int i = 0; i < no_stars; ++i)
            bar[i] = '*';
    }
    cout << setw(4) << aRankValue << ": " << bar << '\n';
}

void displayPersonHistogram( Name aList[], int actual_no, int index)
{
    for(int i = 0; i < NUM_RANKS; ++i)
    {
        displayOneHistogramBar(aList[index].rank[i]);
    }
}

void displayPersonBar(Name aList[], int actual_no, int index, int aDecade)
{
    int rank_no = aDecade - 1;
    cout << setw(8) << aList[index].name;
    displayOneHistogramBar(aList[index].rank[rank_no]);
}

int findName(Name aList[], int actual_no)
{
    char search_name[NAME_LEN];
    char list_name[NAME_LEN];

    int index = -1;

    while( index == -1)
    {
        cout << "Please enter a name: ";
        cin >> search_name;
        convertToUpperCase(search_name);

        for(int i = 0; i < actual_no; ++i)
        {
            strcpy(list_name,aList[i].name);
            convertToUpperCase(list_name);

            if(!strcmp(search_name, list_name))
            {
                index = i;
                return index;
            }
        }
    }
    return index;
}


void displayNames( Name list[], int actual_number_names)
{
    for(int i = 0; i < actual_number_names; ++i)
    {
        cout << list[i].name << '\n';
        for(int j = 0; j < NUM_RANKS; ++j)
        {
            cout << list[i].rank[j] << ' ';
        }
        std::cout << '\n';
    }
}

void convertToUpperCase(char aName[])
{
    for(int i = 0; i < strlen(aName); i++)
        aName[i] = toupper(aName[i]);
}

void displayDecade(int aDecade)
{
    int delta = 0;
    int start = 1900 + (aDecade - 1) * 10;

    if(aDecade == 11)
        delta = 5;
    else
        delta = 9;

    cout
    << "Decade " << aDecade << ": " << start << '-' << start + delta << '\n';
}


int getDecadeNo()
{
    int decade = 1;
    while(
          cout << "Enter decade: "
          && cin >> decade
          && (decade < 1 or decade > 11)
          )
    {
        cout << "Invalid decade\n";
    }
    return decade;
}


void selectSort(Name aList[], int actual_no)
{
					char left[NAME_LEN];
					char right[NAME_LEN];

					int pos_min;

					for (int i = 0; i < actual_no - 1; i++)
					{
						pos_min = i;

						for (int j = i + 1; j < actual_no; j++)
						{
							strcpy(right, aList[i].name); // get the name to the right
							convertToUpperCase(right); // convert to upper case

							strcpy(left, aList[pos_min].name); // get the name to the left
							convertToUpperCase(left);		// convert to uppper case

							if (right < left) { // compare both left and right names
								pos_min = j;  // if left <right, let i and j swap places
							}
						}

						if (pos_min != i)
						{
							strcpy(right, aList[i].name); // get the name to the right
							convertToUpperCase(right); // convert to upper case

							strcpy(left, aList[pos_min].name); // get the name to the left
							convertToUpperCase(left);		// convert to uppper case

							swap(right, left);  // swap is a library function. It will swap the places
						}
					}
				}

void doMenu(Name aList[],  int actual_no,int index)
{

		bool again = true;
		do
		{

			cout << "\ta - Print histogram for a name\n";
			cout << "\tb - Compare two names in a decade\n";
			cout << "\tc - Print top ten names for a decade\n";
			cout << "\td - Quit(write anomalies)\n";

			char userChoice = ' ';
			cout << "\n\tYour selection : ";
			cin >> userChoice;
			cin.get();

			switch (userChoice)
			{
			case 'a':
				displayPersonHistogram(aList, actual_no,index);
				again = true;
				break;
			case 'b':
			  {
			                int index_1 = findName(aList, actual_no);
			                cout << "Name 1: " << aList[index_1].name << " found\n";

			                int index_2 = findName(aList, actual_no);
			                cout << "Name 2: " << aList[index_2].name << " found\n";

			                int decade = getDecadeNo();
			                displayDecade(decade);

			                displayPersonBar(aList, actual_no, index_1, decade);
			                displayPersonBar(aList, actual_no, index_2, decade);



				again=true;
				break;
			  }

			case 'c':
				selectSort(aList, actual_no);
				again = true;
				break;
			case 'd':
				// do d stuff
				again = false;
				break;
			default:
				cout << "Wrong choice of character. Must be a, b, c or d\n";
				break;
			}
		} while (again);
	}
Last edited on
This is what c is supposed to look like:
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
    Select a menu option:
       a - Print histogram for a name
       b - Compare two names in a decade
       c - Print top ten names for a decade
       d - Quit (write anomalies)
    Your selection: c
    
    Enter number corresponding to your decade:
        1 - 1900-1909
        2 - 1910-1919
        3 - 1920-1929
        4 - 1930-1939
        5 - 1940-1949
        6 - 1950-1959
        7 - 1960-1969
        8 - 1970-1979
        9 - 1980-1989
       10 - 1990-1999
       11 - 2000-2005
    Enter a decade: 10
    
    Ten most popular names (male and female) during the decade 1990-1999 were:
             Ashley (1)        Michael (1)
        Christopher (2)        Jessica (2)
              Emily (3)        Matthew (3)
             Joshua (4)          Sarah (4)
              Jacob (5)       Samantha (5)
             Andrew (6)       Brittany (6)
             Amanda (7)         Daniel (7)
          Elizabeth (8)       Nicholas (8)
             Taylor (9)          Tyler (9)
             Joseph(10)          Megan(10)
closed account (48T7M4Gy)
I keep running into errors like these:
Without seeing your code it is difficult to diagnose the problem except to say CharT has no relevance char does so maybe you have a typo somewhere.

As far as the menu, part b and part c are concerned you need to test and retest separate parts of the functionality you are working on. It's a waste of time if you don't isolate the parts you are working on.

For instance, get the sorting to work as a simple and separate small test program. Setup an array of integers and sort them using your new function. You have enough information to do that easily.

You then have to organise how to interrogate the array of names to sort so you give your sort function the right information to work on, here in the form of an integer array, which you already have.

Map it out with pseudocode first:

1. select the decade, d
2. for each Name object, i
sort on object[i].rank[d]
3. printout top 10 from sorted array list


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

using namespace std;

void display(int [], int);
void sort(int [], int);

int main()
{
    int list[]{4,3,9,5,8,6,7,1,2,0};
    int list_size = sizeof(list)/sizeof(int);
    
    display(list, list_size);
    sort(list, list_size);
    display(list,list_size);
    
    return 0;
}

void sort(int array[], int array_size)
{
    int temp = 0;
    
    for(int j = 0; j < array_size; j++)
    {
        for(int i = 0; i < array_size-j; i++)
        {
            if( array[i] > array[array_size-1-j])
            {
                temp = array[array_size-1-j];
                array[array_size-1-j] = array[i];
                array[i] = temp;
            }
        }
    }
}

void display(int array[], int array_size)
{
    for(int i = 0; i < array_size; i++)
    {
        cout << array[i] << ' ';
    }
    cout << '\n';
}


4 3 9 5 8 6 7 1 2 0 
0 1 2 3 4 5 6 7 8 9 
Program ended with exit code: 0
Last edited on
Kemort,
Thank you. I guess I'm just struggling with how to put it all together. I'll use the code blongho provided and see if i can get anywhere.
closed account (48T7M4Gy)
@Dmtg93 That's OK. Best thing to do is try out your ideas and test the functions and the way they work towards the end result.
So for using strings do i have to list all 4429 names into an array like that? Or can I use aList[] somehow?
closed account (48T7M4Gy)
You use aList and the fact that each Name is a srtruct which contains a list of ranks.
Would void selectSort(Name aList[], int actual_no) be on the right track? Or would name_len be the size of the array? I just think actual_no needs to be replaced with something else and cant figure out what it is.

closed account (48T7M4Gy)
If it is something else, then what is it? How many Names are you sorting?
Well Im not sure..I think I would be sorting however many names are in the Names array. But then that needs to break down to the rank from each decade. Like name.decade.
closed account (48T7M4Gy)
You're sorting on a particular decade, for all Names on the original source .txt file.

You need to adapt the sorting function above to the particular case here.
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
void sort(string aList[], int actual_no)
{
    int temp = 0;

    for(int j = 0; j < actual_no; j++)
    {
        for(int i = 0; i < actual_no-j; i++)
        {
            if( aList[i] > aList[actual_no-1-j])
            {
                temp = aList[actual_no-1-j];
                aList[actual_no-1-j] = aList[i];
                aList[i] = temp;
            }
        }
    }
}

void display(string aList[], int actual_no)
{
    for(int i = 0; i < actual_no; i++)
    {
        cout << aList[i] << ' ';
    }
    cout << '\n';
}


I am getting this error
1
2
error: cannot convert 'std::__cxx11::string {aka std::__cxx11::basic_string<char>}' to 'int' in assignment
                 temp = aList[actual_no-1-j];
in line 11
Last edited on
closed account (48T7M4Gy)
The error is because you are incorrectly sorting on a whole Name object instead of the rank value.
ie you should be sorting on aList[x].rank[y] where y is the selected decade.
1
2
3
4
     temp = aList[i].rank[j][actual_no-1-j];
                aList[actual_no-1-j] = aList[i];
                aList[i] = temp;
            }

If I change it to this it's now saying there is no member named rank. If I change string aList[] to Name aList[] I get more errors..

EDIT:

What about this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
void sort(Name aList[], int actual_no)
{
    bool swapped=false;

    do
    {
    	swapped=false;
    	for (int i=0;i<(actual_no-1); i++)
    	{
    		if(aList[i].rank>aList[i+1].rank)
    		{
    			swap(aList[i],aList[i+1]);
    		swapped=true;
    		}
    	}


    } while (swapped);



}
Last edited on
I cant get it to work..I'm sorry. I'm just confusing myself at this point
Last edited on
closed account (48T7M4Gy)
temp = aList[i].rank[j][actual_no-1-j] doesn't mean anything. And the same goes for aList[i].rank, rank is an array of ranks so it should be rank[selected_decade].

You have to swap the two Name objects based on their rank value. Best you revisit the general selection sort I gave you above and adapt that. The swap is not between i and i+1.
Pages: 1234