Home > Net >  Why my returned value of strchr is ignored?
Why my returned value of strchr is ignored?

Time:06-07

I have to make a function, that will code my sentence like this: I want to code all words with an o, so for example I love ice cream becomes I **** ice cream.

But my function ignores the result of strchr. And I don't know why.

This is my code:

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

#define LEN 1000

char *Shift(char *str, char *let) {
    const char *limits = " ,-; .";
    char copy[LEN];
    strcpy(copy, str);
    char *p;
    char *ptr;
    ptr = strtok(copy, limits);
    for (int j = 0; ptr != NULL; ptr = strtok(NULL, limits),   j) {
        int len = 0;
        if (strchr(ptr, let) != NULL) {
            p = strstr(str, ptr);
            for (int i = 0; i < strlen(ptr); i  ) {
                p[i] = "*";
            }
        }
    }
    return str;
}

int main() {
    char *s = Shift("I love my cocktail", "o");
    puts(s);
}

Expected output is: I **** my ********

but I've got just printed the original string

CodePudding user response:

For starters the function strchr is declared like

char *strchr(const char *s, int c);

that is its second parameter has the type int and the expected argument must represent a character. While you are calling the function passing an object of the type char * that results in undefined behavior

if (strchr(ptr, let) != NULL) {

It seems you mean

if (strchr(ptr, *let) != NULL) {

Also you may not change a string literal. Any attempt to change a string literal results in undefined behavior and this code snippet

        p = strstr(str, ptr);
        for (int i = 0; i < strlen(ptr); i  ) {
            p[i] = "*";
        }

tries to change the string literal passed to the function

char *s = Shift("I love my cocktail", "o");

And moreover in this statement

            p[i] = "*";

you are trying to assign a pointer of the type char * to a character. At least you should write

            p[i] = '*';

If you want to change an original string you need to store it in an array and pass to the function the array instead of a string literal. For example

char s[] = "I love my cocktail";
puts( Shift( s, "o" ) );

Pay attention to that there is no great sense to declare the second parameter as having the type char *. Declare its type as char.

Also the function name Shift is confusing. You could name it for example like Hide or something else.

Here is a demonstration program.

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

char * Hide( char *s, char c ) 
{
    const char *delim = " ,-; .";

    for ( char *p = s  = strspn( s, delim ); *p; p  = strspn( p, delim ) )
    {
        char *q = p;
        p  = strcspn( p, delim );

        char *tmp = q;
        while ( tmp != p && *tmp != c )   tmp;

        if ( tmp != p )
        {
            for ( ; q != p;   q ) *q = '*';
        }

    }

    return s;

}

int main( void ) 
{
    char s[] = "I love my cocktail";

    puts(s);

    puts( Hide( s, 'o' ) );
}

The program output is

I love my cocktail
I **** my ********

The for loop

for ( ; q != p;   q ) *q = '*';

within the function can be rewritten as a call of memset

memset( q, '*', p - q );

CodePudding user response:

Here is a simpler alternative:

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

char *Shift(char *str, char *let) {
    size_t pos = 0, pos1, pos2;

    for (;;) {
        pos  = strcspn(str   pos, let);
        if (str[pos] == '\0')
            break;
        for (pos1 = pos; pos1 > 0 && isalpha((unsigned char)str[pos1 - 1]))
             str[--pos1] = '*';
        while (isalpha((unsigned char)str[pos])
            str[pos  ] = '*';
    }
    return str;
}

int main() {
    char s[] = "I love my cocktail";
    puts(Shift(s, "o"));
    return 0;
}
  • Related