views:

146

answers:

5

Hi.

I'm doing K&R Exercise 5-4 (p107).

Write the function strend(s,t) , which returns 1 if the string t occurs at the end of the string s, and zero otherwise.

I figured the best way to do this was to...

  • increment both pointers to the end
  • count backwards through both strings whilst each char matches
  • return 1 if we had finished counting to the beginning of the second string

So here is what I have...

int strend(const char *str1, const char *str2) {
   int i = 0; 
   while (*str1++ != '\0');

   while (*str2++ != '\0') {
      i++;
   }
   i++;

   while (*str2-- == *str1-- && i > 0) {
     i--;
   }

   return (i == 0);
}

As you can see, I used a counter to tell when I had arrived at the beginning of the second string.

Is there any other loop I can use without a counter to tell when we have arrived at the start of the string (similar to looking for \0 for the end of a string)?

Thanks.

Update

Didn't think to use pointers - I'm still learning and forgetting a few things!

I came up with this...

int strend(const char *str1, const char *str2) {
   char *start = str2; 
   while (*str1++ != '\0');

   while (*str2++ != '\0');

   while (*str2-- == *str1--) {
     if (str2 == start) {
         return 1;
     }
   }

   return 0;
}
+2  A: 

Compare the address of the current character to the original string pointer? If they match, then the current character must be the first one and thus the start of the string.

DeadMG
+4  A: 

Check for matching pointers?

Oli Charlesworth
How does [this](http://codepad.org/yRQKLFat) look? Thanks for the suggestion.
alex
+1  A: 

There is no indicator at the beginning of C strings that identify that is where the string begins. You have to keep some reference to the beginning of the string, like making a copy of the pointer str1.

Also, for this exercise, you do not have to do it with backward scanning. You can do it with using forward scanning and there are certain checks you can make to see if it's worthwhile to even bother seeing if str2 is in str1.

birryree
What sort of checks would you recommend? Perhaps making sure substring's size is smaller or equal to search string?
alex
That is certainly the check - for `strend(s, t)`, there's no point in doing anything further if `strlen(t)` > `strlen(s)`. The rest of the problem can be solved with a little pointer manipulation. ;)
birryree
+2  A: 

Are you allowed to use standard C functions? If so, you can use strlen() to get the length of each string.

E.G,

int lenS = strlen(s);
int lenT = strlen(t);

for (int i = 0; i < lenT; ++i) {
  if (s[lenS - i] != t[lenT - i])
    return 0;
}

return 1;
Sam Dufel
+1  A: 

if you're allowed to use string functions:

int strend(char *s, char *t)
{
    char *st = s + strlen(s) - strlen(t);
    if (st < s) return 0;
    if (!strcmp(st,t)) return 1;
    return 0;
}

Even better by tia (comments):

int strend(char *s, char *t)
{
    char *st = s + strlen(s) - strlen(t);
    if (st >= s) return !(strcmp(st,t)); else return 0

}

slashmais
I don't think you'll need that last `else` there. Thanks for your answer.
alex
yep, fixed, thanx
slashmais
I think you can return it right away. Also need to check for the position of `st` like `if (st >= s) return !(strcmp(st,t)); else return 0` (I insist to put `else` for readability :D);
tia
@tia: function must return 0 or 1, strcmp returns the difference beteen the ascii-values of the first mismatch - so may be negative. Your version is nicer, more compact, though.
slashmais
@slashmais the result or ! operator can only be either 0 or 1.
tia
I somehow overlooked the ! - you're right.
slashmais
These will give undefined behaviour if `t` is larger than `s`. Then `st` does not point to the same array as `s`.
schot
@schot: look again ...
slashmais
@slashmais: You get UB on the first line. It's a variant of C-FAQ [question 6.17](http://www.c-faq.com/aryptr/non0based.html). I would write this function like `{ size_t slen = strlen(s), tlen = strlen(t); return (slen < tlen) ? 0 : !strcmp(s + slen - tlen, t);}`.
schot
@schot: all will be well as long as you do not use st if it is less than s, which in this case I don't. Same with the array-trick you refer to: the moment you use array[0] you will get a memory access error.
slashmais