Quick fix help, duplicate words and a few things

Hello,

Could you please help me in fixing the following issues.


Out putting only unique words after there sorted(No Duplicates).

Showing the correct average length from the words in the file.

finding the shortest unique words.

My data file will have.


barry TroY JoE
jiLL
KaTe ABE HILDEGARDE TrOy
zoe


my incorrect output.


enter name of input file
test004

# unique names:  8
average lenght of a name:  5.000

Longest  names:  Hildegarde

Shortest  names:  Joe

Alphabetized Name List 

 Abe
 Barry
 Hildegarde
 Jill
 Joe
 Kate
 Troy
 Troy
 Zoe


The Correct Needed output.

# unique names: 8
average lengh of a name: 4.500

Lenght of longest name(s) is 10
Longest name(s)
Hildegarde

Lenght of shortest name(s) is 3
shortest name(s)
Joe
Abe
Zoe

Alphabetized Name List
Abe
Barry
Hildegarde
Jill
Joe
Kate
Troy
Zoe


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
#include <iostream>
#include <fstream>
#include <string>
#include <cctype>
#include <iomanip>
using namespace std;

const int MAX = 30;

void fixstring(string&);
void get_data(string[], int&);
void bubblesort(string[], int&);

int main()

{
  int n=0;  // <--- Good practice to initialize all your variables.                                      
  int count=0;
  string names[MAX];

  get_data(names, n);
  count = n;  // <--- Defined "count", but never gave it a value before it is used in thee next line.    
  bubblesort(names, count);

  //  Added this to print the sorted names. Keep or not it is up to you, but helps with testing.         
  for (size_t lc = 0; lc < count; lc++)
    {
      /* for (int i = 1; i < count; i++)// I was thinking this would look at each sotered word and remov\
e duplicates                                                                                             
        {                                                                                                
                                                                                                         
          bool matching = false;                                                                         
          for (int j = 0; (j < i) && (matching == false); j++)                                           
            if (names[i] == names[j]) matching = true;                                                   
          if (!matching)  cout << "\n " << names[lc];                                                    
          }*/
      cout << "\n " << names[lc];
    }

  return 0;
}
void get_data(string names[], int& n)

{
  ifstream fin;
  string fnames;
  double  namecount=0;

  //  Moved these lines up to here for when needed.                                                      
  cout<< endl<< "enter name of input file" << endl;
   cin >> fnames;
   fin.open(fnames.c_str());

  //  Always good practice and programming to make sure the input file is open.                          
  if (!fin.is_open())  //<--- Added.                                                                     
    {
      cout << "\n File " << fnames << " did not open" <<endl;
    }

  n = 0;

  while (fin>>names[n])  // <--- Changed. This is where the read should go to.                           
    {
      fixstring(names[n]);
      n++;

    }

  for (int i = 0; i < n; i++)
    {

      bool matching = false;
      for (int j = 0; (j < i) && (matching == false); j++)
        if (names[i] == names[j]) matching = true;
      if (!matching) namecount++;
    }


  cout << endl << "# unique names:  " << namecount << endl;

  double  lettercount = 0;
 for (int k = 0; k <  n; k++)
    {
      string word;
      word=names[k];
      int num = word.size();
      for (int l = 0; l<num; l++)
        lettercount++;
    }

  cout << "average lenght of a name:  " <<fixed << setprecision(3) << lettercount / namecount << endl;


  string Result;

  for (int m = 0; m <  n; m++)
    {
      if (names[m].size()>Result.size())
        Result = names[m];
    }
  cout  << endl << "Longest  names:  " << Result  << endl;

  string result= Result;

  for (int x = 0; x <  n; x++)
    {
      if (names[x].size()<result.size())
        result = names[x];
    }

  cout  << endl << "Shortest  names:  " << result  << endl;

}
//  These next threee functions work.                                                                    
void fixstring(string& word)
{
  int num = word.size();
  int lenght = word.size();
  word[0] = toupper(word[0]);
  for (int i = 1; i<num; i++)
    word[i] = tolower(word[i]);
}
void bubblesort(string names[], int& count)
{
  string temp; //place holder when values are interchanged                                               
  for (int i = 0; i < count - 1; i++)
    for (int j = 0; j < count - (i + 1); j++)
      if (names[j] > names[j + 1]) // <--- Changed to >.                                                 
        {
          temp = names[j];
          names[j] = names[j + 1];
          names[j + 1] = temp;
        }
  cout<< endl   << "Alphabetized Name List " << endl;

}
code]
Last edited on
Use a std::set<string>

This will miraculously:
(a) ensure uniqueness;
(b) sort them for you.
That would be too easy and I would loose points. Unless you could show me how to only add this function to the for (size_t lc = 0; lc < count; lc++) only which prints out the sorted list?

Or how to add that in the beginning of my get data?
Last edited on
If you already have a sorted array then to flag duplicates you only have to compare each element with its neighbour.

There are many ways, but one using ordinary arrays would be:

- create a new array with size MAX;
- copy the first element of your sorted array into the new array;
- go through the sorted array from second to last; if you are equal to the previous element then do nothing; if not equal then copy this element to the next available slot in the new array.


I'd much rather do the whole thing with std::set<string> though.

That would be too easy and I would loose points.
I'm fascinated by the logic here!
Last edited on
Agreed that the set<string> would save a lot of time and headache, but i need the points to pass the class.

I went to my bubble sort function and added the for loop that would find duplicates. But im thinking the placement is in the wrong spot since it didnt perform what i needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void bubblesort(string names[], int& count)
{
  string temp; //place holder when values are interchanged                                               
  for (int i = 0; i < count - 1; i++)
    for (int j = 0; j < count - (i + 1); j++)
      if (names[j] > names[j + 1]) // <--- Changed to >.                                                 
        {
          temp = names[j];
          names[j] = names[j + 1];
          names[j + 1] = temp;
        }
  for (int z = 0; z < count; z++) // this would go thru and find duplicates????
    {

      bool matching = false;
      for (int x = 0; (x < z) && (matching == false); x++)
        if (names[z] == names[x]) matching = true;
      if (!matching) names[z];
    }

  cout<< endl   << "Alphabetized Name List " << endl;

}
@sr2cute702
If you are using normal arrays I think you would be much better sorting first, then removing duplicates afterwards (by copying non-duplicates as you find them into a separate array). I gave a possible algorithm for this, but you've chosen to ignore it and just rearrange your existing code instead.
I due want to thank you for your help, i did get the duplicates removed from the final sorted list.

could you help me with finding the biggest name and smallest name?

here is the initial set up that did work but only showed one name. how do i get this to show me all the smallest names and all of the biggest names if there are multiple matching sizes?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
  string Result;

  for (int m = 0; m <  n; m++)
    {
      if (names[m].size()>Result.size())
        Result = names[m];
    }
  cout  << endl << "Longest  names:  " << Result  << endl;

  string result= Result;

  for (int x = 0; x <  n; x++)
    {
      if (names[x].size()<result.size())
        result = names[x];
    }

  cout  << endl << "Shortest  names:  " << result  << endl;
Last edited on
For the longest name, go through the array TWICE. The first time should find the longest length (here 10). The second pass should print out any names with that length.

Do the same for the shortest. (You can conveniently find the length that is shortest in the same loop that you find the longest.)

When you have finished, go back and do the lot with std::set<string> ... just for fun.
Last edited on
Registered users can post here. Sign in or register to post.