请帮我检查C中的字符串反转代码?

请帮我检查C中的字符串反转代码?,c,string,C,String,我写这段代码是为了反转字符串,但是最后一个printf()似乎无法打印出更新字符串。我想知道为什么 #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++) {

我写这段代码是为了反转字符串,但是最后一个
printf()
似乎无法打印出更新字符串。我想知道为什么

#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;
}
结果是:

sizeof:15,strlen:14
sizeof:4,strlen:14
nmlkjihgfedcba
然后检查以下内容:

#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;
}
现在很清楚,
strlen()
总是试图给出字符串的实际长度,但是为什么第一个长度是14,第二个输入方式是15

sizeof()
由您在字符x[]中输入的数字定义,始终包括EOS

和指向字符串的指针变量,
sizeof()
始终返回指针长度而不是字符串长度

【感谢@David C.Rankin】您的代码提醒我,数组变量总是用作传递给函数的指针,因此无论您使用公共函数(下面的第一个代码)还是指向函数的指针(下面的第二个代码),原始字符串总是保留。对吗

第一:

    #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;
        }
第二:

#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;
}
因此,如果要保留原始字符串,必须使用其他方法:


…要继续

代码中的问题是如何使用
sizeof()
运算符。你使用的方式

int j = sizeof(x);
在这种情况下是不正确的。这里需要使用
string.h
头文件中的
strlen()
函数

案例1:

sizeof()
运算符返回数据类型的大小
x
是字符的数组,当使用字符串literal
“abcdefghijklmn”
初始化时,需要
15
char
s。[14字母+1终止null.]以存储值

因此,
sizeof(x)
将返回
15

案例2:

OTOH,
strlen()
不计算终止null,因此
strlen(x)
将返回
14

接下来,我们知道,
C
中的数组索引是基于
0的
,这意味着由
n
元素组成的数组的索引将从
0
n-1

因此,在案例1中,当使用值
j-1
时,我们指的是终止null,它将被复制并放入
0
th索引,基本上标记字符串的结尾。因此,l在将反转数组打印为字符串时,第一个元素beinh null标记字符串的结尾,不输出任何内容

OTOH<在案例2中,使用值
j-1
,我们指的是数组
x
中存在的最后一个alphanbetic
char
值,它将被复制到
0
第四个索引中。复制将以这种方式继续,我们将有一个反向的字符串

int j = sizeof(x);

As
sizeof(x)
将返回15(14个数组字符和1个空字符)。
其中,as数组索引为0到13

i=0时和as
j
为15

x[i] = x[j - i - 1]; //x[0] = x[15-0-1]; i.e x[14] which is NULL.
As
x[14]
是分配给
x[0]
的空字符
所以,当打印字符串时,它首先得到空字符,这是字符串的终止,这就是它不提供任何输出的原因

我总是喜欢使用strlen来获取字符串的长度,因为它不包含空字符。
再想一想,你也可以使用

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

使用“string.h”头文件来使用此函数。

尝试打印反转的字符串,如下所示:

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

数组的最后一个字符是“\0”,无法将其反转

#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;
}
#包括
int main(){
字符x[]=“abcdefghijklmn”;
int j=sizeof(x);
int i=0;
chart='a';
printf(“%s,%i\n”,x,j/2);
对于(;i
sizeof()
将返回带有
null
终止字节的值。这将导致额外运行一次循环

把它变成这样

int j=sizeof(x)-1;
或者使用
strlen
功能

包含头文件
#包含


李,我很高兴你喜欢这个项目。花时间真正理解看似简单的任务所涉及的基本指针、字符和内存操作,可以学到很多东西。我喜欢看你的最终版本。这里还有一些供您消化和比较的内容。看看你是否能梳理出每一种方法的正确用法:

无效版本

(提示:将指针传递到要反转的字符范围的开始字符和结束字符)

A
char*
版本修改原始版本

/** 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;
}
/** 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;
}
保留(复制)原件的
char*
版本

/** 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;
}
/** 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;
}

sizeof vs.strlen问题可能?
sizeof(x)
include EOS(
'\0'
)您可能希望阅读此处,然后自己尝试调试此类问题。我认为这不是sizeof问题,我没有在指针变量上使用它。可能应该是j-i-2而不是j-i-1?只有在阵列中没有空闲空间时,才可能重复使用
sizeof
。例如,使用
charx[10]=“abc”它将失败。请参阅@SouravGhosh@WeatherVane的答案,对于此类情况,最好使用
strlen
。但正如OP在没有提供任何数组限制的情况下使用
sizeof
提问一样,我给出了这个答案。我更喜欢
strlen
而不是
sizeof
。你的意思是:只有当数组中没有空闲空间时,使用sizeof才会起作用。@leewillam,不,你弄错了,我在这个问题中说,数组中没有空闲空间
sizeof
在这两种情况下都可以使用。我现在明白了,但通常在声明char x[]=“sabsdjkaskdnks”时我不输入数字;因此sizeof将始终返回正确的大小。
#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;
}
int j=sizeof(x)-1;
int j=strlen(x);
/** 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;
    }
}
/** 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;
}
/** 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;
}