2

我正在编写一个简单的 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 中)没有任何反应,只打印空白。

谢谢

4

3 回答 3

5

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

#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

希望能帮助到你。

于 2013-10-27T22:59:12.273 回答
3

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

#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);

在这方面更加明确。

于 2013-10-27T23:56:00.777 回答
2

在这里,您显然想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避免对交换字符使用临时存储变量的技巧(^CXOR中的运算符)

于 2013-10-27T22:34:23.537 回答