-2

I'm writing this code to reverse the string, but somehow the last printf() seems can not print out the update string. I want to know why.

#include <stdio.h>

int main() {
    char x[] = "abcdefghijklmn";
    int j = sizeof(x);
    int i = 0;
    char t = 'a';
    printf("%s,%i\n", x, j / 2);

    for (; i < j / 2; i++) {
        t = x[i];
        x[i] = x[j - i - 1];
        x[j - i - 1] = t;
        printf("%c,%i,%i\n", x[i], i, j - i - 1);
    }

    printf("%s\n", x);

    return 0;
}

【LET ME SUMMARIZE】Thank you guys, after reading all your answers, I've rewrite the code, which is quite clear to show the difference between sizeof() and strlen(), also it was a simpler way to reverse your string. check it and leave your comment if you want.

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

void StringReverse(char *s) {
        int i = 0;
        int j = strlen(s) - 1;
        printf("sizeof:%i,strlen:%i\n",sizeof(s),strlen(s));
        for (; i < j + 1; i++)
            printf("%c", s[j - i]);
    }

int main() {
    char x[] = "abcdefghijklmn";
    printf("sizeof:%i,strlen:%i\n",sizeof(x),strlen(x));
    StringReverse(x);

    return 0;
}

The result is :

sizeof:15,strlen:14
sizeof:4,strlen:14
nmlkjihgfedcba

Then check this:

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

void StringReverse(char *s) {
        int i = 0;
        int j = strlen(s) - 1;
        printf("sizeof:%i,strlen:%i\n",sizeof(s),strlen(s));
        for (; i < j + 1; i++)
            printf("%c", s[j - i]);
    }

int main() {
    char x[100];
    puts("Input a tring to reverse:");
    fgets(x,100,stdin);

    printf("sizeof:%i,strlen:%i\n",sizeof(x),strlen(x));
    StringReverse(x);

    return 0;
}

And the result is:

Input a tring to reverse:
abcdefghijklmn
sizeof:100,strlen:15
sizeof:4,strlen:15

nmlkjihgfedcba

It is clear now that strlen() alway try to give the real length of the string, but why the first length is 14, the second input way it is 15?

sizeof() is defined by the number you put in the char x[] ,always include EOS;

and pointer variable to a string, sizeof() always return the pointer length instead of the string length.

【Thanks to @David C. Rankin】Your code reminds me that array variable is always used as a pointer to be passed to the function, so the original string is always not preserved no matter you use common function(first code below) or pointer to funtion(second code below). Correct?

first:

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

    void StringReverse(char *s) {
                int i = 0;
                int j = strlen(s);
                printf("sizeof:%i,strlen:%i\n",sizeof(s),strlen(s));

                char t = 'a';
                    for (; i < j / 2; i++) {
                        t = s[i];
                        s[i] = s[j - i - 1];
                        s[j - i - 1] = t;
                    }

                printf("%s\n", s);
            }

        int main() {
            char x[]="abcdefghijklmn";

/* if you instead write char *x="abcdefghijklmn"; here 
the compiler will encounter error, because a pointer to 
a 【string literal】 can not be used to modify the string.
*/ 
            printf("sizeof:%i,strlen:%i\n",sizeof(x),strlen(x));
            StringReverse(x);
            printf("\n%s\n", x);  //original string x is not preserved.
            return 0;
        }

the result is:

sizeof:15,strlen:14
sizeof:4,strlen:14
nmlkjihgfedcba

nmlkjihgfedcba

second:

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

char *StringReverse(char *s) {
    int i = 0;
    int j = strlen(s);
    printf("sizeof:%i,strlrn:%i\n", sizeof(s), strlen(s));

    char t = 'a';
    for (; i < j / 2; i++) {
        t = s[i];
        s[i] = s[j - i - 2];
        s[j - i - 2] = t;
    }

    return s;
}

int main() {
    char x[100];
    puts("Input a tring to reverse:");
    fgets(x, 100, stdin);

    printf("sizeof:%i,strlrn:%i\n", sizeof(x), strlen(x));
    StringReverse(x);

    printf("\n%s\n", x);  //original string x is not preserved.

    return 0;
}

the result is:

Input a tring to reverse:
abcdefghijklmn
sizeof:100,strlrn:15
sizeof:4,strlrn:15

nmlkjihgfedcba

So if you want to preserve the original string, you have to use some other way:

...to be continue

Lee William
  • 125
  • 1
  • 11

6 Answers6

1

Lee, I'm glad you enjoyed the project. You can learn a lot from taking the time to really understand basic pointer, character and memory operations involved in seemingly simple tasks. I enjoyed looking through your final version. Here are a few more for you to digest and compare. See if you can tease out the proper use of each:

A void version

(hint: pass pointers to beginning and ending characters of the range of characters to be reversed)

/** strreverse - reverse string given by begin and end pointers.
 *  Takes valid string and swaps src & dest each iteration.
 *  The original string is not preserved.
 *  If str is not valid, no action taken.
 */
void strreverse (char *begin, char *end)
{
    char tmp;

    if (!begin || !end) {
        printf ("%s() Error: invalid begin or end\n", __func__);
        return;
    }

    while (end > begin)
    {
        tmp = *end;
        *end-- = *begin;
        *begin++ = tmp;
    }
}

A char* version modifying the original

/** strrevstr - reverse string, swaps src & dest each iteration.
 *  Takes valid string and reverses, original is not preserved.
 *  If str is valid, returns pointer to str, NULL otherwise.
 */
char *strrevstr (char *str)
{
    if (!str) {
        printf ("%s() Error: invalid string\n", __func__);
        return NULL;
    }

    char *begin = str;
    char *end = str + strlen (str) - 1;
    char tmp;

    while (end > begin)
    {
        tmp = *end;
        *end-- = *begin;
        *begin++ = tmp;
    }

    return str;
}

A char* version that preserves (copies) the original

/** strrevdup - reverse duplicate string, swaps src & dest each iteration.
 *  Takes valid string, duplicates and reverses, original is preserved.
 *  Returns pointer to reversed string on success, NULL otherwise.
 *  Requires string.h, caller is responsible for freeing memory allocated.
 */
char *strrevdup (char* str)
{
    if (!str) {
        printf ("%s() Error: invalid string\n", __func__);
        return NULL;
    }

    char *rstr = strdup (str);
    char *begin = rstr;
    char *end = rstr + strlen (rstr) - 1;
    char tmp;

    while (end > begin){
        tmp=*end;
        *end-- = *begin;
        *begin++ = tmp;
    }

    return rstr;
}
David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
0

The issue in your code is with the usage of sizeof() operator. The way you use

int j = sizeof(x);

is not correct in this context. What you want here is to make use of strlen() function from string.h header file.

Case 1:

sizeof() operator returns the size of the datatype. x is an array of chars, and when initalized with the string literal "abcdefghijklmn", it takes 15 chars. [14 alphabet + 1 terminating null.] to store the value.

Thus, sizeof(x) will return 15.

Case 2:

OTOH, strlen() does not count the terminating null, so strlen(x) will return 14.

Next, as we know, array index in C are 0-based, that means an array consisting of n elements, will have index running from 0 to n-1.

So, in case 1, while using the value j-1, we're referring to the terminating null, which will be copied and put to the 0th index, essentially marking the end of the string. So,l while printing out the reversed array as a string, the very first element, beinh null, marks the end of the string and doesn't output anything.

OTOH< in case 2, using the value j-1, we're referring to the last alphanbetic char value present in the array x which will be copied to the 0th index. The copying will continue this way and we'll have a reversed string in pace.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
0

Just change this line

int j = sizeof(x);

To

int j = sizeof(x)-1;

As sizeof(x) will return 15 (14 array characters and 1 null character).
where as array index is from 0 to 13.

when i=0; and as j is 15.

x[i] = x[j - i - 1]; //x[0] = x[15-0-1]; i.e x[14] which is NULL.

As x[14] is null character which is assign to x[0].
So while printing the string it getting null character at first place which is termination of string, That is why it is not giving any output.

I will always prefer to use strlen to get length of the string as it will not include null character.
In second thought you can also use

int j = strlen(x);  // this will return 14.

use "string.h" header file to use this function.

Himanshu
  • 4,327
  • 16
  • 31
  • 39
  • Using `sizeof` will only work if there is no slack space in the array. For example, with `char x[10]="abc";` it will fail. See answer from @SouravGhosh. – Weather Vane Apr 03 '15 at 10:42
  • @WeatherVane, it is better to use `strlen` for these type of conditions. but as OP asked question using `sizeof` without providing any array limit, so i given this answer. I will prefer `strlen` over `sizeof`. – Himanshu Apr 03 '15 at 10:46
  • what do you mean by : Using sizeof will only work if there is no slack space in the array. – Lee William Apr 03 '15 at 12:15
  • @LeeWilliam, No you are getting it wrong, I said in this question, there is no slack space in array. `sizeof` will work in both cases. – Himanshu Apr 03 '15 at 12:24
  • I understand now but usually I put no number when declare char x[]="sabsdjkaskdnks"; so sizeof will always return the correct size. – Lee William Apr 03 '15 at 12:29
  • @LeeWilliam, yes you are right and example given by you `x[10]="abc";` , shows in this case `sizeof` will fail to work as required. so i edited my answer and added line to use `strlen` function. – Himanshu Apr 03 '15 at 12:34
0

try to print reversed string like that:

for (i = 1; i < sizeof(x); i++) 
    printf("%c", x[i]);

instead of:

 printf("%s\n", x);
Sun Dro
  • 581
  • 4
  • 9
0

The last char of the array is '\0',can not reverse it

#include <stdio.h>

int main() {
    char x[] = "abcdefghijklmn";
    int j = sizeof(x);
    int i = 0;
    char t = 'a';
    printf("%s,%i\n", x, j / 2);

    for (; i < j / 2; i++) {
        t = x[i];
        x[i] = x[j - i - 2];
        x[j - i - 2] = t;
        printf("%c,%i,%i\n", x[i], i, j - i - 2);
    }

    printf("%s\n", x);

    return 0;
}
kiviak
  • 1,083
  • 9
  • 10
0

sizeof() will return the value with null terminating byte. It will lead to that run a loop one iteration extra.

So change that into like this,

int j=sizeof(x)-1;

Or else use the strlen function.

Include the header file #include<string.h>

int j=strlen(x);
Karthikeyan.R.S
  • 3,991
  • 1
  • 19
  • 31