【问题标题】:reverse string in c using pointers使用指针在c中反转字符串
【发布时间】:2018-06-24 22:34:25
【问题描述】:

我正在尝试使用指针反转字符串,但它似乎不起作用,有什么问题?输出是olllo,但应该是olleh

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


void reverse(char *cadena){

    size_t len = strlen(cadena);
    char *end= cadena;
    char *aux = cadena;
    while(*++end){}
    --end; //end points to a

    for(;len;--len){
        *aux++ = *end--;

    }

}

int main()
{

    char buffer[] = "hello";
    reverse(buffer);
    printf("%s",buffer);


    return 0;
}

【问题讨论】:

  • 你的for循环坏了;你应该交换每个字符对并且只运行到字符串的一半。
  • 而且你真的不需要两个循环来完成这个任务
  • @SHG 是正确的,你可以直接使用长度来计算 end。 char *end= cadena + (len - 1);

标签: c string pointers reverse


【解决方案1】:

行:

*aux++ = *end--;

交换任何东西。它只是分配左侧的右侧的值。你总是会得到一个回文,由字符串的右半部分组成。对于交换逻辑,您应该这样做:

char tmp = *aux;
*aux = *end;
*end = tmp;

另外,您不应该真正遍历整个字符串。实际上,这意味着将字符串反转,然后再次将其反转。只需在迭代 仅一半 字符串时应用交换逻辑,就可以开始了:

void reverse(char *cadena) {
    if(cadena != NULL){                                 // add some checks...    
        size_t len = strlen(cadena);
        char *end = cadena + (len > 1 ? len - 1 : 0);   // ...for safety    
        char *aux = cadena;

        for (len /= 2; len; --len) {
            char tmp = *aux;
            *aux++ = *end;
            *end-- = tmp;
        }
    }
}

【讨论】:

  • 好吧,我不知道您为什么决定将 NULL 定义为 nop,我通常更喜欢快速中止以使调试更容易。但实际上并没有错。我也会尝试减少分支...
  • 对不起,这不是代码审查。这里的主要目标是展示这个想法,而不是提供最佳解决方案
【解决方案2】:

解决你的错误

您的循环的问题在于,当您尝试将字符反转到位时,您最终会交换已经交换的字符。

我将尝试通过展示每次迭代中发生的情况来解释。 你可以看到cadena 的初始内容和最终的(res)在每次迭代中每次交换之后。 | 是指针 auxend 当前指向的位置:

len = 5
aux  |  
     h e l l o
end          |
res: o e l l o

len = 4
aux    |  
     h e l l o
end        |
res: o l l l o

len = 3
aux      |  
     h e l l o
end      |
res: o l l l o

len = 2
aux        |  
     h e l l o
end    |
res: o l l l o

len = 1
aux          |  
     h e l l o
end  |
res: o l l l o

len = 0
=> break the loop

关于解决方案..

我的原位reverse 将是this one

void reverse(char *str)
{
    if (!str || !(*str)) return;

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

    while (str < end) {
        char tmp = *str;
        *str++ = *end;
        *end-- = tmp;
    }
}

一些关键点:

  • 注意使用strlen 来查找字符串的最后一个字符
  • 您应该迭代直到开始和结束指针相遇。否则你重新反转字符串

【讨论】:

  • 您在收到空字符串时也会遭受 UB 的困扰。通过重新考虑在哪里减少来解决这个问题。
  • @Deduplicator 感谢您的评论。想到了却没写出来。
【解决方案3】:

您的代码中有三个重要错误:

  1. 在此 sn-p 中前进到末尾时,您对空字符串的处理不当:

    char *end= cadena;
    // Irrelevant: char *aux = cadena;
    while(*++end){}
    --end; //end points to a
    

    无论如何,您已经有了字符串长度,所以只需添加它。

    修复此错误时,请确保仅创建有效指针,即指向对象或仅在对象后面。

  2. 您将遍历整个字符串的长度,而不是仅一半。如果您实际上交换了元素,那么您将交换所有内容两次,这是一个非常昂贵的 nop:

    for(;len;--len){
    
  3. 您是在复制而不是交换。您没有保存覆盖的值,也没有将其存储回它所属的位置。

        *aux++ = *end--;
    }
    

固定代码:

void reverse_string(char* s) {
    char* e = s + strlen(s);
    while (s < e) {
        char t = *s;
        *s++ = *--e;
        *e = t;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-15
    • 2012-05-05
    • 2020-02-20
    • 1970-01-01
    • 1970-01-01
    • 2015-10-19
    相关资源
    最近更新 更多