Selection Sort for String

I wrote a code in order to sort a file of 20 names, I do not get any error but it does not show me the new order of names. I do not understand what I missed and I do not get the new order from the function showArray


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
#include <iostream> // preprocessor directive //
  #include <fstream>  // library for file (create/open/read)
  using namespace std;

  //swaps ints passed in by reference
  void swapper(string &x, string &y)
  {
      string temp;
      temp = x;
      x = y;
      y = temp;
  }
  // display the array of string with his new orders
  void showArray(string array[], int size)
  {
      for (int i = 0; i < size - 1; i++)
      {
          cout << "show " << array[i] << endl;
      }
  }

  //sorts array of length size using selection sort algorithm
  void selectionSort(string array[], int size)
  {
      int lowestPosition;
      string lowestValue;

      for (int i = 0; i < size - 1; i++)
      {
          //first, find position of lowest element in positions i through size-1
          lowestValue = array[i];
          lowestPosition = I;
          for (int j = i + 1; j < size; j++)
          {
              if (array[j] < lowestValue)
              {
                  lowestPosition = j;
                  lowestValue = array[j];
              }
          }
          //now, swap the lowest element we found with element at position I
          swapper(array[i], array[lowestPosition]);
      }
  }

  int main()
  {
      ifstream readFile;
      string names[20];

      readFile.open("names.txt");

      // check if file exist
      if (!readFile)
      {
          cout << "ERROR: Invalid filename\n";
          exit(1);
      }

      for (int i = 0; i < 19; i++)
      {
          while (readFile >> names[i])
          {
              cout << names[i] << endl;
          }
      }

      readFile.close();

      selectionSort(names, 20);
      showArray(names, 20);

      return 0;
  }
Last edited on
First: Be consistent with your numbers. You have a bunch of 19s and 20s thrown about.
In general, you should have some named constant like:
const int NumNames = 20;
and have for loops like:
1
2
3
4
for (int i = 0; i < NumNames; i++)
{

}


Second:
1
2
3
4
5
6
7
for (int i = 0; i < 19; i++)
{
    while (readFile >> names[i])
    {
        cout << names[i] << endl;
    }
}
This is overwriting names[0] 19 times. If you only have 19 names, it probably doesn't ever put any data into names[1] or beyond.

Assuming you have 20 words in your file, you can do something like:
1
2
3
4
5
6
7
8
const int NumNames = 20;
string names[NumNames];

// ...
for (int i = 0; i < NumNames && readFile >> names[i]; i++)
{
    cout << names[i] << '\n';
}
Last edited on
Hello siid14,


PLEASE ALWAYS USE CODE TAGS (the <> formatting button), to the right of this box, when posting code.

Along with the proper indenting it makes it easier to read your code and also easier to respond to your post.

http://www.cplusplus.com/articles/jEywvCM9/
http://www.cplusplus.com/articles/z13hAqkS/

Hint: You can edit your post, highlight your code and press the <> formatting button. This will not automatically indent your code. That part is up to you.

You can use the preview button at the bottom to see how it looks.

I found the second link to be the most help.


Evan if this would work:
1
2
3
4
5
6
7
for (int i = 0; i < 19; i++)
{
    while (readFile >> names[i])
    {
        cout << names[i] << endl;
    }
}

you would only read 19 names not 20.

Either use the for loop as Ganado has suggested or the while loop, but not both.

1
2
3
4
5
6
while (readFile >> names[i])
{
    cout << names[i] << endl;

    i++;
}


Also you are missing the header file "<string>".

If you define constexpr int MAXNAMES{ 20 }; at the beginning of the file you will not have to pass the size to the functions.

Something feels off with the "swapper" function, but I am not sure until I have a chance to run the program.

Since the program reads a file you should include this file contents in the original post or post it in a new reply. Your file may not be the same as my file and that could cause a problem.

Andy
Here the file Andy. I do not know if there is a special process for textfile so Imma just copy and paste what I have in my file. Here it is :

Samir
Amir
Manane
Harry
Haris
Hugo
Mickael
Kevin
Moustapha
Karl
Maxime
Hugo
Hadi
Malick
Akim
Rhagiv
Emeric
Gilles
Oswald
Axel

Also, I used the Ganado loop and it works perfectly. Thanks for that.
Hello siid14,

Another thing I noticed when working on the program. DO NOT use "exit()". This is a C function and causes an unconditional exit of the program. The problem is it does not know about classes and how to properly destroy the class before leaving tha program. it is better to use "return 1;" for a proper exit.

Once I fixed the read problem the rest of the program ran fine producing this output:

Enrique Thomas
Londyn White
Maverick Chan
Susan Dixon
Ariella Leonard
Zaniyah Shah
Jaylah Nielsen
Rolando Roy
Devyn Cobb
Eliezer Mcpherson
Rhianna Hall
Tamia Larsen
Hayden Lloyd
Bruce Vazquez
Micah Moreno
Taniyah Long
Keaton Weber
Braden Hebert
Juliette Bush
Jaylene Walker

show #01 Ariella Leonard
show #02 Braden Hebert
show #03 Bruce Vazquez
show #04 Devyn Cobb
show #05 Eliezer Mcpherson
show #06 Enrique Thomas
show #07 Hayden Lloyd
show #08 Jaylah Nielsen
show #09 Jaylene Walker
show #10 Juliette Bush
show #11 Keaton Weber
show #12 Londyn White
show #13 Maverick Chan
show #14 Micah Moreno
show #15 Rhianna Hall
show #16 Rolando Roy
show #17 Susan Dixon
show #18 Tamia Larsen
show #19 Taniyah Long

I noticed that the last name is missing in the sorted names. I believe the problem would be in the selection sort. I will have to look into that.

Andy
Hello siid14,

Tracked it down. The problem is not in the sort, it works fine.

The problem turned out to be in the "showArray" function. for (int i = 0; i < size - 1; i++). See the problem it only prints 19 out of 20.

I noticed your input file and will give ti a try.

Andy
Hello siid14,

Now that it is working this is what I did just for comparison:

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
#include <iostream> // preprocessor directive //
#include <fstream> // library for file (create/open/read)
#include <string>

using namespace std;

constexpr int MAXNAMES{ 20 };

//swaps ints passed in by reference
void swapper(string &x, string &y)
{
    string temp;

    temp = x;
    x = y;
    y = temp;
}

// display the array of string with his new orders
void showArray(string array[])
{
    std::cout << '\n';

    for (int i = 0; i < MAXNAMES; i++)
    {
        cout << "show #" << (i + 1 < 10 ? "0" : "") << i + 1 << " " << array[i] << endl;
    }
}

//sorts array of length size using selection sort algorithm
void selectionSort(string (&array)[MAXNAMES])
{
    int lowestPosition;
    string lowestValue;

    for (int i = 0; i < MAXNAMES - 1; i++)
    {
        //first, find position of lowest element in positions i through size-1
        lowestValue = array[i];
        lowestPosition = i;

        for (int j = i + 1; j < MAXNAMES; j++)
        {
            if (array[j] < lowestValue)
            {
                lowestPosition = j;
                lowestValue = array[j];
            }
        }

        //now, swap the lowest element we found with element at position I
        swapper(array[i], array[lowestPosition]);
    }
}

int main()
{
    int i{};
    string names[MAXNAMES];

    ifstream readFile("names.txt");

    // check if file exist
    if (!readFile)
    {
        cerr << "\n     ERROR: Invalid filename\n";

        //exit(1);  // <--- DO NOT use.
        return 1;
    }

    while (i < MAXNAMES && std::getline(readFile, names[i]))
    {
        cout << names[i] << endl;

        i++;
    }

    readFile.close();

    selectionSort(names);

    showArray(names);

    return 0;
}


Andy
Does your comparison code works perfectly when you run it, cause I got error when I do. Here it is :

fraudListA2.cpp:7:1: error: unknown type name 'constexpr'
constexpr int MAXNAMES{20};
^
fraudListA2.cpp:7:23: error: expected ';' after top level declarator
constexpr int MAXNAMES{20};
                      ^
                      ;
fraudListA2.cpp:58:10: error: expected ';' at end of declaration
    int i{};
         ^
         ;
3 errors generated.

You need to compile as C++11 or greater.
Hello siid14,

Like dutch said the minimum C++ standard that you should be using is the 2011 standards. The 2014 standards would be better and the 2017 standards is considered the normal minimum. This would be replaced by the 2020 standards in the future.

My IDE and compiler is set up to use the 2014 standards, but most of my code is more towards the 2011 standards.

If you can not update your IDE/compiler to at least the 2011 standards you can change "constexpr" to "const" and replace the uniform initializer, the {}s, with "= 0".

A good tip is to mention what IDE and or compiler you are using along with what operating system you are using.

Andy
Why not 'simply':

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

constexpr size_t MAXNAMES {20};

std::ostream& operator<<(std::ostream& os, const std::string array[])
{
	for (int i = 0; i < MAXNAMES; ++i)
		os << "#" << std::setw(2) << std::setfill('0') << i + 1 << ' ' << array[i] << '\n';

	return os << '\n';
}

int main()
{
	std::ifstream readFile("names.txt");

	if (!readFile)
		return (std::cerr << "\nERROR: Invalid filename\n"), 1;

	std::string names[MAXNAMES];

	for (size_t i {}; i < MAXNAMES && std::getline(readFile, names[i]); ++i);
	std::sort(names, names + MAXNAMES);
	std::cout << names;
}


Or even use a vector?

Using a custom sort (selection sort for example) or even the old sort from C you have control over the outcome.
(Eg with strings you can code for case independence in the comparison stage, {the callback function in the C sort for example})

Here is the oldest sort built into windows, DOS originally.
This sort is mainly for filenames in a folder, but is adaptable, thus is case independent.
I have recreated the original file names.text as names2.txt.
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
#include<iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <direct.h>
#include <iomanip>   
#define GetCurrentDir _getcwd

using namespace std;
enum {up,down};
std::ifstream::pos_type filesize(const char* filename)
{
    std::ifstream in(filename, std::ifstream::ate | std::ifstream::binary);
    return in.tellg(); 
}

template <typename S>
void save(const char * filename,S array)
{
    FILE * f = fopen(filename, "wb");
    int size= array.size()*sizeof(array[0]);
   auto ap = &array[0];
    fwrite(ap,size,1,f) ;
    fclose(f);
}

template <typename L>
 void load(const char * filename,L  &array)
{
	int s=filesize(filename)/sizeof(array[0]);
	array.resize(s);
	FILE * f = fopen(filename, "rb");
	auto ap = &array[0];
	fread(ap,array.size()*sizeof(array[0]),1,f); 
   fclose(f);
}

void dossort(string filename,int direction,string fileout="_out_.txt")
{
	string cmd;
	char CurrentPath[1024];
	GetCurrentDir(CurrentPath, sizeof(CurrentPath));
	string cd=CurrentPath;
	if (direction==down)
        cmd = "SORT/r " +cd + "\\"+ filename + " /o " + cd +"\\"+fileout ;
    else
        cmd = "SORT "  + cd + "\\"+ filename + " /o " + cd +"\\"+fileout ;
   system(cmd.c_str()); 
}

int main()
{
char * filein= (char *)"names2.txt";
char * fileout=(char *)"_out_.txt";
string s =
"Samir\nAmir\nManane\nHarry\nHaris\nHugo\nMickael\nKevin\nMoustapha\nKarl\nmaxime\nHugo\nHadi\nMalick\nAkim\nRhagiv\nEmeric\nGilles\nOswald\naxel";
cout<<"original file:"<<endl;
cout<<s<<endl<<endl;
save(filein,s);

	string resultup,resultdown;
	dossort(filein,up,fileout);
	load(fileout,resultup);
	dossort(filein,down,fileout);
	load(fileout,resultdown);
	cout<<"sorted file:"<<endl;
	cout<<" up:"<<setw(15)<<" down:"<<endl;
	istringstream RU( resultup );
	istringstream RD( resultdown );
	string tu,td;
	while ( RU>>tu && RD>>td)
	 {
	 	cout<<left<<setw(15)<<tu<<setw(10)<<td<<endl;
     }
	
	cout <<"Press return to delete the text file "<<filein<<" and "<<fileout<<endl; 
    cin.get();	
	
	 if( remove( filein ) != 0  ||  remove( fileout ) != 0 )
     cout<<"Error deleting files, please complete the task manually"<<endl;
     else
     {
     cout<<endl;
     cout<< "Files successfully deleted"<<endl;
     }
  
cout <<"  "<<endl;
cout <<"Press return to end . . ."<<endl; 
cin.get();	  	
  
} 


Tested g++ 64 bits on win 10.
Topic archived. No new replies allowed.