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; }