Solved

# Comparing strings using pointers

Posted on 2006-04-09
1,936 Views
I'm getting more acquainted with pointers and thought a good way to learn would be to try and imitate a simple function.  Doesn't seem to be working well for me at the moment. Using pointers to str1[] and str2[], I'd like to be able to get the same results as using strcmp().  When I run the code below, it always returns 0. How can I correct it?
Thanks

#include <iostream>
#include <cstring>
using namespace std;

int StrCompare (char *s1, char *s2);

int main ()
{
char* str1[] = {"", "a", "ab", "abc"};
char* str2[] = {"", "", "abcd", "abce", "ab", "a", "aba", "aca"};
cout << "The function for strcmp <\"\",\"\" > is:\t\t " << StrCompare(str2[0], str2[1])  << endl;
cout << "The function for strcmp <\"abcd\",\"abce\" > is:    " << StrCompare(str2[2], str2[3])  << endl;
cout << "The function for strcmp <\"ab\",\"a\" > is:\t \t " << StrCompare(str2[4], str2[5])  << endl;
cout << "The function for strcmp <\"a\",\"ab\" > is:\t\t" << StrCompare(str2[5], str2[4])  << endl;
cout << "The function for strcmp <\"aba\",\"aca\" > is:\t" << StrCompare(str2[6], str2[7])  << endl;
system("pause");
return 0;
}

int StrCompare(char *s1, char *s2)
{
if (*s1 == *s2)
{
return 0;
}
if (*s1 > *s2)
{
return 1;
}
if (*s1 < *s2)
{
return -1;
}
}
0
Question by:Wookie68

LVL 86

Expert Comment

You cannor use these operators to compare strings that way, since you are only comaring the 1st character of each string, that will not work. If you focus on string liteals, testing the pointer addresses to find identical litrals might work, but is limited to that very purpose. To compare strings, you will need to compare the *whole* contents, and that is what 'strcmp()' does.
0

LVL 6

Accepted Solution

Your StrCompare code is only comparing the very first character in your strings :) Hence, it doesn't look at the rest of the string.

You would need to do a loop first up until a null-terminating character. It might be something like:

int StrCompare(char *s1, char *s2)
{
// Loop until the strings are different, or one of the strings ends
while(*s1 && *s2 && *s1 == *s2)
{
s1++;
s2++;
}

if (*s1 == *s2)
{
return 0;
}
if (*s1 > *s2)
{
return 1;
}
if (*s1 < *s2)
{
return -1;
}
}
0

Author Comment

I know it seems crazy to NOT use strcmp()... I borrowed a book from a friend to learn more about pointers and one of the exercises was to implement strcmp() using pointers. I figured they wouldn't ask it as an exercise and not have something for me to learn from it.

So in addition to what I have above, I also need to figure the length of the element as well?
0

LVL 86

Assisted Solution

>>So in addition to what I have above, I also need to figure the length of the element as well?

More than that, you will have to compare each element, e.g.

int my_strcmp (
const char * src,
const char * dst
)

int ret = 0 ;

while( ! (ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst)
++src, ++dst;

if ( ret < 0 )
ret = -1 ;
else if ( ret > 0 )
ret = 1 ;

return( ret );
}
0

LVL 5

Expert Comment

Hi Wookie68.

>>So in addition to what I have above, I also need to figure the length of the element as well?

length of both elements! and then iterate throw the smallest element:

strcmp("lollol", "lol")

in this case, you must iterate through the elements of the second argument, and compare all those symbols, with first argument.
0

LVL 23

Assisted Solution

The thing to keep in mind is a string is an array of characters.

If you have an array named  a[]        or a[some_number], then

"a" by itself  is converted to the base address of the array

and "*a"  is the first element.

If you have a pointer to  "char",  i.e. "char *x;"; a "string" in C,   then *x represents a single character,
the first of the string, and the one pointed to.

The last character of a string is 0, and a string can be empty.  if   *x is equal to  the character \0
(ASCII code NUL or 0),  then the string is empty.

Before trying  Strcmp, why don't you try  thinking the simpler... like StrLen.

I.E.

int Strlen(char *s1)
{
int counter = 0;

if ( s1 == NULL ) {
/* s1 is a null pointer */
printf ("Error!\n");
return -1;
}

while ( *s1 != '\0' ) {
counter++;
s1++;
}
return counter;
}

You might like to try StrCmp() again before looking below..

int StrCmp(char s1[],  char s2[]) {
int i = 0;
int result = 0;

while ( 1 ) {
if ((unsigned char)s1[i] < (unsigned char)s2[i]) { return -1; }
if ((unsigned char)s1[i] > (unsigned char)s2[i]) { return 1; }
if (s1[i] == '\0') { return 0; }

i++;
}
}

Note that while this syntactically uses arrays, due to pointer conversion support in C, it is essentially
the same as using pointers.

So the above should look very similar to the pure pointer solution.

Note this particular code relies on some trickery:

If  string 1 is shorter than string 2,  when checking last character of s1 it will be \0 and the last character of
s2 will be other than \0 (therefore greater).

If string2 is shorter than string1, then the last character of s2 will be \0 and the last character of
s1 will not be \0 (therefore will have a value greater than string2's \0)

Hence the two comparisons also handle the case where one string is shorter.

Finally, if the two strings are the same length,   then where s1[0] == '\0'   it will also be true that
s2[0] == '\0', so we return 0,  without having to check both cases.

This is premature optimization, even if it doesn't look as pretty, I could have asserted every case;
which actually less error prone...

if (s1[i] == '\0'  && s2[i] != '\0') {
return -1;
}

if (s1[i] != '\0'  && s2[i] == '\0') {
return 1;
}

if ((unsigned char)s1[i] < (unsigned char)s2[i]) {
return -1;
}
...
if (s1[i] == '\0' || s2[i] == '\0') { return 0; }
0

LVL 8

Expert Comment

Just to expand on Mysidia's comment:

char *CharArray= "MyArray";

When you have an array of characters, each character is accessed one at a time.
*CharArray for example is equivalent to CharArray[0] which in this case is M.

If you wish to access further elements, you must specifiy which.  For example, the
second element would be:

CharArray[1] OR... in pointer notation *(CharArray+1)

Knowing this, we can loop through our array properly:

#include <iostream>

short StrLen(char* String); //Function determines length

using namespace std;
int main()
{
char *CharArray= "MyArray";
for (int i=0;i<StrLen(CharArray);i++) //Loop through all values 0 through its entier length
{
char CVal = *(CharArray+i);//Same as CharArray[i]
cout << CVal << endl; //show value
CVal = CharArray[i]; //Same as *(CharArray+i)  // Here we are dereferencing the character at position i
cout << CVal << endl; //show value (same as value above)
}
}

short StrLen(char* String)
{
int i =0; //Loop through the array
while (*(String+i) != '\0') //while the current value *(String+i) OR String[i] is not the end of the string '\0' specifies the end of the held string
{
i++; //increase i
};
return i;//return i -1 for size of string
}

Hopefully that helps you to understand the difference between pointer notation and array notation.
0

## Featured Post

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.