Jump to: navigation, search

The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 5.04 on page 107

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



Solution by Bryan Williams

/*

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

    Author : Bryan Williams

*/


int strlen(char *s) /* added by RJH; source: K&R p99 */
{
  int n;

  for(n = 0; *s != '\0'; s++)
  {
    n++;
  }
  return n;
}

int strcmp(char *s, char *t) /* added by RJH; source: K&R p106 */
{
  for(;*s == *t; s++, t++)
    if(*s == '\0')
      return 0;
  return *s - *t;
}


int strend(char *s, char *t)
{
  int Result = 0;
  int s_length = 0;
  int t_length = 0;

  /* get the lengths of the strings */
  s_length = strlen(s);
  t_length = strlen(t);

  /* check if the lengths mean that the string t could fit at the string s */
  if(t_length <= s_length)
  {
    /* advance the s pointer to where the string t would have to start in string s */
    s += s_length - t_length;

    /* and make the compare using strcmp */
    if(0 == strcmp(s, t))
    {
      Result = 1;
    }
  }

  return Result;
}



#include <stdio.h>


int main(void)
{
  char *s1 = "some really long string.";
  char *s2 = "ng.";
  char *s3 = "ng";

  if(strend(s1, s2))
  {
    printf("The string (%s) has (%s) at the end.\n", s1, s2);
  }
  else
  {
    printf("The string (%s) doesn't have (%s) at the end.\n", s1, s2);
  }
  if(strend(s1, s3))
  {
    printf("The string (%s) has (%s) at the end.\n", s1, s3);
  }
  else
  {
    printf("The string (%s) doesn't have (%s) at the end.\n", s1, s3);
  }

  return 0;
}


Solution by Kirill Yatsenko

3 lines of code...

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

int strend(const char*, const char*);

int main()
{
    int val = strend("12345 111", "111");
    printf("\n res = %d", val);

    return 0;
}

int strend(const char* s, const char* t)
{
    s += strlen(s) - strlen(t);

    while(*s && *s++ == *t++);

    return !*s;
}


Solution by Fenglu Niu King's

The simplest(Just Private Opinion)

#include <stdio.h>

int strend(char *, char *);

int main(void)
{
    char *s = "abcdef";
    char *t = "def";
    printf("%d\n",strend(s, t));
    return 0;
}

int strend(char *s, char *t)
{
    char *pt;
    for (pt = t;*s != '\0'; ++s)
        if (*pt != '\0' && *s == *pt)
            ++pt;
        else
            pt = t;
    if (*s == '\0' && *pt == '\0')
        return 1;
    return 0;
}


Solution by Nicholas Smillie (Category 0)

Cleaner solution...

#include <string.h>

int strend(char *s, char *t);

int main()
{
    char *s = "the world is over";
    char *t = "over";

    if (strend(s, t))
        printf("The text '%s' occurs at the end of the string '%s'", t, s);
    else
        printf("Test failed.");

    return 0;
}

int strend(char *s, char *t)
{
    s += (strlen(s) - strlen(t));      //increments to the point of comparison
    while (*s++ == *t++)               //tests for equality
        if (*s == '\0')                //checks for null character while lines are equal
            return 1;
    return 0;
}


Solution by Jesus Alvarez (Category 0)

(The solution above is the correct way, this solution reverses the strings and then compares. Reversing is not necessary.)

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

#define STR_BUFFER 10000

int  strend(char *, char *);
void strrev(char *, char *);

int main(int argc, char *argv[])
{
        char string1[STR_BUFFER] = "ole.";
        char string2[STR_BUFFER] = "hole. ";

        printf ("String 1: %s\n", string1);
        printf ("String 2: %s\n", string2);

        if (strend(string1, string2)) {
                printf ("String 2 occurs at the end of string 1!\n");
        } else {
                printf ("String 2 does not occur at the end of string 1.\n");
        }
        return 0;
}

int strend(char *s, char *t)
{
        char *s_pt, *t_pt;
        char s_rev[STR_BUFFER];
        char t_rev[STR_BUFFER];

        s_pt = s_rev;
        t_pt = t_rev;

        /* Reverse the strings to make the matching more fun, but not very
         * efficient. :) */
        strrev(s, s_rev);
        strrev(t, t_rev);

        for ( ; *s_pt == *t_pt; s_pt++, t_pt++) {
                if (*s_pt == ' ' || *s_pt == '\t' || *s_pt == '\0') {
                        return 1; /* The ends of the strings match. */
                } else {
                        return 0;
                }
        }

        return 0;
}

/*
 * strrev()
 * Reverses a string.
 * @param: str  Pointer to the string to be reversed.
 * @param: dest Pointer where the result will be stored.
 */
void strrev(char *str, char *dest)
{
        int i = strlen(str)-1; /* -1 to skip the '\0' */
        for (str += i; i >=0; dest++, str--, i--) {
                /* Increment backwards over str copying to dest. */
                *dest = *str;
        }
        dest++;
        dest = '\0';
}


Solution by Jose G. López (Category 0)

#include <stdio.h>

int strend(char *s, char *t);

int main(void)
{
	char *s = "hello, hello";
	char *t = "llo";

	if (strend(s, t))
		printf("'%s' occurs at the end of '%s'\n", t, s);
	else
		printf("no occurences at the end of '%s' from '%s'\n", s, t);

	return 0;
}

int strend(char *s, char *t)
{
	int i = 0;
	int ind;

	while (*s) {
		for (ind = 0; *(s + ind) == *(t + ind) 
				&& *(s + ind) != '\0' && *(t + ind) != '\0'; ind++)
			;
		if(*(s + ind) == '\0' && *(t + ind) == '\0')
			return 1;
		s++;
	}

	return i;
}


Solution by Prabhat Pal (Category 0)

#include<stdio.h>

int strend(char *s, char *t)
{
    char *p = t;
    while(*s)
    {
        p = t;
        while(*s++ != *p); /* new s value is one ahead of matched *p value */
        ++p; /*Lock step*/
        while(*s++ == *p++)
            if(*(s-1)=='\0' && *(p-1)=='\0')
                return 1; /*Both matched till the end, boundary condition*/
    }
    return 0;
}

int main(void)
{
    char s[] = "The cat zzy!! is going crazyy!!";
    char t[] = "zyy!!";
    printf("%s\n",(strend(s,t))?"Matched":"Not Matched");
    return 0;
}


Solution by menonsahab's

#include <stdio.h>
#include <string.h>
int strend(char *s, char *t)
{
	int slen = strlen(s), tlen = strlen(t);
	if (slen < tlen)
		return 0;
	else
	{
		s = s + slen - tlen;
		return strcmp(s, t) ? 0 : 1;
	}
}
int main()
{
	char s[] = "Daiki", t1[] = "iki", t2[] = "Midorima";
	printf("strend(%s, %s) = %d\n", s, t1, strend(s, t1));
	printf("strend(%s, %s) = %d\n", s, t2, strend(s, t2));
	return 0;
}


Solution by seankndy

#include <stdio.h>

int strend(char *s, char *t);

int main(void)
{
        printf("first strend returned %d\n", strend("hello, world!", ", world!"));
        printf("second strend returned %d\n", strend("hello, world!", "hello"));
        printf("third strend returned %d\n", strend("hello, world!", "xorld!"));
        printf("fourth strend returned %d\n", strend("hello, world!", "!"));
        printf("fifth strend returned %d\n", strend("hello, world!", "hello, world! hello, world!"));
        return 0;
}

int strend(char *s, char *t)
{
        char *sc = s;
        char *tc = t;

        while (*s != '\0')
                s++;
        while (*t != '\0')
                t++;
        while (s > sc && t > tc && *s-- == *t--)
                ;
        return (t == tc && *s == *t ? 1 : 0);
}


Solution by I9383

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

main()
{
	int strend(char *, char *);
	char s[] = "Hello, world";

	printf("%d\n", strend(s, "ld"));

	return 0;
}

int strend(char *s, char *t)
{
	while (*s++)
		if (*s == *t && !strcmp(s, t))
				return 1;
	return 0;
}


Solution by Luke Panayi (Category 0)

Clean cat0 solution that saves the starting pointer of t and resets back to it when matching is broken:

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

#include <stdio.h>

int strend(char *s, char *t)	{
	char *tstart = t;
	while (*s)	{
		if (*++s == *t)	{
			while (*++s == *++t)	{
				if (!*s && !*t)
					return 1;
				}
			t = tstart;
			}
		}	
	return 0;
}

int main()	{
	printf("%d\n", strend("hello world!", "world!"));
	return 0;
}


Solution by codybartfast (Category 0)

I tested with the following cases:

	"a", "" -> 1
	"duck", "duck" -> 1
	"Unsubtle", "subtle" -> 1
	"frankly", "frank" -> 0
	"aaaaaX", "aaaaX" -> 1

These cases matched the results of Bryan, menonsahab and seankndy's code. Nicholas, Jose and Prabhat's code produced similar results but have "a", "" -> 0. The others had potential errors, often with the "duck" or "aaaaX" case.

My own solution is neither pretty nor efficient:

int strend(char *s, char *t)
{
	char *cs, *ct;
	do {
		for (cs = s, ct = t; *cs == *ct; cs++, ct++)
			if (*cs == '\0')
				return 1;
	} while (*s++ != '\0');
	return 0;
}

Solution by Roberto Kok (Category 0)

Thanks to codybartfast for mentioning the "aaaX" problem.

#include <stdio.h>

int strend(char *, char *);

int main() {
    char a[] = "aaaX";
    char b[] = "aaX";
    printf("does '%s' end in '%s'? --> %d\n", a, b, strend(a, b));
}

int strend(char *s, char *t) {
    char *s0 = s, *t0 = t; // create pointers to the beginnings of s and t
    while ((*s && s++) || (*t && t++)); // fast-forward s and t to their endings
    for (;t0 < t && s0 < s && *(s-1) == *(t-1); s--, t--); // compare s and t backwards, char by char, until we run out of chars
    return (t == t0) ? 1 : 0; // if we made it back to the beginning of t, it's a match!
}


Solution by DtxdF

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

int strend(char *s, char *t) {
	size_t l = strlen(t);

	while (*s++)
		;

	s--;

	while (*t++)
		;

	t--;

	while (--l) {
		if (*s-- != *t--)
			return 0;

	}

	return 1;

}

int main(void) {
	char *str = "I love programming in C";

	printf("%d\n", strend(str, "in C")); /* 1 */
	printf("%d\n", strend(str, "in Java")); /* 0 :) */

	return EXIT_SUCCESS;

}

Solution by anonymous

I noticed quite a few preserved the original pointer location of the string that was passed into the function, but I suppose they forgot that the pointers sent the function are pass-by-value (meaning the pointer *s and *t are automatic variables that contain a copy of original pointer). You can pass the address of a pointer which would affect the original pointer, but I don't think that has been brought up in the book as of yet.

My function uses for loops for moving s and t to the end, but next time I am going to copy seankndy's first two while loops since I find it easier to comprehend. I could have done the third while loop like seankndy's version, but my goal was for ease of understanding so I didn't. Also, the easiest way to do this would be to include strings.h and use strlen and strcmp from it, but I felt like that was too easy.

#include <stdio.h>

/*
    Exercise 5-4. Write the function strend(s, t), which returns 1 if the string t occurs at the end of the string s, and zero otherwise.
*/

int strend(char *s, char *t);

int main()
{
    char *a = "To be, or not to be, that is the question:\nWhether 'tis nobler in the mind to suffer\nThe slings and arrows of outrageous fortune,\nOr to take arms against a sea of troubles";
    printf("%d\n", strend(a, a));
    printf("%d\n", strend(a, "to take arms against a sea of troubles"));
    printf("%d\n", strend(a, "sea of trouble"));
    printf("%d\n", strend(a, "s"));
    printf("%d\n", strend(a, "")); // equals '\0'
    printf("%d\n", strend(a, "\n"));

    return 0;
}

// returns 1 if the string t occurs at the end of the string s, and zero otherwise.
int strend(char *s, char *t)
{
    int len = 0;
    for ( ; *s; s++) // move s to point to '\0' in str. Handles if s == "" (never increments), but does not work if s is uninitialized (e.g. char a[1000];) since its values are garbage
        ;
    for ( ; *t; t++) // move t to point to '\0' in str. Handles if t == "" (never increments), but does not work if t is uninitialized (e.g. char a[1000];) since its values are garbage
        len++; // get length of t
    while (len-- >= 0) // if len of t is >= 0 instead of > 0 since I consider the string terminator as part of the string
        if (*s-- != *t--)
            return 0;
    return 1;
}

Solution by Evgenii Pavlenko (Category 0)

#include <stdio.h>

int strend(char *, char *);

int main(void)
{
  char str1[] = "Hello, world";
  char str2[] = "world";

  printf("String one is (%s)\n", str1);
  printf("String two is (%s)\n", str2);
 
  int result = strend(str1, str2);
  printf("The result is (%d)\n", result);

  return 0;
}

int strend(char *s, char *t)
{
  int counter;
  
  /* count number of characters and place pointer to last letter of second string */
  for(counter = 0; *t != '\0'; ++counter, *t++)  
    ;
  
  /* place pointer to position of last letter of first string */
  for ( ; *s != '\0'; *s++) 
    ;
    
  /* compare letters of strings from the end */
  for ( ; counter > 0 && *s == *t; counter--, *--s, *--t)
    ;
    
  return (counter == 0) ? 1 : 0;
}
Personal tools