我有一个小问题,我不能交换我的字符串,但我有错误总线,并且只能在连接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);
}
答案 0 :(得分:1)
虽然您不能将字符串文字 "TestString"
传递给ft_strrev
,但是在C99 +中,您可以传递复合文字,例如(char[]){"TestString"}
。
字符串文字,例如"TestString"
是在只读内存中创建的(通常在可执行文件的.rodata
部分中)任何尝试修改只读数据的尝试都会调用 Undefined Behavior >如您所见。
复合文字,允许转换为创建 array 并允许修改的数组。
在ft_strrev
中,虽然获取字符串长度的循环很好,但请理解结果索引-是 nul-termination 字符的索引-后来尝试通过在交换期间在整个1
和str
的索引中减 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
尝试这两个更改。如果您有任何疑问,请告诉我。