views:

157

answers:

4

I've this assignment to implement strcmp function. Sometimes it runs okay but other times it crashes. Please help me.

#include <iostream>

using namespace std;     

int mystrcmp(const char *s1, const char *s2);

int main()
{
cout<<mystrcmp("A","A")<<endl;     
cout<<mystrcmp("B","A")<<endl;     
cout<<mystrcmp("A","B")<<endl;     
cout<<mystrcmp("AB","A")<<endl;

return 0;     
}

int mystrcmp(const char *s1, const char *s2)
{
 while (*s1==*s2)
 {
  s1++;
  s2++;
 }

 if(*s1=='\0')
  return(0);

 return(*s1-*s2);
}
+3  A: 

Your mystrcmp will happily run off the end of the string, because your test for the NUL terminator is outside the loop. If the strings are the same, then both *s1 and *s2 are 0 and the loop keeps going.

Ben Voigt
+3  A: 
while (*s1==*s2)
{
 s1++;
 s2++;
}

'\0' == '\0'

pst
+10  A: 

It will crash if both the input are identical, because your loop continues beyond the terminating nul character.

To fix this you must have a check for nul character inside the loop as:

while (*s1==*s2) {

  // if s1 points to nul character, then s2 should also, because of the ==
  // which means we've reached the end of the strings and they are equal
  // so return 0.
  if(*s1=='\0')
    return 0;

  s1++;
  s2++;
 }

 return *s1-*s2;
codaddict
Thanks man!! It works perfectly now. I owe you a beer :)
John
Here in SO you give beer by giving an upvote :)
codaddict
To expand on codaddict's comment. Pointing one past the end of the string (i.e. one past the '\0') is legal. Dereferencing it is not. John's original while loop could have been left alone and catching all four possible post-loop cases implemented instead. (Don't bother considering this unless the if() every time through the loop is expensive for some reason.)
Eric Towers
Just read the FAQ, I've accepted the answer.
John
@Eric Towers: John's original loop, after comparing the ASCII NULs, immediately dereferences to the following bytes, and may continue as long as the "garbage" afterwards happens to be the same. It IS necessary to check as codaddict has done.
Tony
@Tony: Doh! You're right. No more Stack Overflow after midnight for me... :)
Eric Towers
@codaddict: dunno, I'd prefer the beer, if given the choice ;)
jalf
+1  A: 

You need to think what will happen if your two strings are as follows:

s1:this is a string\0|abcdef
s2:this is a string\0|abcdef
       good memory <-|-> bad memory

Because you're simply advancing the pointers while the contents are equal, you may end up reading memory in a way that's undefined.

A better way is to base your code of the following pseudo-code:

def strcmp(s1,s2):
    while character at s1 is not '\0':
        if character at s1 is not the same as character at s2:
            exit while loop
        increment s1 and s2
    return difference between *s1 and *s2

This will stop when you either reach the end of the first string or you find a difference (including if you've reached the end of the second string before the first).

paxdiablo