Need C++ Help. I'm trying to sort a string array by ignoring the case.

mulder

Senior member
Oct 9, 1999
684
0
76
I don't want anyone to come right out and write it for me. I need the experience on learning to do it for myself. With that said I need some help getting started.

Basically I have an string array with 10 elements in it. Each element is a word that has different letters in upper or lower case. I can sort the list using the selection sort algorithm, but it takes into consieration the case of the letters and puts the words with upper case over the words that start with lower case and so on. I know why it does this -- because in the ASCII chart upper case comes before lower case. However, I need to change the sort to ingnore the case and sort it again from there, but at the same time not changing the original word.

For example...Say my list has {Free, aPPle, Bird, caRd, AirPlane}. The first sort would look like:

AirPlane
Bird
Free
aPPle
caRd


Now I want it to do:

AirPlane
aPPle
Bird
caRd
Free

Make sense? I remember reading about some functions -- isupper/islower or toupper/tolower. Do those need to come into play? If someone could point me in the right direction as far as getting an idea of what to do, then I can probably write the code. Thanks for your help. I'll check back later.
 

fow99

Senior member
Aug 16, 2000
510
0
0
I think you can use 'toupper' to convert the character you are gonna compare and then do the comparision itself.
 

mulder

Senior member
Oct 9, 1999
684
0
76
Ok, I thought I might. However, if I use toupper to convert it will it change the case permanently(sp?) or just for the comparison? Because if I have a word such as bIRd I don't want it to change to BIRD in the original array. Will that happen? Thanks for the reply.
 

fow99

Senior member
Aug 16, 2000
510
0
0
No. It won't do anything to your oringinal string.
You see 'toupper' is a function which take your character as input and give the uppered one as output which would be used in comparison. Note that the output is actually made up by your compiler.
 

fow99

Senior member
Aug 16, 2000
510
0
0
Actually if you really want to do something in C++ style, you'd be better of using the string class offerd by ANSI C++. But you will have to learn something new again.
 

HigherGround

Golden Member
Jan 9, 2000
1,827
0
0
hint 1) you can tell what case are the individuals characters in your string by getting their values. That is upper case characters have ASCII values of 65 (A) - 90 (Z), and lower case chars have value range of 97 (a) - 122 (z). Adding 32 to upper case characters will convert them to lower case...example


const char s2[] = "STrInG";
char s2copy[strlen(s2)+1];

for(int j=0; j<strlen(s2); j++)
if(s2[j] >= 65 &amp;&amp; s2[j] <= 90)
s2copy[j] = s2[j]+32;
else
s2copy[j] = s2[j];


copies s2 into s2copy and converts all of the upper case chars into lower case .

Let me know if You need any more hints/help
 

mulder

Senior member
Oct 9, 1999
684
0
76
I need more help. :) And I think I left out information about the program that may have been helpful, or not. I am using a string class that was created by the teacher; so it's not the string class provided with the Visual C++ library. He makes mention of having to modify our compare() function in order to get the case insensitive sort to work. Here is what the compare function currently looks like (before any modification):

int string::compare(const string&amp; cString) const
{

char* left = buffer;
char* right = cString.buffer;

while((*left != '\0') &amp;&amp; (*left == *right))
{
left++;
right++;
}

return *left - *right;

}


To tell you the truth I am lost. It's been a while since I had to work on something like this and I can't figure out where to start. HigherGround, I tried using what you gave me and it works when I type in your example. But I have to take out strlen and actually put in a number. I included <string> and <string.h>, but neither seemed to help. Here is the actual array I'm working with:

string friends[] = {
&quot;MARY&quot;,
&quot;ray&quot;,
&quot;Luke&quot;,
&quot;aNIta&quot;,
&quot;TeRRy&quot;,
&quot;diane&quot;,
&quot;DANA&quot;,
&quot;Susan&quot;,
&quot;CARY&quot;,
&quot;bobby&quot;
};


Here's what I am thinking right now...I would have to modify the function to receive the passed array of strings. Inside that function I would have to create some temporary strings to house the new upper-case strings. Correct? That way I would be able to perform the sort. But after that how do I get it to output the original string and not the upper-case? And how would I attempt to write this in code? Sorry for the nagging. I just wanted to see if someone might be able to help out some more. Thanks.
 

HigherGround

Golden Member
Jan 9, 2000
1,827
0
0
i'm in a bit of a hurry this evening, ...here's a full program that does case insensitive sorts, i don't have a compiler here so i hope i didn't make any booboos :)


#include <stdio.h>
#include <string.h>
#include <stdlib.h>

static const char* strings[] = { &quot;ABC5&quot;, &quot;abc3&quot;, &quot;aBc1&quot;, &quot;Abc4&quot;, NULL };

// convert to lower case
inline char* convert2lower(const char *s1, char *s2)
{
int len = strlen(s1);

for(int j=0; j<len; j++)
{
s2[j] = s1[j];
if(s1[j] >= 65 &amp;&amp; s1[j] <= 90)
s2[j] +=32;
}

return s2;
}

inline int QSortCompare(const void *v1, const void *v2)
{
// assuming that strings are smaller then 32 chars
// these strings hold lower case copies
char s1lower[32];
char s2lower[32];

// this is is a string.h compare of strings
return strcmp(convert2lower(*(const char**)v1, s1lower), convert2lower(*(const char**)v2, s2lower));
}

void main( )
{
// stdlib quick sort, not the fastest, becaue it's not inline but it does the job done
qsort(strings, 4, sizeof(char*), QSortCompare);
}


I'm not sure whether you are using qsort or are you using your own algorithm, such as Merge or Quick sort...either way modify your comapre routine to by making a two case insensitive copies of the string class and using those copies to do the compare.

OK...ii don't have to leave just yet...so here's what i noticed

1) string classes are just a conveniance wrapper around char*, yours is no different
2) you will access the char* members anyway so why not use strcmp(...)
3) strcmp(...) is case sensitive so you'll still have to convert the case, but the code will look cleaner

so here's what you do...

1) add a member convert2lower(...) (see code above) that copies the buffer member to some temporary variable that holds a lower case converted characters. Obviously you'll have to do this for both string objects.
2) in your compare(...) routine simply return strcmp(....) result from the compare of the converted strings.
3) if you want to use qsort(...) method, make the compare method static, since the compiler might not be able to resolve it, and pass in the reference to that function....for example qsort(friends, 10, sizeof(string), &amp;string::compare)

as requested i'm not writing the code for you, but giving you some hints...if you need more help, don't hesitate, we are here to serve :)
 

mulder

Senior member
Oct 9, 1999
684
0
76
Hey HigherGround,

Thanks for the in-depth reply. I am watching football today and just checked in to see if anyone had responded, so I'll look over the response in more detail later. However, I read over it a little and I noticed some ideas that I was reading about last night. I went to the bookstore and read over some C++ books and I saw the functions such as strcmp and strcmpi. I also re-read some notes in my program and the teacher said we could use the standard library class for help if needed. As far as the sort...I just picked a selection sort algorithm out of the book. I assumed it was the standard selection sort with no special mods. Anyway, I want to thank you for your help. I'll let you know how it goes. Talk to you later.