【问题标题】:How to reverse a string with pointers only?如何仅使用指针反转字符串?
【发布时间】:2021-01-14 00:17:25
【问题描述】:

我正在尝试反转一个字符串,但它保持不变。除了<string.h><stdio.h>,我不使用任何模块。

void rev(s){
    char i, temp;
    char *sf = s;
    char ri = strlen((s) - 1);
    char *sl = &s[ri];
    for (i = 0; i < ri; i++){
        if (*sf != *sl){
            temp = *sf++;
            s[i] = *sl--; //
            s[ri--] = temp; //those two seems to be getting new characters, but it won't
        }
        else {
            ri--;
            sf++;
            sl--;
        }
    }
    printf("%s", s);
}

【问题讨论】:

  • 你试过用笔和纸运行你的程序吗?
  • @Deno 函数不能编译。
  • char ri = strlen((s1) - 1); 是做什么的?没有名为 s1 的变量。
  • 不要反转整个字符串,反转一半。
  • strlen((s) - 1) 当然应该读作strlen(s) - 1

标签: c char reverse c-strings function-definition


【解决方案1】:

函数不会编译,至少因为参数没有类型说明符。

void rev(s){

char 类型的可接受值范围很小。所以你不能用它来计算字符串的长度。

此声明中strlen的调用

char ri = strlen((s) - 1);

调用未定义的行为。看来你的意思

char ri = strlen(s) - 1; 

也可以为空字符串调用未定义的行为。

这个循环

for (i = 0; i < ri; i++){

不使用指针。

该函数可以通过以下方式定义,如下面的演示程序所示。

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

char * reverse( char *s )
{
    if ( *s )
    {
        for ( char *first = s, *last = s + strlen( s ); first < --last; ++first )
        {
            char c = *first;
            *first = *last;
            *last = c;
        }
    }
    
    return s;
}

int main( void ) 
{
    char s1[] = "1";
    char s2[] = "12";
    char s3[] = "123";
    
    puts( reverse( s1 ) );
    puts( reverse( s2 ) );
    puts( reverse( s3 ) );
}   

程序输出是

1
21
321

【讨论】:

  • @P__J__ 我没明白你的意思。谁说它好?
  • @P__J__ 还有一个我不明白你的意思。在我的回答中,一切都写得很清楚。所以你的 cmets 不会掩盖感觉。
  • 他只是说(我认为)您正在创建并使用char 变量来读取strlen() 的返回值,(在此语句中:char ri = strlen(s) - 1;)当strlen() 返回时size_t。但是你已经知道了,所以我不确定你在玩什么。
  • @P__J__ 是的,我现在明白了。误读为if ( s )
【解决方案2】:

一个简单的解决方案:

char *sl = sf;
while (*sl != 0)
    ++ sl;
-- sl; 
while (sf < sl)
{
    char c = *sf;
    *sf = *sl;
    *sl = c;

    ++sf, --sl;
}

通过跳过所有字符直到找到 NUL(零)字符来查找字符串的结尾。
然后后退一个字符(递减sl),这样你就有了指向字符串的第一个和最后一个字符的指针。

然后将两个指针移向另一个并交换字符,直到指针相遇或交叉。

【讨论】:

  • 嗯,将 --sl 放在 for 循环的 init 部分看起来很混乱,即使它是正确的
  • @klutt 已更改。
  • 更好,但这实际上有一个错误。对于空字符串,这将导致 UB,因为 --sl 将是 sf - 1。您可以通过在--sf 之前的某处添加if(*sf == '\0') return sf 来解决此问题。在 while 循环之前或之后。
【解决方案3】:

您的代码有很多问题(错误?):

char ri = strlen((s) - 1); 必须是 size_t ri = strlen((s)) - 1;

其他代码很难分析,因为您使用的不是自我解释的变量名称。

这里的代码更简单,更容易分析。

char *reverseString(char *str)
{
    char *wrk = str, *end;
    if(str && *str)
    {
        end = str + strlen(str) - 1;
        while(end > wrk)
        {
            char temp = *wrk;
            *wrk++ = *end;
            *end-- = temp;
        }
    }
    return str;
}


int main(void)
{
    char str[] = "1234567890";
    printf("reversed: %s\n", reverseString(str));
}

【讨论】:

  • 我觉得你应该解释一下为什么if(str &amp;&amp; *str)不能被if(str)代替
  • 如果字符串为空,则调用 strlen 没有任何意义。
  • 嗯,这是真的,但这不是为什么有必要这样做的原因。
  • 一个元素之前?你确定吗?我知道一个元素 AFTER 是可以的,但不是一个元素之前。
  • 据我所知,你错了。您的函数会为空字符串调用 UB,而无需额外的 &amp;&amp; *str,我提出它的原因是阅读此内容的人很容易相信您可以安全地删除它。
猜你喜欢
  • 1970-01-01
  • 2012-05-05
  • 1970-01-01
  • 1970-01-01
  • 2012-06-26
  • 1970-01-01
  • 2015-10-19
相关资源
最近更新 更多