I have been running into issues with the strcpy() function in C. In this function I take a string in buffer and the string contains a something along the lines of '(213);' and I am trying to remove the brackets so the output would be something like 200;.
for (i = 0; i < bufferlen; i++) {
// check for '(' followed by a naked number followed by ')'
// remove ')' by shifting the tail end of the expression
// remove '(' by shifting the beginning of the expression
if((buffer[i] == '(') && (isdigit(buffer[i+1]))){
int numberLen = 0;
int test =0;
i++;
while((isdigit(buffer[i]))){
i++;
numberLen++;
}
if(buffer[i] == ')'){
int numberStart = i - numberLen-1;
strcpy(&buffer[i], &buffer[i+1]);
strcpy(&buffer[numberStart], &buffer[numberStart+1]);
printf("buffer = %s\n", buffer);
}
}
}
However, the output is as follows
buffer before strcpy(&buffer[i], &buffer[i+1]); = (213);
buffer after strcpy(&buffer[i], &buffer[i+1]); = (213;
buffer after strcpy(&buffer[numberStart], &buffer[numberStart+1]); = 23;;
for some reason the second strcpy function removes the second value of the string. I have also tried
strcpy(&buffer[0], &buffer[1]); and still end up with the same results. Any insight as to why this is occurring would be greatly appreciated.
Continuing from the comment, strcpy(&buffer[i], &buffer[i+1]); where source and dest overlap results in Undefined Behavior, use memmove, or simply use a couple of pointers instead.
The prohibition on using strings that overlap (i.e. are the same string) is found in C11 Standard - 7.24.2.3 The strcpy function
If I understand your question and you simply want to turn "'(213)'" into "213", you don't need any of the string.h functions at all. You can simply use a couple of pointers and walk down the source-string until you find a digit. Start copying digits to dest at that point by simple assignment. When the first non-digit is encountered, break your copy loop. Keeping a flag to indicate when you are "in" a number copying digits will allow you to break on the 1st non-digit to limit your copy to the first sequence of digits found (e.g. so from the string "'(213)' (423)", only 213 is returned instead of 213423). You could do somehting like:
char *extractdigits (char *dest, const char *src)
{
/* you can check src != NULL here */
char *p = dest; /* pointer to dest (to preserve dest for return) */
int in = 0; /* simple flag to break loop when non-digit found */
while (*src) { /* loop over each char in src */
if (isdigit(*src)) { /* if it is a digit */
*p++ = *src; /* copy to dest */
in = 1; /* set in-number flag */
}
else if (in) /* if in-number, break on non-digit */
break;
src++; /* increment src pointer */
}
*p = 0; /* nul-terminate dest */
return dest; /* return pointer to dest (for convenience) */
}
A short example would be:
#include <stdio.h>
#include <ctype.h>
#define MAXC 32
char *extractdigits (char *dest, const char *src)
{
/* you can check src != NULL here */
char *p = dest; /* pointer to dest (to preserve dest for return) */
int in = 0; /* simple flag to break loop when non-digit found */
while (*src) { /* loop over each char in src */
if (isdigit(*src)) { /* if it is a digit */
*p++ = *src; /* copy to dest */
in = 1; /* set in-number flag */
}
else if (in) /* if in-number, break on non-digit */
break;
src++; /* increment src pointer */
}
*p = 0; /* nul-terminate dest */
return dest; /* return pointer to dest (for convenience) */
}
int main (void) {
char digits[MAXC] = "";
const char *string = "'(213}'";
printf ("in : %s\nout: %s\n", string, extractdigits (digits, string));
}
Example Use/Output
$ ./bin/extractdigits
in : '(213}'
out: 213
Look things over and let me know if you have further questions.
Related
I am trying to remove duplicated letters in each word from string.(I haven't specified it for upper and lower case letters yet)
Input:
Ii feel good todday!!
thhis iss fixed
Output:
I fel god today!
this is fixed
I am calling this function in the main and i have to use the result in another function. That's why I call it by reference.
int main(){
char string[100];
printf("Enter a string:");
gets(string);
dup_letters_rule(&string);
return 0;
}
void dup_letters_rule(char *str_[]){
char new_str_[100];
int i=0, j=0;
printf("Fixed duplicates:\n");
while(*str_[i]!='\0'){
if(*str_[i]== *str_[i+1] && *str_[i+1]!='\0'){
while(*str_[i]==*str_[i+1] && *str_[i+1]!='\0'){
i++;
}
*str_[i]=new_str_[j];
j++;
i++;
}
else{
*str_[i]=new_str_[j];
j++;
i++;
}
}
new_str_[j]='\0';
puts(new_str_);
}
It works like:
void dup_letters_rule(char *str_[]){
char *new_str_=*str_, *temp=*str_;
temp++;
printf("Fixed duplicates:\n");
while(*new_str_!='\0'){
if(*new_str_== *temp && *temp!='\0'){
while(*new_str_==*temp && *temp!='\0'){
new_str_++;
temp++;
}
putchar(*new_str_);
new_str_++;
temp++;
}
else{
putchar(*new_str_);
new_str_++;
temp++;
}
}
}
But then, I can't use *str_ string in another function.
The code can be simplified.
We can keep an int value that is the previous char seen and compare it against the current char and only "copy it out" if they are different. (i.e. we only need two pointers).
We also have to use tolower because Ii goes to I.
Although a second/output buffer could be used, the function can do the cleanup "in-place". Then, the caller can use the cleaned up buffer. This is what we'd normally want to do.
If the caller needs to keep the original string, it can save the original to a temp buffer and call the function with the temp
I had to refactor your code. I tested it against your sample input. It is annotated:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void
dup_letters_rule(char *src)
{
char *dst = src;
int prev = -1;
// rchr -- the "raw" char
// lchr -- the result of tolower(rchr)
// prev -- the previous value of lchr (starts with -1 to force output of
// first char)
for (int rchr = *src++; rchr != 0; rchr = *src++) {
// get lowercase char
int lchr = tolower((unsigned char) rchr);
// output if _not_ a dup
if (lchr != prev)
*dst++ = rchr;
// remember this char for the next iteration
prev = lchr;
}
*dst = 0;
}
int
main(void)
{
char *cp;
char buf[1000];
while (1) {
cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// get rid of newline
buf[strcspn(buf,"\n")] = 0;
// eliminate dups
dup_letters_rule(buf);
// output the clean string
printf("%s\n",buf);
}
return 0;
}
UPDATE:
can i print the clean string in the dup_letters_rule function? – hamster
Sure, of course. We're the programmers, so we can do whatever we want ;-)
There is a maxim for functions: Do one thing well
In many actual (re)use cases, we don't want the simple/low level function to do printing. That is the usual.
But, we could certainly add printing to the function. We'd move the printf from main into the function itself.
To get the best of both worlds, we can use two functions. One that just does the transformation. And, a second that calls the simple function and then prints the result.
Here's a slight change that illustrates that. I renamed my function and created dup_letters_rule with the printf embedded in it:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void
dup_letters_rule_basic(char *src)
{
char *dst = src;
int prev = -1;
// rchr -- the "raw" char
// lchr -- the result of tolower(rchr)
// prev -- the previous value of lchr (starts with -1 to force output of
// first char)
for (int rchr = *src++; rchr != 0; rchr = *src++) {
// get lowercase char
int lchr = tolower((unsigned char) rchr);
// output if _not_ a dup
if (lchr != prev)
*dst++ = rchr;
// remember this char for the next iteration
prev = lchr;
}
*dst = 0;
}
void
dup_letters_rule(char *buf)
{
dup_letters_rule_basic(buf);
// output the clean string
printf("%s\n",buf);
}
int
main(void)
{
char *cp;
char buf[1000];
while (1) {
cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// get rid of newline
buf[strcspn(buf,"\n")] = 0;
dup_letters_rule(buf);
}
return 0;
}
UPDATE #2:
and why it's not char *dst = *src; but char *dst = src; – hamster
This is basic C. We want dst to have the same value/contents that src does. Just as if we did:
int x = 23;
int y = x;
If we do what you're suggesting, the compiler flags the statement:
bad.c: In function ‘dup_letters_rule_basic’:
bad.c:8:14: warning: initialization of ‘char *’ from ‘char’ makes pointer from integer without a cast [-Wint-conversion]
char *dst = *src;
^
Doing char *dst = *src [as you suggest] is using * in two different ways.
Doing char *dst says that dst is defined as a pointer to a char.
Doing *src here [which is the initializer for dst and is an expression], the * is the dereference operator. It says "fetch the value (a char) pointed to by src". Not what we want.
Perhaps this would be more clear if we didn't use an initializer. We use a definition (without an initializer) and set the initial value of dst with an assignment statement:
char *dst; // define a char pointer (has _no_ initial value)
dst = src; // assign the value of dst from the value of src
The assignment [statement] can occur anywhere after the definition and before the for loop/statement. Here's the first few lines of the function body:
char *dst;
int prev = -1;
dst = src;
To remove the duplicate consecutive characters from a string in-place, keep track of position in string where the next character, which is not same as its previous character, to be write and check current processing character with previous character (ignore the difference in their case) except when the character is the first character of string because the first character does not have any character previous to it. If current processing character is same as previous character then move to next character in the string and if they are not same then overwrite the character at tracked position with current processing character and increment tracked position pointer by 1.
Its implementation:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void remove_consecutive_dup_chars (char * pstr) {
if (pstr == NULL) {
printf ("Invalid input..\n");
return;
}
/* Pointer to keep track of position where next character
* to be write in order to remove consecutive duplicate character.
*/
char * p = pstr;
for (unsigned int i = 0; pstr[i] ; ++i) {
if ((i) && (tolower (pstr[i]) == tolower (pstr[i - 1]))) {
continue;
}
*p++ = pstr[i];
}
/* Add the null terminating character.
*/
*p = '\0';
}
int main (void) {
char buf[256] = {'\0'};
strcpy (buf, "Ii feel good todday!!");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "thhis iss fixed");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
strcpy (buf, "aaaaaa zzzzzz");
remove_consecutive_dup_chars (buf);
printf ("%s\n", buf);
return 0;
}
Output:
I fel god today!
this is fixed
a z
I'm having looping issues with my code. I have a method that takes in two char arrays (phrase, characters). The characters array holds characters that must be read individually and compared to the phrase. If it matches, every occurrence of the character will be removed from the phrase.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
//This method has two parameters: (str, c)
//It will remove all occurences of var 'c'
//inside of 'str'
char * rmstr(char * c, char * str) {
//Declare counters and pointers
int stemp = 0;
int ctemp = 0;
char *p = str;
char *d = c;
//Retrieve str count
while(str[stemp] != '\0') {
stemp++;
}
//Retrieve c count
while(c[ctemp] != '\0') {
ctemp++;
}
//Output information
printf("String Count: %d\n",stemp);
printf("Character Count: %d\n",ctemp);
//Iterate through arrays
for (int i = 0; i != stemp; i++) {
for (int j = 0; j != ctemp; j++) {
if (c[j] != str[i]){
*p++ = str[i];
}
break;
}
printf("%s\n",str);
}
*p = 0;
return str;
}
int main()
{
char c[256] = "ema";
char input[256] = "Great message!";
char *result = rmstr(c, input);
printf("%s", result);
return 0;
}
In this case, the input would be "Great Message!" and the character I'd like to remove all occurrences of the characters: e, m, a (As specified in main).
Using the code as it is above, the output is as follows:
Grat mssag!
It is only looping through 1 iteration and removing 'e'. I would like it to loop through 'm' and 'a' as well.
After you fix your break; that was causing your inner loop to exit, it may make sense to reorder your loops and loop over the chars to remove while checking against the characters in str. This is more of a convenience allowing you to shuffle each character down by one in str if it matches a character is c. If you are using the functions in string.h like memmove to move characters down, it doesn't really matter.
A simple implementation using only pointers to manually work through str removing all chars in c could look something like the following:
#include <stdio.h>
char *rmstr (char *str, const char *chars)
{
const char *c = chars; /* set pointer to beginning of chars */
while (*c) { /* loop over all chars with c */
char *p = str; /* set pointer to str */
while (*p) { /* loop over each char in str */
if (*p == *c) { /* if char in str should be removed */
char *sp = p, /* set start pointer at p */
*ep = p + 1; /* set end pointer at p + 1 */
do
*sp++ = *ep; /* copy end to start to end of str */
while (*ep++); /* (nul-char copied on last iteration) */
}
p++; /* advance to next char in str */
}
c++; /* advance to next char in chars */
}
return str; /* return modified str */
}
int main (void) {
char c[] = "ema";
char input[] = "Great message!";
printf ("original: %s\n", input);
printf ("modified: %s\n", rmstr (input, c));
return 0;
}
(there are many ways to do this -- how is largely up to you. whether you use pointers as above, or get the lengths and use string-indexes is also a matter of choice)
Example Use/Output
$ ./bin/rmcharsinstr
original: Great message!
modified: Grt ssg!
If you did want to use memmove (to address the overlapping nature of the source and destination) to move the remaining characters in str down by one each time the character in str matches a character in c, you could leave the loops in your original order, e.g.
#include <string.h>
char *rmstr (char *str, const char *chars)
{
char *p = str; /* set pointer to str */
while (*p) { /* loop over each char in str */
const char *c = chars; /* set pointer to beginning of chars */
while (*c) { /* loop over all chars with c */
while (*c == *p) { /* while the character matches */
memmove (p, p + 1, strlen (p)); /* shuffle down by 1 */
c = chars; /* reset c = chars to check next */
}
c++; /* advance to next char in chars */
}
p++; /* advance to next char in str */
}
return str; /* return modified str */
}
(make sure you understand why you must reset c = chars; in this case)
Finally, if you really wanted the shorthand way of doing it, you could use strpbrk and memmove and reduce your function to:
#include <string.h>
char *rmstr (char *str, const char *chars)
{
/* simply loop using strpbrk removing the character found */
for (char *p = strpbrk (str, chars); p; p = strpbrk (str, chars))
memmove (p, p+1, strlen(p));
return str; /* return modified str */
}
(there is always more than one way to skin-the-cat in C)
The output is the same. Look things over here and let me know if you have further questions.
This code removes spaces from a string.
char *RemoveSpaces(char *source)
{
char* i = source;
char* j = source;
while(*j != '\0')
{
*i = *j++;
if(*i != ' ')
i++;
}
*i = 0;
return i;
}
But when I use printf it doesn't return anything.
printf("%s", RemoveSpaces("HELLO WORLD!!! COME ONE\r"));
*i = 0;
return i; // wrong pointer returned
is wrong. It returns a pointer to the string termination (i.e. a pointer to the 0). Therefore it prints nothing.
Try:
*i = 0; // or *i = '\0';
return source; // correct pointer returned
Further, modifying a string literal is not allowed. Instead do:
char str[] = "HELLO WORLD!!! COME ONE\r";
printf("%s", RemoveSpaces(str));
A slight adjustment to your space removal logic may help things make more sense. Instead of setting
*i = *j++;
if(*i != ' ')
i++;
before you test whether *i != ' ', you may find it makes more sense to test first and then assign (where p is your i and ep (end pointer) is your j), e.g.
while (*ep) { /* iterate ep from beginning to end of src */
if (*ep != ' ') /* if its not a space */
*p++ = *ep; /* set begin pointer to char at end ptr, advance */
ep++; /* advance to next char */
}
*p = 0; /* nul-terminate src at p */
In that sense, you only assign and advance the initial pointer if the current character is not a space.
In your example and here, you are modifying the content of source in place, your 'i' and 'j' pointers are used for iterating over the characters in source, so when you are done with the iterations, you return source (or source can be used back in the caller without the return as you are modifying the contents of source in-place.
Putting those pieces together, you could do something similar like the following that will take the string to remove spaces from as the first argument to your code (or use "HELLO WORLD!!! COME ONE\n" by default if no argument is given), e.g.
#include <stdio.h>
char *rmspaces (char *src)
{
char *p = src, /* pointer to beginning of src */
*ep = src; /* pointer to iterate to the end of src */
while (*ep) { /* iterate ep from beginning to end of src */
if (*ep != ' ') /* if its not a space */
*p++ = *ep; /* set begin pointer to char at end ptr, advance */
ep++; /* advance to next char */
}
*p = 0; /* nul-terminate src at p */
return src;
}
int main (int argc, char **argv) {
char *s = argc > 1 ? argv[1] : (char[]){"HELLO WORLD!!! COME ONE\n"};
printf ("%s", rmspaces (s));
return 0;
}
(Note:, your editing in-place is fine, but source (or src) in my case must be modifiable, meaning you cannot pass a string-literal as source (which would likely SegFault). Above a compound-literal is used in the default case to insure the test past is a modifiable character array)
Example Use/Output
$ ./bin/rmspaces
HELLOWORLD!!!COMEONE
Look things over and let me know if you have further questions.
I was wondering we would go about splitting strings into tokens or any other efficient ways of doing this.
i.e. I have...
char string1[] = "hello\tfriend\n";
How would I get "hello" and "friend" in their own separate variables?
Here is a very simple example splitting your string into parts saved in an array of character arrays using a start and end pointer. The MAXL and MAXW defines simply are a convenient way to define constants that are used to limit the individual word length to 32 (31 chars + null terminator) and a maximum of 3 words (parts) of the original string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXL 32
#define MAXW 3
int main (void) {
char string1[] = "hello\tfriend\n";
char *sp = string1; /* start pointer */
char *ep = string1; /* end pointer */
unsigned c = 0; /* temp character */
unsigned idx = 0; /* index for part */
char strings[MAXW][MAXL] = {{0}}; /* array to hold parts */
while (*ep) /* for each char in string1 */
{
if (*ep == '\t' || *ep == '\n') /* test if \t or \n */
{
c = *ep; /* save character */
*ep = 0; /* replace with null-termator */
strcpy (strings[idx], sp); /* copy part to strings array */
*ep = c; /* replace w/original character */
idx++; /* increment index */
sp = ep + 1; /* set start pointer */
}
ep++; /* advance to next char */
}
printf ("\nOriginal string1 : %s\n", string1);
unsigned i = 0;
for (i = 0; i < idx; i++)
printf (" strings[%u] : %s\n", i, strings[i]);
return 0;
}
Output
$ ./bin/split_hello
Original string1 : hello friend
strings[0] : hello
strings[1] : friend
Using strtok simply replaces the manual pointer logic with the function call to split the string.
Updated Line-end Handling Example
As you have found, when stepping though the string you can create as simple an example as you need to fit the current string, but with a little extra effort you can expand your code to handle a broader range of situations. In your comment you noted that the above code does not handle the situation where there is no newline at the end of the string. Rather than changing the code to handle just that situation, with a bit of thought, you can improve the code so it handles both situations. One approach would be:
while (*ep) /* for each char in string1 */
{
if (*ep == '\t' || *ep == '\n') /* test if \t or \n */
{
c = *ep; /* save character */
*ep = 0; /* replace with null-termator */
strcpy (strings[idx], sp); /* copy part to strings array */
*ep = c; /* replace w/original character */
idx++; /* increment index */
sp = ep + 1; /* set start pointer */
}
else if (!*(ep + 1)) { /* check if next is ending */
strcpy (strings[idx], sp); /* handle no ending '\n' */
idx++;
}
ep++; /* advance to next char */
}
Break on Any Format/Non-Print Character
Continuing to broaden characters that can be used to separate the strings, rather than using discrete values to identify which characters divide the words, you can use a range of ASCII values to identify all non-printing or format characters as separators. A slightly different approach can be used:
char string1[] = "\n\nhello\t\tmy\tfriend\tagain\n\n";
char *p = string1; /* pointer to char */
unsigned idx = 0; /* index for part */
unsigned i = 0; /* generic counter */
char strings[MAXW][MAXL] = {{0}}; /* array to hold parts */
while (*p) /* for each char in string1 */
{
if (idx == MAXW) { /* test MAXW not exceeded */
fprintf (stderr, "error: MAXW (%d) words in string exceeded.\n", MAXW);
break;
}
/* skip each non-print/format char */
while (*p && (*p < ' ' || *p > '~'))
p++;
if (!*p) break; /* if end of s, break */
while (*p >= ' ' && *p <= '~') /* for each printable char */
{
strings[idx][i] = *p++; /* copy to strings array */
i++; /* advance to next position */
}
strings[idx][i] = 0; /* null-terminate strings */
idx++; /* next index in strings */
i = 0; /* start at beginning char */
}
This will handle your test string regardless of line ending and regardless of the number of tabs or newlines included. Take a look at ASCII Table and Description as a reference for the character ranges used.
I've seen many solutions for getting substring of a string with usage of strndup or memcpy or strncpy and etc,.
I was wondering if there's a way to get substring without using those functions; even if it's unnecessary.
EDIT: I tried making function myself; I don't remember what the problem was but something went wrong and I ended up not using it.
char *substring(char *str, int start, int length) {
char *s = malloc(sizeof(char)*(length+1));
for(int i=start; i<start+length; i++) {
s[i-start] = str[i];
}
s[length] = '\0';
return s;
}
There are a number of ways to recreate strstr. The following is a quick implementation using the inch-worm method, where you simply use pointers to search for the beginning of the substring in string, then if found, compare every character in substring with the corresponding character in string. If all characters match, the substring is found, return a pointer to the beginning of substring in string.
If a character fails the test, look for another character in string that matches the first character in substring, until string is exhausted.
There are probably several more checks that can be inplemented, but this example should get you started:
#include <stdio.h>
#include <stdlib.h>
char *strstr2 (char *str, char *sub)
{
if (!str || !sub) return NULL; /* validate both strings */
char *p = NULL; /* general pointer */
char *sp = NULL; /* substring pointer */
char *rp = NULL; /* return pointer */
char matched = 0; /* matched flag */
size_t szstr = 0; /* string length */
size_t szsub = 0; /* substring length */
p = sub;
while (*p++) szsub++; /* strlen of substr */
p = str;
while (*p++) szstr++; /* strlen of str */
if (szsub > szstr) return NULL; /* szstr < szsub - no match */
p = str;
while (p < (p + szstr - szsub + 1))
{
while (*p && *p != *sub) p++; /* find start of sub in str */
if ((str + szstr) == p) return NULL; /* if end reached - no sub */
rp = p; /* save return pointer */
sp = sub; /* set sp to sub */
matched = 1; /* presume will match */
while (*sp) /* for each in substring */
if (*p++ != *sp++) { /* check if match fails */
matched = 0; /* if failed, no match */
break; /* break & find new start */
}
if (matched) /* if matched, return ptr */
return rp; /* to start of sub in str */
}
return NULL; /* no match, return NULL */
}
int main() {
char *string = NULL;
char *substr = NULL;
char *begin = NULL;
printf ("\nEnter string : ");
scanf ("%m[^\n]%*c", &string);
printf ("\nEnter substr : ");
scanf ("%m[^\n]%*c", &substr);
if ((begin = strstr2 (string, substr)) != NULL)
printf ("\nSubstring found beginning at : %s\n\n", begin);
else
printf ("\nSubstring NOT in string.\n\n");
if (string) free (string);
if (substr) free (substr);
return 0;
}
output:
$ ./bin/strstr
Enter string : This is the full string or "haystack".
Enter substr : g or "
Substring found beginning at : g or "haystack".
$ ./bin/strstr
Enter string : This is the full string or "haystack".
Enter substr : g or '
Substring NOT in string.
Wow!!! So many variables and tests and lots of indentation.
In the 1970's, some considered it poor style to not have all of the return
statements at the bottom of the routine, but that thinking has mostly disappeared.
For some reason, many programmers write their conditionals to test
if one variable is equal, not equal, greater, or less than something else.
They believe that conditionals should be boolean values and nothing else.
But C allows tests of int, char or others equal or not equal to zero.
Zero can be NULL or NUL or any other zero value. This is legal and appropriate.
if (variable) return NULL;
Some consider conditionals with side effects, such as,
if (*h++ == *n++) continue;
where variables h and n are modified, to not be great style.
To avoid that, I suppose you can rewrite it as
if (*h == *n) { h++; n++; continue;}
Here is my version. It is not worse than the version you supplied on this page. But I want to believe it is shorter, simpler, and easier to understand.
My style is not perfect. Nobody has perfect style. I supply this only
for contrast.
char * strstr( const char *haystack, const char *needle) {
const char *h = haystack, *n = needle;
for (;;) {
if (!*n) return (char *)h;
if (!*h) return NULL;
if (*n++ == *h++) continue;
h = ++haystack;
n = needle;
}
}