• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1985
  • Last Modified:

Comparing strings using pointers

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
Wookie68
Asked:
Wookie68
3 Solutions
 
jkrCommented:
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
 
enwhyseeCommented:
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
 
Wookie68Author Commented:
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
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
jkrCommented:
>>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
 
B1-66ERCommented:
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
 
MysidiaCommented:

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..



For  StrCmp, one could start with something like this...

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
 
List244Commented:
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Tackle projects and never again get stuck behind a technical roadblock.
Join Now