C 字符串反转

Posted

技术标签:

【中文标题】C 字符串反转【英文标题】:C String Reversed 【发布时间】:2013-10-27 22:19:56 【问题描述】:

我正在编写一个简单的 c 程序来反转字符串,从 argv[1] 中获取字符串。代码如下:

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

char* flip_string(char *string)
    int i = strlen(string);
    int j = 0;

    // Doesn't really matter all I wanted was the same size string for temp.
    char* temp = string;
    puts("This is the original string");
    puts(string);
    puts("This is the \"temp\" string");
    puts(temp);

    for(i; i>=0; i--)
        temp[j] = string[i]
        if (j <= strlen(string)) 
            j++;
        
    

    return(temp);


int main(int argc, char *argv[])
    puts(flip_string(argv[1]));
    printf("This is the end of the program\n");

基本上就是这样,程序编译和一切,但最后不返回临时字符串(只是空格)。一开始,当它等于字符串时,它会很好地打印温度。此外,如果我在 for 循环中逐个字符地执行 temp 的 printf ,则会打印出正确的临时字符串,即字符串 -> 反转。就在我尝试将其打印到标准输出(在 for 循环之后/或在 main 中)时,什么也没有发生,只打印空格。

谢谢

【问题讨论】:

我也在 Ubuntu 论坛上写过这篇文章,但认为这更像是一个一般性的编码问题。 你知道tempstring 指向同一个内存位置吗? 别忘了接受 WhozCraig 的回答,这是做你想做的事的正确方法。干净整洁。 次要问题:不要在循环内长度不变的字符串上一遍又一遍地调用 strlen()。调用一次并存储结果。然后在循环中使用存储的值。 【参考方案1】:

您在尝试使用指针时朝着正确的方向前进。只要多想一点,你可能就会有它。下面是一个安全的实现:

#include <stdio.h>

char *flip_string(char *str)

    char *lhs = str, *rhs = str;
    if (!str || !*str || !*(str+1))
        return str;

    while (*++rhs); // rhs to eos
    while (lhs < --rhs)
    
        char tmp = *lhs;
        *lhs++ = *rhs;
        *rhs = tmp;
    
    return str;


int main()

    char test1[] = "Hello, World!";
    char test2[] = "";
    char test3[] = "1";
    printf("%s, %s, %s\n", flip_string(test1), flip_string(test2), flip_string(test3));
    return 0;

输出

!dlroW ,olleH, , 1

希望对你有帮助。

【讨论】:

可能值得指出char[]char* 之间的重要区别。在这种情况下,它会复制字符串,否则它将是未定义的行为。 我认为让flip_string 就地反转返回参数很烦人。看过printf 行的人可能不会想到flip_string 实际上也修改它的论点。实现这个想法意味着您不再需要保留原始的str 指针,因此您可以使用它进行遍历,保存一个局部变量。 @FrerichRaabe 我同意。无论出于何种原因,这都是明显的要求。如果不是这样,我会按照你的描述去做;只需使用str 即可升级。当然,所有这些对于 mb-chars 来说都是完全失败的,例如,当然不限于 utf8。【参考方案2】:

您的函数似乎在执行“就地反转”,即它替换了内存中的给定字符串。这样做时,请确保不要将尾随零移动到前面。下面是函数的简单实现

#include <assert.h>
#include <string.h>

void flip_string(char *s)

    assert(s);
    char *t = strchr(s, '\0') - 1;
    for (; s < t; ++s, --t) 
        char tmp = *s;
        *s = *t;
        *t = tmp;
    

函数断言它得到一个字符串(即不是空指针)并且内存是可写的。然后它设置一个t 指针指向字符串的最后一个字符——通过strchr 执行此操作而不是编写手动循环的好处是strchr 通常是一个高度优化的函数,它不会遍历单字节步骤中的字符串,而是一次考虑四个甚至更多字节。它也可以说更具表现力。

然后,主循环交换 st 引用的字符(即最初的第一个和最后一个字符),然后向前/向后移动指针直到它们相遇。

函数更简洁一点,因为它不需要保留传入的原始指针,而是可以直接修改s。这是决定一个函数应该要么修改它的参数返回一个新值的结果——但不能两者兼而有之。两者都做意味着你可以像这样调用函数

printf("%s", flip_string(s));

...这将完全掩盖 s 实际被修改的情况。

flip_string(s);
printf("%s", s);

在这方面更加明确。

【讨论】:

【参考方案3】:

在这里,您显然希望 temp 成为除 string 之外的其他变量。但是你做的初始化会导致两个指针指向同一个位置。

你应该做的是:

char *flip_string(const char *string)

    char *tmp = NULL;
    size_t len = strlen(string);
    int i = 0;
    /*
     * Don't forget that strlen() returns the length of the string
     * **WITHOUT** counting the ending '\0' character.
     * Thus, you have to add the extra space when you're allocating
     */
    if (!(tmp = malloc(len + 1))) 
        printf("Allocation failed ...\n");
        return NULL;
    
    /*
     * The newly created string must have an ending character
     * Which is '\0'
     */

    tmp[len] = '\0';

    /*
     * Here, you want to reverse the "true content" of your string.
     * That is why you ignore the ending '\0' of the string by
     * setting the upper bound to strlen (with a strict '<') **AND**
     * it is also the reason a '- 1' just pops in the index choice.
     */
    for(i = 0; i < len; i++) 
        tmp[i] = string[len - i - 1];
    
    return tmp;

正如 WhozCraig 所强调的,有一种替代解决方案,它可以简单地修改参数字符串而不需要分配内存:

void flip_string(char *s)

    size_t len = strlen(s);
    char *p = s + len - 1;
    while (s < p) 
        *p ^= *s;
        *s ^= *p;
        *p ^= *s;
        p--;
        s++;
    

注意XOR 技巧,以避免对交换的字符使用临时存储变量(^C 中的XOR 运算符)

【讨论】:

你可以,但我没有。没有理由完全分配内存来反转标准的以零结尾的字符串。只需要两个指针和一个 while 循环(如果你想独立于 strlen() 则需要两个)。 @WhozCraig,你应该发布它,你的回答应该比我的更有启发性(这里没有讽刺意味!)。 你们太棒了。谢谢! 另外,sizeof(char) 始终为 1。(对于 NULL 检查来说,这是一种奇怪的语法......)除此之外,我不喜欢 XOR 交换。 第二个版本有问题,使用了异或技巧,这里没有必要。

以上是关于C 字符串反转的主要内容,如果未能解决你的问题,请参考以下文章

C语言问题:字符串(单词)反转,例如:I am boy,反转为 I ma yob 简单实用,指针操作

C 字符串反转

反转字符串c ++中的单词[重复]

为啥这个字符串反转 C 代码会导致分段错误? [复制]

如何用JS实现字符串反转

c----反转字符串