我正在学习C,我正在尝试使用指针来反转字符串。 (我知道你可以使用一个数组;这更多的是学习指针。)
尝试运行下面的代码时,我一直遇到分段错误。 GCC似乎不喜欢*end = *begin;
行。 为什么?
特别是因为我的代码几乎与the non-evil C function already discussed in another question
相同#include <stdio.h>
#include <string.h>
void my_strrev(char* begin){
char temp;
char* end;
end = begin + strlen(begin) - 1;
while(end>begin){
temp = *end;
*end = *begin;
*begin = temp;
end--;
begin++;
}
}
main(){
char *string = "foobar";
my_strrev(string);
printf("%s", string);
}
答案 0 :(得分:19)
传递给函数的参数存在一个问题:
char *string = "foobar";
这是在只读部分中分配的静态字符串。当您尝试使用
覆盖它时*end = *begin;
你会得到段错误。
尝试
char string[] = "foobar";
你应该注意到一个区别。
关键是在第一种情况下,字符串存在于只读段中,只使用指向它的指针,而在第二种情况下,在堆栈上保留具有适当大小的字符数组并且静态string(始终存在)被复制到其中。之后,您可以自由修改数组的内容。
答案 1 :(得分:5)
您还可以利用字符串末尾的空字符来交换字符串中的字符,从而避免使用任何额外的空格。这是代码:
#include <stdio.h>
void reverse(char *str){
int length=0,i=0;
while(str[i++]!='\0')
length++;
for(i=0;i<length/2;i++){
str[length]=str[i];
str[i]=str[length-i-1];
str[length-i-1]=str[length];
}
str[length]='\0';
}
int main(int argc, char *argv[]){
reverse(argv[1]);
return 0;
}
答案 2 :(得分:4)
在您的代码中,您有以下内容:
*end--;
*begin++;
这只是纯粹的运气,这是正确的事情(实际上,原因是运营商优先)。看起来你打算让代码真正做到
(*end)--;
(*begin)++;
哪个是完全错误的。你拥有它的方式,操作发生在
end
,然后取消引用begin
然后取消引用在这两种情况下,取消引用都是多余的,应该删除。您可能希望行为
end--;
begin++;
这些是推动开发人员瘫痪的因素,因为他们很难追查。
答案 3 :(得分:3)
这将使用指针
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void reve(char *s)
{
for(char *end = s + (strlen(s) - 1); end > s ; --end, ++s)
{
(*s) ^= (*end);
(*end) ^= (*s);
(*s) ^= (*end);
}
}
int main(void)
{
char *c = malloc(sizeof(char *) * 250);
scanf("%s", c);
reve(c);
printf("\nReverse String %s", c);
}
答案 4 :(得分:2)
将char *string = "foobar";
更改为char string[] = "foobar";
。问题是char *
指向只读内存然后尝试修改导致分段错误。
答案 5 :(得分:0)
这是我的原地C字符串反转版本。
#include <stdio.h>
#include <string.h>
int main (int argc, const char * argv[])
{
char str[] = "foobar";
printf("String:%s\n", str);
int len = (int)strlen(str);
printf("Lenth of str: %d\n" , len);
int i = 0, j = len - 1;
while(i < j){
char temp = str[i];
str[i] = str[j];
str[j] = temp;
i++;
j--;
}
printf("Reverse of String:%s\n", str);
return 0;
}
答案 6 :(得分:0)
这产生了一个小的(ish)递归函数,它的工作原理是将值存储在堆栈的路上,并在返回(返回)的路上将指针递增到字符串的开头(* s)。
看起来很聪明的代码但在堆栈使用方面很糟糕。
#include <stdio.h>
char *reverse_r(char val, char *s, char *n)
{
if (*n)
s = reverse_r(*n, s, n+1);
*s = val;
return s+1;
}
int main(int argc, char *argv[])
{
char *aString;
if (argc < 2)
{
printf("Usage: RSIP <string>\n");
return 0;
}
aString = argv[1];
printf("String to reverse: %s\n", aString );
reverse_r(*aString, aString, aString+1);
printf("Reversed String: %s\n", aString );
return 0;
}
答案 7 :(得分:0)
下面,您可以看到我的问题代码:
#include <string>
#include <iostream>
char* strRev(char* str)
{
char *first,*last;
if (!str || !*str)
return str;
size_t len = strlen(str);
for (first = str, last = &str[len] - 1; first < last ; first++, last--)
{
str[len] = *first;
*first = *last;
*last = str[len];
}
str[len] = '\0';
return str;
}
int main()
{
char test[13] = "A new string";
std::cout << strRev(test) << std::endl;
return 0;
}