My program keeps crashing!

So our objective here is this:

Requirements.

Write a program named nameSorter.cpp, to read names in a text file, sort them alphabetically, and print them to the screen. Here are some detailed specifications:

The names are to be stored in a text file, one name per line. Prompt the user to enter the filename via the keyboard (ref. section 5.2.3).

Skip any blank lines (ref. section 3.3.3 for string length). Skip any exact duplicates (ref. section 6.1 for text comparison, and 12.1.2's "Two Boolean Search Loops For A List"). Allow up to 8 names (ref. section 12.1).

Stop reading the file after the end-of-file is reached (ref. section 7.3.2), or the 8th name is read (ref. section 7.4).

Sort the names alphabetically, from A to Z (ref. section 10.2.3), however they appear in the file. For example, "Abraham" comes before "George". Or if the names are in the format first-last, "Abraham Lincoln" comes before "George Washington". Or if the names are in the format last-name-first, "Jefferson, Thomas" comes before "Madison, James". (In fact, the text does not even need to be names!)

The sorting and checking for duplicates should both be case-independent (ref. section 6.4.1). But do not permanently convert the name case -- compare lowercase (or uppercase) versions of the text for sorting purposes. (You may want to use temporary variables so store the converted text.)
Write your own input file for testing purposes. Do not submit your input file.

Be sure to use the code from chapter 12 for adding values to a list, and not the code from chapter 10. This means that the size counter should start a zero, and be incremented by one every time a value gets added. The purpose is to show the difference between arrays and lists.

Scoring. The lab will be returned for redo if you do not apply array-based list concepts. The lab will be returned for redo for using a capacity other than 8. The lab will be returned for redo for not checking for duplicates, or for not doing a case-independent check for duplicates. The lab will be returned for redo for permanently converting the case of input values, not skipping blank lines in the input file, or not doing a case-independent sort.

So I completed the assignment as so:

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

using namespace std;

#include <cctype>

class toUpper {public: char operator()(char c) const {return toupper(c);}};

int main()
{
  cout << "Editor(s) used: XP Notepad" << endl; 
  cout << "Compiler(s) used: VC++ 2010 Express" << endl;
  cout << "Description: This program alphabetically sorts the first 8 names" << endl;
  cout << " from a user-specific text file." <<endl;
  cout << endl;


  
  string filename;
  string line;
  string nameX;
  string nameY;
  string swap;

  int count = 0;
  bool nameTaken = false;

  ifstream fin;

  const int MAX_NAMES = 8;
  int SIZE = 0;
  string name[MAX_NAMES];

  while (1)
  { 
    cout << "Enter filename: ";
    getline(cin, filename);
   
    if (filename.length() > 0) break;
    cout << "Enter filename: " << endl;
  }

  cout << endl;

  // open and read input file
  fin.open(filename.c_str());
  if (!fin.good()) throw "I/O error";

  while (fin.good() && SIZE < 10)
  {
    getline(fin, line);
  
    if (line.length() == 0) continue;

    nameTaken = false;
    for (int i = 0; i < SIZE; i++)
      if (name[i] == line) 
        nameTaken = true;

  if (!nameTaken && SIZE < MAX_NAMES)
    {
      name[SIZE++] = line;
    }
  }

  // sort names
  for (int i = 0; i < SIZE; i++)
  {
    for (int j = 0; j < SIZE; j++)
    {
      nameX = name[i];
      nameY = name[j];

      transform(nameX.begin(), nameX.end(), nameX.begin(), toUpper());
      transform(nameY.begin(), nameY.end(), nameY.begin(), toUpper());

      if (nameX < nameY)
      {
        swap = name[i];
        name[i] = name[j];
        name[j] = swap;
      }
    }
  }

  for (int i = 0; i < SIZE; i++)
    cout << name[i] << endl;

  return 0;
}


I got this for feedback:

"LAb12d: your program must skip any exact duplicates. Note, the checking for duplicates should be case-independent (ref. section 6.4.1).(-2) Pls fix and resubmit."

Okay, so I wrote this (it compiles, but crashes when you load the input txt file:

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

using namespace std;

#include <cctype>

class toUpper {public: char operator()(char c) const {return toupper(c);}};

int main()
{
  cout << "Editor(s) used: XP Notepad" << endl; 
  cout << "Compiler(s) used: VC++ 2010 Express" << endl;
  cout << "Description: This program alphabetically sorts the first 8 names" << endl;
  cout << " from a user-specific text file." <<endl;
  cout << endl;


  
  string filename;
  string line;
  string nameX;
  string nameY;
  string swap;

  int count = 0;
  bool nameTaken = false;

  ifstream fin;

  const int MAX_NAMES = 8;
  int SIZE = 0;
  string name[MAX_NAMES];
  string nameCopyA;
  string nameCopyB;

  while (true)
  { 
    cout << "Enter filename: ";
    getline(cin, filename);
   
    if (filename.length() > 0) break;
    cout << "Enter filename: " << endl;
  }

  cout << endl;

  // open and read input file
  fin.open(filename.c_str());
  if (!fin.good()) throw "I/O error";

  while (fin.good() && SIZE < 10)
  {
    getline(fin, line);
  
    if (line.length() == 0) continue;
    
    nameCopyA = line; 

      transform(nameCopyA.begin(), nameCopyA.end(), nameCopyA.begin(), toUpper());
      
    nameTaken = false;
    for (int i = 0; i < SIZE; i++)

      nameCopyB = name[SIZE];
        
        transform(nameCopyB.begin(), nameCopyB.end(), nameCopyB.begin(), toUpper());

      if (nameCopyA == nameCopyB) 
        nameTaken = true;

  if (!nameTaken && SIZE < MAX_NAMES)
    {
      name[SIZE++] = line;
    }
  }

  // sort names
  for (int i = 0; i < SIZE; i++)
  {
    for (int j = 0; j < SIZE; j++)
    {
      nameX = name[i];
      nameY = name[j];

      transform(nameX.begin(), nameX.end(), nameX.begin(), toUpper());
      transform(nameY.begin(), nameY.end(), nameY.begin(), toUpper());

      if (nameX < nameY)
      {
        swap = name[i];
        name[i] = name[j];
        name[j] = swap;
      }
    }
  }

  for (int i = 0; i < SIZE; i++)
    cout << name[i] << endl;

  return 0;
}


The txt file is simple. Call it test.txt. Here is the contents of test:

George Washington

John Adams

Thomas Jefferson

james Madison
James Madison

James Monroe

john Quincy Adams

Andrew Jackson

Martin Van Buren

William Harrison

John Tyler

James Polk

Zachary Taylor

Millard Fillmore

Franklin Pierce

James Buchanan

Abraham Lincoln

Andrew Johnson

Ulysses Grant


It should skip the duplicated entry for James Madison given the case sensitivity, and only print the first eight. I know this is a long post, but I'm not asking anyone to do my homework for me, just looking for help on debugging what I have already spent my time on. What gives???
Last edited on
Any ideas?
What are you trying to do here?:

1
2
3
4
5

 for (int i = 0; i < SIZE; i++)

      nameCopyB = name[SIZE];


1, name[SIZE] can be an invalid address
2, Why would you want to copyname[ SIZE ] to nameCopyB SIZE times?

Please post your code using the code tags (under Format)
Last edited on
nameCopyB = name[SIZE];

This crashes when SIZE is 8, as this is an attempt to access the ninth object in the array, but that object does not exist.

If you learned how to use a debugger, you would have found this yourself in thirty seconds.
Last edited on
@kooth: I wanted to create a copy of the lines already read and stored in name so that they can be compared with another copy of the lines being currently read. That way I can transform both copies to account for case sensitivity. What part of my code wasn't formatted, I thought it all was!

So anyway, how would I fix this?
Would this work?

nameCopyB = name[i];

The computer I am on doesn't have a compiler, so I'll have to try this out a bit later after class.
I think what moschops is referring to is line 75 - 79 of your code. Look at that REALLY closely and if you still cant get it then I'll help a bit more. If you don't know how to step through your code start replacing the variables with numbers and go through that for loop.
Also, I noticed that your throw statement is meaningless. Read up on try/catch statements and on good modularization and cohesion. Programming is fun, isn't it.
Sorry Chirrs: My bad! I was looking at too many things yesterday, and I got confused as to which post I was trying to answer.

To answer your question about:

nameCopyB = name[ i ];

Yes, that will stop your program from blowing up, but Moschops has good advice (as always): Learn to use your debugger.

Perhaps you meant to put all of that code as part of the "if" statement on line 66? That would make more sense to me:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

for (int i = 0; i < SIZE; i++)
    {
     nameCopyB = name[ i ];
        
    transform( nameCopyB.begin(), nameCopyB.end(),
        nameCopyB.begin(), toUpper() );

    if( nameCopyA == nameCopyB ) 
        {
        nameTaken = true;

        break;

        }    /*    if( nameCopyA ==  nameCopyB )    */

    }    /*    for( i < SIZE )    */


Topic archived. No new replies allowed.