在C中交换字符串

时间:2018-07-09 18:05:55

标签: c string swap

我有一个小问题,我不能交换我的字符串,但我有错误总线,并且只能在连接ft_strrev时使用。我认为这是因为我的弦无法停止。 Ty

#include <stdio.h>

char *ft_strrev(char *str)
{
    int i;
    int a;
    int temp;

    i = 0;
    a = 0;

    while(str[a] != '\0')
    {
        a++;
    }

    printf ("%i\n", a);

    while(i < a  / 2 && a < 0)
    {
        temp = str[a - i - 1];
        str[a - i - 1] = str[i];
        str[i]= temp;
        i++;
        printf ("%c\n", str[i]);
    }
    return (str);
}

int main()
{
    printf("TestString");
    printf("%s", ft_strrev("TestString"));
    return (0);
}

3 个答案:

答案 0 :(得分:1)

虽然您不能将字符串文字 "TestString"传递给ft_strrev,但是在C99 +中,您可以传递复合文字,例如(char[]){"TestString"}

字符串文字,例如"TestString"是在只读内存中创建的(通常在可执行文件的.rodata部分中)任何尝试修改只读数据的尝试都会调用 Undefined Behavior >如您所见。

复合文字,允许转换为创建 array 并允许修改的数组。

ft_strrev中,虽然获取字符串长度的循环很好,但请理解结果索引-是 nul-termination 字符的索引-后来尝试通过在交换期间在整个1str的索引中 temp来解决。避免痛苦,只需在开始交换之前从1中减去a。例如,一个方便的地方将是:

printf ("%i\n", a--);

有了第一个字符的索引和最后一个字符的索引,循环逻辑简化为:

    while (i < a) {
        ...
        i++, a--;
    }

(您也可以简单地使用指向第一个和最后一个字符的指针,而不是使用数组索引-但这完全取决于您)

简化事情,并在格式字符串中添加几个'\n',这样您的输出就不会全部混在一起,并且您的程序符合POSIX(输出最终的'\n'),您可以执行以下:

#include <stdio.h>

char *ft_strrev(char *str)
{
    int i = 0,
        a = 0;

    while (str[a])
        a++;

    printf ("%i\n", a--);

    while (i < a) {
        char temp = str[i];
        str[i] = str[a];
        str[a]= temp;
        i++, a--;
    }

    return str;
}

int main (void)
{
    printf ("TestString\n");
    printf ("%s\n", ft_strrev ((char[]){"TestString"}));

    return 0;
}

(您还应该在if (str != NULL)的开头检查ft_strrev

使用/输出示例

$ ./bin/cmplitrev
TestString
10
gnirtStseT

话虽这么说,虽然 compound-literal 可以100%使用-除非您熟悉它,否则它不是最易读的内容,因此,最好只声明一个字符即可main()中的数组,并将数组作为参数传递给ft_strrev

答案 1 :(得分:0)

您有2个主要错误。

while-loop中的第一名,应该是a > 0您爱上了a < 0

其次,通过调用ft_strrev("TestString"),您将传递无法编辑的 String常量。这将产生一个Segmentation Fault。因此,您需要为此动态分配内存。

解决方案:-

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

char *ft_strrev(char *st)
{
    int i;
    int a;
    char temp, *str;

    str = (char *)malloc(sizeof(st)); // allocating memory.
    strcpy(str, st);                  // copying string.
    i = 0;
    a = 0;

    while (str[a] != '\0')
    {
        a++;
    }

    printf("%i\n", a);

    while (i < a / 2 && a > 0) // not a < 0
    {
        temp = str[a - i - 1];
        str[a - i - 1] = str[i];
        str[i] = temp;
        i++;
        printf("%c\n", str[i]);
    }
    return (str);
}
int main()
{
    printf("TestString");
    printf("%s", ft_strrev("TestString"));
    return (0);
}

输出:-

TestString10
e
s
t
S
S
gnirtStseT

答案 2 :(得分:0)

  

我无法交换我的字符串,但总线有错误。...

由于功能while

中的ft_strrev()循环条件,您在问题中发布的程序无法给出总线错误
while(i < a  / 2 && a < 0) 
                    ^^^^^

假设变量a包含输入字符串“ TestString”的大小,即10,并且10 < 0将始终返回false。因此,控制永远都不会进入while循环的内部,在您尝试修改str的同时反转输入字符串(即字符串文字)时,您会尝试在其中进行修改。

以下答案基于这样的假设:在发布有问题的程序时,您输入了错误,正确的条件是a > 0而不是a < 0

您的程序正在使用undefined behavior,因为您试图修改字符串文字。您正在将字符串文字传递给函数ft_strrev()

printf("%s", ft_strrev("TestString"));  // here "TestString" is a string literal

并在功能ft_strrev()中反转输入字符串时,在while循环块中,您试图修改输入字符串。

未定义的行为包括程序可能无法编译,或者程序执行不正确(崩溃或无声地生成不正确的结果),或者可能偶然地确实满足了程序员的意图。

要解决此问题,您可以动态分配内存,然后将字符串文字复制到该内存中并反转。完成后,在这里您需要照顾释放动态分配的内存。

另一种解决方案是从字符串文字初始化数组,如下所示:

int main() {
    char arr[] = "TestString"; // initializing array with string literal
    printf("%s\n", arr);
    printf("%s\n", ft_strrev(arr));
    return 0;
}

声明

char arr[] = "TestString";

等效于

char arr[] = {'T','e','s','t','S','t','r','i','n','g','\0'};

此外,您不需要为数组提供维度。基于初始化程序,编译器将自动设置尺寸。

此数组arr是一个本地数组,您可以根据逻辑来修改它的值以反转字符串。

因此,与其直接将字符串文字传递给ft_strrev()函数,还不如使用main()中的数组 [与我上面演示的相同] 并在{{1}中进行更正}函数ft_strrev()循环条件

while

尝试这两个更改。如果您有任何疑问,请告诉我。