-2

Code is crash unexpectedly, any logical error in this code?

Purpose of this code is to reverse the string.

When I try to debug the code, the issue seems in the strrev function. But could not catch up with the exact issue.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *s[]={"To err is hman..",
"man is wild",
"Dream big thought",
"do it myself self",
};
void xstrrev(char *a1,char *a2,char *a3,char *a4)
{
   strrev(a1);
   strrev(a2);
   strrev(a3);
   strrev(a4);
}
int main()
{
 for(int i=0;i<4;i++)
    {
        printf("%s\n",s[i]);
    }

    printf("Hello world!\n");
    xstrrev(s[0],s[1],s[2],s[3]);
    for(int i=0;i<4;i++)
    {
        printf("%s\n",s[i]);
    }
    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Jonson
  • 7
  • 4

3 Answers3

1

This declaration

char *s[]={"To err is hman..",
"man is wild",
"Dream big thought",
"do it myself self",
};

declares an array of pointers to string literals. Though in C (opposite to C++) string literals have types of non-constant character arrays nevertheless you may not change string literals. Any attempt to change a string literal results in undefined behavior.

Instead of the array of pointers declare a two-dimensional character array like

char s[][18] = 
{
    "To err is hman..",
    "man is wild",
    "Dream big thought",
    "do it myself self",
};

Pay attention to that the function strrev is not a standard C function.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
1

I assume strrev takes a char * pointer to a null-terminated string and reverses the order of the char elememts of the string in place. That means that it cannot be used to reverse a string literal because modification of a string literal results in undefined behavior.

OP's array s contains pointers to string literals that are passed to strrev, resulting in undefined behavior. To prevent that, the code needs to be changed so that the array s contains pointers to modifiable strings. That can be done either by creating each string as a named array of char, or by constructing each string as an anonymous compound literal.

Version using named arrays of char:

static char s_0[] = "To err is hman..";
static char s_1[] = "man is wild";
static char s_2[] = "Dream big thought";
static char s_3[] = "do it myself self";
char *s[] = { s_0, s_1, s_2, s_3 };

Version using compound literals:

char *s[] = {
    (char []){ "To err is hman.." },
    (char []){ "man is wild" },
    (char []){ "Dream big thought" },
    (char []){ "do it myself self" },
};

In both of the cases above, the string literals are only being used to initialized arrays of char that are modifiable. The pointers in array s point to these modifiable arrays of char, so there is no problem passing them to strrev.


Regarding strrev, that function is not defined by the C standard, but it might be an extended standard library function of some implementation. All function names beginning with str, mem, or wcs are reserved by the C standard.

Ian Abbott
  • 15,083
  • 19
  • 33
0

Well as @Vlad from Moscow and @kaylum mentioned, that you can't modify the content of an array of pointers to string literals, so rather than that you can do it with allocation, as shown in the below code :

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void    ft_strrev(char *str)
{
    char    keep;
    int     len;
    int     i;
    int     stop;

    len = strlen(str);
    stop = len / 2;
    i = 0;
    while (len > stop)
    {
        keep = str[i];
        str[i] = str[len - 1];
        str[len - 1] = keep;
        i++;
        len--;
    }
}

void xstrrev(char *a1,char *a2,char *a3,char *a4)
{
   ft_strrev(a1);
   ft_strrev(a2);
   ft_strrev(a3);
   ft_strrev(a4);
}
int main()
{
    char    **s;

    s = calloc(sizeof(char*), 5);
    s[0] = strdup("To err is hman..");
    s[1] = strdup("man is wild");
    s[2] = strdup("Dream big thought");
    s[3] = strdup("do it myself self");

 for(int i=0;i<4;i++)
    {
        printf("%s\n",s[i]);
    }

    printf("Hello world!\n");
    xstrrev(s[0],s[1],s[2],s[3]);
    for(int i=0;i<4;i++)
    {
        printf("%s\n",s[i]);
    }
    return 0;
}

and since I can't use strrev() function with my compiler, because This is a non-standard function that works only with older versions of Microsoft C, I did my own reverse function ft_strrev.

Holy semicolon
  • 868
  • 1
  • 11
  • 27