I'm having some issues copying the contents of one pointer to another. I'm not able to get the contents of * s to copy into * a. If I remove the bump for * a, it copies only the last character from s. Also the use of any string library functions or any array notation isn't allowed. Sorry if the formatting is poor, this is my first post. Thanks in advance for any help.
char* copy( char *s )
{
char *a = (char *) malloc(sizeof(char)*length(s));
if (s == NULL)
{
printf("ERROR: OUT OF MEMORY\n" );
return 0;
}
while( *s != '\0' )
{
*a = *s;
s++;
a++;
}
*a = '\0';
return a;
}
Never modify the value of a pointer you have allocated. If you do that, may lose track of the address and be unable to free it.
char* copy( const char *s )
{
char *a = malloc(length(s)+1);
if (a == NULL)
{
perror( "malloc failed" );
return NULL;
}
char *c = a;
while( *s != '\0' )
{
*c = *s;
s++;
c++;
}
*c = '\0';
return a;
}
Very simple test:
int main(int argc, char *argv[])
{
const char *s = "this is a test string";
char *a;
if (NULL != (a = copy(s))) {
printf("The copy is: %s\n", a);
free(a);
}
}
Results in:
The copy is: this is a test string
Related
How do i make below program work properly, The main problem i have seen so far is str1 is not defined properly which may be the real cause for the program not working properly.
#include<stdio.h>
#include<string.h>
int main()
{
char string[]="We will rock you";
char s1[10],s2[10];
printf("Enter string 1 ");
gets(s1);
printf("Enter string 2 ");
gets(s2);
int start,end,compare;
for(int i=0;string[i]!='\0';i++)
if(string[i]==s1[0])
{
start=i;
break;
}
//printf("%d",start);
end=start+strlen(s1);
//printf("\n%d",end);
char str1[30],check[10];
//Defining string 1
for(int i=0;i<start;i++)
str1[i]=string[i];
//printf("\n%sd",str1);
//Defining check
for(int i=start;i<end;i++)
check[i-start]=string[i];
//printf("\n%s\n",check,str1);
compare=strcmp(check,s1);
//printf("\n%d",compare);
if(compare==0)
strcat(str1,s1);
printf("\n%s",str1);
for(int i=end,j=strlen(str1);i<strlen(string);i++)
{
str1[j]=string[i];
}
strcpy(string,str1);
printf("\n%s",string);
}
I know this is not the best way to do it, it has so many loopholes as it wont work for words appearing again and it may also change words like (ask, task or asking) if str1 is given ask.
But still help me , What am i doing wrong???
What am i doing wrong???
For starters the function gets is unsafe and is not supported by the C Standard. Instead either use scanf or fgets.
If in this for loop
int start,end,compare;
for(int i=0;string[i]!='\0';i++)
if(string[i]==s1[0])
{
start=i;
break;
}
the condition string[i]==s1[0] does not evaluate to true then the variable start will have an indeterminate value because it is not initialized and all the subsequent code after the for loop invokes undefined behavior because there is used the uninitialized variable start.
If the condition evaluates to true then the value of end
end=start+strlen(s1);
can be larger than the length of the original string string. That again can invoke undefined behavior in this for loop
for(int i=0;i<start;i++)
str1[i]=string[i];
After this for loop
for(int i=start;i<end;i++)
check[i-start]=string[i];
//printf("\n%s\n",check,str1);
compare=strcmp(check,s1);
the array check does not contain a string. So calling the function strcmp also invokes undefined behavior.
It seems that in this call there is at least a typo.
if(compare==0)
strcat(str1,s1)
it seems you mean
strcat( str1, s2 );
^^^
If s1 was not found in string then this loop
for(int i=end,j=strlen(str1);i<strlen(string);i++)
{
str1[j]=string[i];
}
just does not make a sense.
Pay attention to that in general the length of s2 can be greater than the length of s1. In this case you may not change s1 to s2 within string declared like
char string[]="We will rock you";
because that results in accessing memory outside the array.
Function replacing string in the string.
char *strreplace(char *haystack, const char *needle, const char *replace, char *buff)
{
int length = strlen(haystack);
int needlelength = strlen(needle);
int replacelength = strlen(replace);
char *ptr = buff;
char *start, *source, *dest;
if (buff == NULL)
{
ptr = malloc((length + 1) * sizeof(char));
source = ptr;
dest = haystack;
}
else
{
source = haystack;
dest = buff;
}
if (ptr != NULL)
{
if (buff == NULL) strcpy(ptr, haystack);
else
{
if (!length)
{
*buff = 0;
}
}
while (needlelength && *source)
{
size_t chunklen;
char *result;
start = source;
if ((result = strstr(source, needle)) == NULL)
{
strcpy(dest, source);
break;
}
chunklen = result - start;
strncpy(dest, start, chunklen);
dest += chunklen;
strcpy(dest, replace);
dest += replacelength;
source = result;
source += needlelength;
}
if (buff == NULL)
{
free(ptr);
ptr = haystack;
}
else
{
ptr = buff;
}
}
return ptr;
}
Hello and Sorry for bad English.
I think this code can help you
char* replace ( char text[] , char mainchar, char replace_char )
{
char out [120];
char* out_pointer = out ;
register char index_2=0;
for ( register char index_1 = 0 ; index_1 < strlen (text) ; ++index_1 )
{
if ( text[index_1] != mainchar )
{
out_pointer[index_2]=text[index_1];
++index_2 ;
}
else
{
out_pointer[index_2]=replace_char;
++index_2 ;
}
}
return out_pointer;
}
To use this function in your source code, proceed as follows :
#include <stdio.h>
#include <string.h>
int main ()
{
char* replace ( char text[] , char mainchar, char replace_char )
{
char out [120];
char* out_pointer = out ;
register char index_2=0;
for ( register char index_1 = 0 ; index_1 < strlen (text) ; ++index_1 )
{
if ( text[index_1] != mainchar )
{
out_pointer[index_2]=text[index_1];
++index_2 ;
}
else
{
out_pointer[index_2]=replace_char;
++index_2 ;
}
}
return out_pointer;
}
char Array[100];
strcpy (Array, replace("Hello", 'H', 'e'));
printf ("%s", Array);
}
My code:
What I'm trying to do is to input two strings, then return the longest one. If they're the same length then return NULL. Now, the code is just outputting gibberish and I cannot find out why. The function returns a pointer to the first character of the largest string. Then it goes through the while loop, and I'm trying to dereference the pointer and print out its value.
Note: I'm revising for an exam and we have to use only pointers and not treat strings as arrays.
#include<stdio.h>
char* string_ln(char*, char*);
int main() {
char str1[20];
char str2[20];
char* length;
scanf("%s%s", str1, str2);
length = string_ln(str1, str2);
while (length != '\0') {
printf("%c", *length);
length++;
}
}
char* string_ln(char*p1, char*p2) {
int count1 = 0;
while (*p1 != '\0') {
count1++;
p1++;
}
int count2 = 0;
while (*p2 != '\0') {
count2++;
p2++;
}
if (count1 > count2) {
return p1;
}
else if (count2 > count1) {
return p2;
}
else {
return NULL;
}
}
In writing string_ln you iterate over both strings completely to find their lengths, and then compare those numbers. This can work, but you don't actually need to do this. You only need to know which is longer. It doesn't matter how much longer the longer string is.
char *string_ln(char *str1, char *str2) {
char *iter1, *iter2;
for (iter1 = str1, iter2 = str2;
*iter1 && *iter2;
iter1++, iter2++);
if (!(*iter1 || *iter2)) {
return NULL;
}
else if (*iter1) {
return str1;
}
else {
return str2;
}
}
We simply need to iterate over both strings, until at least one hits a NULL character. Once we get to that point, we can test to see which iterator is NULL. If it's both of them, then they're the same length. If the first iterator is not NULL, then the first string is longer. Otherwise, the second string is longer.
The benefit to this approach is that we avoid unnecessary work, and make it much quicker to compare strings of very different lengths.
There are a few problems here. First, you're modifying p1 and p2 in the function, so you won't actually return a pointer to the beginning of the largest string, but to its end. One way to avoid this is to iterate over copies of p1 and p2:
char* string_ln(char*p1, char*p2)
{
char* tmp1 = p1;
int count1 = 0;
while (*tmp1 != '\0') {
count1++;
tmp1++;
}
char* tmp2 = p2;
int count2 = 0;
while (*tmp2 != '\0') {
count2++;
tmp2++;
}
if(count1>count2){
return p1;
}
else if(count2>count1){
return p2;
}
else{
return NULL;
}
}
Second, in your main, you're using the %c format string, which works for a single char, not a whole string. Since you have a string anyway, you can avoid a format string and just print it directly. Also, note that you should explicitly check for NULLs:
int main() {
char str1[20];
char str2[20];
char* longest;
scanf("%s%s", str1, str2);
longest = string_ln(str1, str2);
if (longest) {
printf(longest);
} else {
printf("They are the same length");
}
}
I think you're missing to dereference the pointer. Instead of
while(length!='\0')
you'd need
while(*length!='\0')
That said, in the called function, you're reuring pointers after the increment, i.e., the returned pointers do not point to the start of the string anymore. You need to ensure that you return pointers which points to the beginning of the string. You can change your code to
int count1 = 0;
while (p1[count1] != '\0') {
count1++;
}
int count2 = 0;
while (p2[count2] != '\0') {
count2++;
}
so that p1 and p2 does not change.
For starters the function should be declared like
char * string_ln( const char *, const char * );
because the passed strings are not being changed within the function.
You are returning from the function the already modified pointer p1 or p2 that is being changed in one of the while loops
while (*p1 != '\0') {
count1++;
p1++;
}
while (*p2 != '\0') {
count2++;
p2++;
}
So the returned pointer points to the terminating zero '\0' of a string.
Moreover in main before this while loop
length = string_ln(str1, str2);
while(length!='\0'){
printf("%c", *length);
length++;
}
you are not checking whether the pointer length is equal to NULL. As a result the program can invoke undefined behavior.
The function itself can be defined the following way using only pointers.
char * string_ln( const char *p1, const char *p2 )
{
const char *s1 = p1;
const char *s2 = p2;
while ( *s1 != '\0' && *s2 != '\0' )
{
++s1;
++s2;
}
if ( *s1 == *s2 )
{
return NULL;
}
else if ( *s1 == '\0' )
{
return ( char * )p2;
}
else
{
return ( char * )p1;
}
}
and in main you need to write
char *length = string_ln( str1, str2 );
if ( length != NULL )
{
while ( *length )
printf( "%c", *length++ );
}
Pay attention to that the return type of the function is char * instead of const char *. It is because in C there is no function overloading and the returned pointer can point to a constant string or to a non-constant string. It is a general convention in C for declaring string functions.
I'm solving some problems from a C programming book to brush up on Strings. I can't figure out why my solution is not working.
Question asks to write a function named censor that modifies a string by replacing every occurrence of foo by xxx.
My code:
int main()
{
char msg[] = "I love food, you fool.";
censor(msg);
puts(msg);
return 0;
}
void censor(char *str) {
char *c = str;
while (c+2 != '\0') {
if (*c == 'f' && *(c+1) == 'o' && *(c+2) == 'o')
*c = *(c+1) = *(c+2) = 'x';
c++;
}
}
I found that the while loop runs for like 1700 times. I'm pretty sure msg[] will include a null character automatically end of string.
You're checking the value of the pointer, not what it points to. So instead of this:
while (c+2 != '\0') {
You want this:
while (*(c+2) != '\0') {
If I have understood correctly you may not yet use standard C string functions and the function censor should be written using pointers.
For starters such a string function should return a pointer to the modified string. That is the function return type should be char * instead of void.
The condition in the while loop
while (c+2 != '\0') {
is equivalent to
while (c+2 != NULL) {
because the expression c + 2 has the pointer type char *. So the condition is incorrect.
Moreover in general if you will even change the condition like
while ( *( c+2 ) != '\0') {
the loop can have undefined behavior if the user will pass a string that has less than two characters.
The function can be defined as it is shown in the demonstrative program below.
#include <stdio.h>
char * censor( char *s )
{
const char *s1 = "foo";
const char *s2 = "xxx";
for ( char *p = s; *p; )
{
const char *t1 = s1;
while ( *t1 && *t1 == *p )
{
++t1; ++p;
}
p -= t1 - s1;
if ( *t1 == '\0' )
{
for ( const char *t2 =s2; *t2; ++t2 )
{
*p++ = *t2;
}
}
else
{
++p;
}
}
return s;
}
int main( void )
{
char msg[] = "I love food, you fool.";
puts( msg );
puts( censor( msg ) );
return 0;
}
The program output is
I love food, you fool.
I love xxxd, you xxxl
The code of the shown function does not depend on the strings "foo" and "xxx". The pointers s1 and s2 can be initialized with any other strings that have an equal length.
I am new to pointers and want to learn them well. So this is my own attempt to write my strcat function. If I return just a it prints some binary things (I think it should print the solution), If I return *a it says seg fault core dumped I couldn't find the error. Any help is accepted thanks.
#include <stdio.h>
#include <string.h>
int main() {
char *strcaT();
char *a = "first";
char *b = "second";
printf("%s", strcaT(a, b));
return 0;
}
char *strcaT(char *t, char *s) {
char buffer[strlen(t) + strlen(s) - 1];
char *a = &buffer[0];
for (int i = 0; i < strlen(s) + strlen(t); i++, t++) {
if (*t == '\n') {
for (int i = 0; i < strlen(s);i++) {
buffer[strlen(t) + i] = *(s + i);
}
}
buffer[i] = *(t + i);
}
return a;
}
The code has multiple cases of undefined behavior:
you return the address of a local array in strcaT with automatic storage, which means this array can no longer be used once it goes out of scope, ie: when you return from the function.
the buffer size is too small, it should be the sum of the lengths plus 1 for the null terminator. You write beyond the end of this local array, potentially overwriting some important information such as the caller's framce pointer or the return address. This undefined behavior has a high chance of causing a segmentation fault.
you copy strlen(t)+strlen(s) bytes from the first string, accessing beyond the end of t.
It is unclear why you test for '\n' and copy the second string at the position of the newline in the first string. Strings do not end with a newline, they may contain a newline but and at a null terminator (byte value '\0' or simply 0). Strings read by fgets() may have a trailing newline just before the null terminator, but not all strings do. In your loop, the effect of copying the second string is immediately cancelled as you continue copying the bytes from the first string, even beyond its null terminator. You should perform these loops separately, first copying from t, then from s, regardless of whether either string contains newlines.
Also note that it is very bad style to declare strcaT() locally in main(), without even a proper prototype. Declare this function before the main function with its argument list.
Here is a modified version that allocates the concatenated string:
#include <stdio.h>
#include <stdlib.h>
char *strcaT(const char *s1, const char *s2);
int main() {
const char *a = "first";
const char *b = "second";
char *s = strcaT(a, b);
if (s) {
printf("%s\n", s);
free(s);
}
return 0;
}
char *strcaT(const char *t, const char *s) {
char *dest = malloc(strlen(t) + strlen(s) + 1);
if (dest) {
char *p = dest;
/* copy the first string */
while (*t) {
*p++ = *t++;
}
/* copy the second string at the end */
while (*s) {
*p++ = *s++;
}
*p = '\0'; /* set the null terminator */
}
return dest;
}
Note however that this is not what the strcat function does: it copies the second string at the end of the first string, so there must be enough space after the end of the first string in its array for the second string to fit including the null terminator. The definitions for a and b in main() would be inappropriate for these semantics, you must make a an array, large enough to accommodate both strings.
Here is a modified version with this approach:
#include <stdio.h>
char *strcaT(char *s1, const char *s2);
int main() {
char a[12] = "first";
const char *b = "second";
printf("%s\n", strcaT(a, b));
return 0;
}
char *strcaT(char *t, const char *s) {
char *p = t;
/* find the end of the first string */
while (*p) {
*p++;
}
/* copy the second string at the end */
while (*s) {
*p++ = *s++;
}
*p = '\0'; /* set the null terminator */
return t;
}
It is a very bad idea to return some local variable, it will be cleared after the function finishes its operation. The following function should work.
char* strcaT(char *t, char *s)
{
char *res = (char*) malloc(sizeof(char) * (strlen(t) + strlen(s) + 1));
int count = 0;
for (int i = 0; t[i] != '\0'; i++, count++)
res[count] = t[i];
for (int i = 0; s[i] != '\0'; i++, count++)
res[count] = s[i];
res[count] = '\0';
return res;
}
In the main function
char *strcaT();
It should be declared before main function:
char *strcaT(char *t, char *s);
int main() {...}
You returns the local array buffer[], it's is undefined behavior, because out of strcaT function, it maybe does not exist. You should use the pointer then allocate for it.
The size of your buffer should be +1 not -1 as you did in your code.
char *strcaT(char *t, char *s) {
char *a = malloc(strlen(t) + strlen(s) + 1);
if (!a) {
return NULL;
}
int i;
for(i = 0; t[i] != '\0'; i++) {
a[i] = t[i];
}
for(int j = 0; s[j] != '\0'; j++,i++) {
a[i] = s[j];
}
a[i] = '\0';
return a;
}
The complete code for test:
#include <stdio.h>
#include <stdlib.h>
char *strcaT(char *t, char *s);
int main() {
char *a = "first";
char *b = "second";
char *str = strcaT(a, b);
if (str != NULL) {
printf("%s\n", str);
free(str); // Never forget freeing the pointer to avoid the memory leak
}
return 0;
}
char *strcaT(char *t, char *s) {
char *a = malloc(strlen(t) + strlen(s) + 1);
if (!a) {
return NULL;
}
int i;
for(i = 0; t[i] != '\0'; i++) {
a[i] = t[i];
}
for(int j = 0; s[j] != '\0'; j++,i++) {
a[i] = s[j];
}
a[i] = '\0';
return a;
}
For starters the function strcaT should append the string specified by the second parameter to the end of the string specified by the first parameter. So the first parameter should point to a character array large enough to store the appended string.
Your function is incorrect because at least it returns a (invalid) pointer to a local variable length character array that will not be alive after exiting the function and moreover the array has a less size than it is required to store two strings that is instead of
char buffer[strlen(t) + strlen(s) - 1];
^^^
it should be declared at least like
char buffer[strlen(t) + strlen(s) + 1];
^^^
and could be declared as static
static char buffer[strlen(t) + strlen(s) + 1];
Also the nested loops do not make sense.
Pay attention that you should provide the function prototype before calling the function. In this case the compiler will be able to check passed arguments to the function. And the name of the function strcaT is confusing. At least the function can be named like strCat.
The function can be defined the following way
#include <stdio.h>
#include <string.h>
char * strCat( char *s1, const char *s2 )
{
char *p = s1 + strlen( s1 );
while ( ( *p++ = *s2++ ) );
return s1;
}
int main(void)
{
enum { N = 14 };
char s1[N] = "first";
char *s2 = "second";
puts( strCat( s1, s2 ) );
return 0;
}
The program output is
firstsecond
On the other hand if you are already using the standard C function strlen then why not to use another standard C function strcpy?
With this function your function could be defined more simpler like
char * strCat( char *s1, const char *s2 )
{
strcpy( s1 + strlen( s1 ), s2 );
return s1;
}
If you want to build a new character array that contains two strings one appended to another then the function can look for example the following way.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * strCat( const char *s1, const char *s2 )
{
size_t n1 = strlen( s1 );
char *result = malloc( n1 + strlen( s2 ) + 1 );
if ( result != NULL )
{
strcpy( result, s1 );
strcpy( result + n1, s2 );
}
return result;
}
int main(void)
{
char *s1 = "first";
char *s2 = "second";
char *result = strCat( s1, s2 );
if ( result ) puts( result );
free( result );
return 0;
}
Again the program output is
firstsecond
Of course calls of the standard C function strcpy you can substitute for your own loops but this does not make great sense.
If you are not allowed to use standard C string functions then the function above can be implemented the following way.
#include <stdio.h>
#include <stdlib.h>
char * strCat( const char *s1, const char *s2 )
{
size_t n = 0;
while ( s1[n] != '\0' ) ++n;
for ( size_t i = 0; s2[i] != '\0'; )
{
n += ++i;
}
char *result = malloc( n + 1 );
if ( result != NULL )
{
char *p = result;
while ( ( *p = *s1++ ) != '\0' ) ++p;
while ( ( *p = *s2++ ) != '\0' ) ++p;
}
return result;
}
int main(void)
{
char *s1 = "first";
char *s2 = "second";
char *result = strCat( s1, s2 );
if ( result ) puts( result );
free( result );
return 0;
}
I have changed your program to look like below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* strcaT();
char* a = "first";
char* b = "second";
printf("%s",strcaT(a,b));
return 0;
}
char* strcaT(char *t, char *s)
{
char* a = (char*)malloc(sizeof(char)*(strlen(t) + strlen(s) + 1));
for(int i=0; i<strlen(t); i++) {
a[i] = t[i];
}
for(int i=0; i<strlen(s); i++) {
a[strlen(t) + i] = s[i];
}
a[strlen(t)+strlen(s)] = '\0';
return a;
}
You are getting segfault because you are returning address of a local array which is on stack and will be inaccessible after you return. Second is that your logic is complicated to concatenate the strings.
Hello i am trying to make my own strstr() function and i can't figure out why it is returning a segmentation fault.I am trying to search a string within another string and then return a pointer to the first 'same' letter. Any help would be appreciated.
This is my code:
char* ms_search(char *Str1,char* Str2){
char* p = NULL;
int i,k=0,j = 0;
for(i = 0;i < ms_length(Str1); i++){
if(Str1[i] == Str2[k]){
if(k == 0){
p = &Str1[i];
j= i;
}
if(k == ms_length(Str2)){
break;
}
k++;
}
else{
if(Str1[i] == Str2[0]){
p = &Str1[i];
k=1;
j= i;
}
else{
j=0;
k = 0;
p = NULL;
}
}
}
if(p != NULL){
Str1[ms_length(Str2)+1] = '\0';
}
return &Str1[j];
}
int main(){
int i;
char* p2;
char* p="lolaaa";
char* p1= "aaa";
//char ar2[] = "aaa4";
//ms_copy(p,p1);
//printf("%s",p);
//ms_nconcat(p,p1,3);
//if(ms_ncompare(p,p1,3) == 1) printf("einai idia");
p2 = ms_search(p,p1);
printf("%s",p2);
return 0;
}
Hello i am trying to make my own strstr()
First of all you have to follow the C standard.
The C89/C99 prototype is:
char *strstr(const char *s1, const char *s2);
Standard strstr() function will NOT change the passed buffers.
The functionality is described as:
strstr() function locates the first occurrence in the string pointed to by s1 of the sequence of characters (excluding the terminating null character) in the string pointed to by s2.
The strstr function returns a pointer to the located string, or a null pointer if the string is not found. If s2 points to a string with zero length, the function returns s1.
In standard C, this can be implemented as:
#include <string.h> /* size_t memcmp() strlen() */
char *strstr(const char *s1, const char *s2)
{
size_t n = strlen(s2);
while(*s1)
if(!memcmp(s1++,s2,n))
return (char *) (s1-1);
return 0;
}
The standalone implementation is given below:
#include <stdio.h>
char *strstr1(const char *str, const char *substring)
{
const char *a;
const char *b;
b = substring;
if (*b == 0) {
return (char *) str;
}
for ( ; *str != 0; str += 1) {
if (*str != *b) {
continue;
}
a = str;
while (1) {
if (*b == 0) {
return (char *) str;
}
if (*a++ != *b++) {
break;
}
}
b = substring;
}
return NULL;
}
int main (void)
{
char string[64] ="This is a test string for testing strstr";
char *p;
p = strstr1 (string,"test");
if(p)
{
printf("String found:\n" );
printf ("First occurrence of string \"test\" in \"%s\" is:\n%s", string, p);
}
else
{
printf("String not found!\n" );
}
return 0;
}
Output:
String found:
First occurrence of string "test" in "This is a test string for testing strstr" is:
test string for testing strstr
Your standalone strstrl is correct.
I have my preferences, and you have yours.
Neither is perfect.
You prefer
if ( *b == 0 ) {
return (char *) s1;
}
I prefer
if ( ! *b ) return (char *) s1;
You prefer
str += 1;
I prefer
str++;
You prefer
while (1)
I prefer
for (;;)
If I rewrite your strstrl with my preferences, we get
char *strstr1(const char *str, const char *substring)
{
const char *a, *b = substring;
if ( !*b ) return (char *) str;
for ( ; *str ; str++) {
if (*str != *b) continue;
a = str;
for (;;) {
if ( !*b ) return (char *) str;
if (*a++ != *b++) break;
}
b = substring;
}
return NULL;
}
Note that this version has the same snippet
if ( ! *b ) return (char *) str;
in two locations. Can we rearrange to do that test only once?
Note how we do two tests when lead character matches
if ( *str != *b )
and again later for the same lead char
a = str ; if ( *a++ != *b++)
Can we rearrange that to do a single test?
My rewrite of your standalone strstr is below. It might not be
your style, but it is in many ways similar to your standalone strstr.
My rewrite is shorter and, I want to believe, easier to understand.
char *strstr(const char *str, const char *substring)
{
const char *a = str, *b = substring;
for (;;) {
if ( !*b ) return (char *) str;
if ( !*a ) return NULL;
if ( *a++ != *b++) { a = ++str; b = substring; }
}
}