#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define SUCCESS 0
#define FAILURE -1
int str_rev(char **s, char **d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(**s != '\0'){
**s++;count++;
}
while(count > 0){
**d++ = **s--;count--;
}
**d = '\0';
return SUCCESS;
}
}
int main(){
int ret_val = SUCCESS;
char *a = "angus";
char *b;
b = malloc((strlen(a) * sizeof(*a)) + 1);
ret_val = str_rev(&a,&b);
if(ret_val == FAILURE){
printf("\n String is not reversed! going to quit! \n");
free(b);
return FAILURE;
}
printf("\n b:%s \n",b);
free(b);
return SUCCESS;
}
我正在编写一个简单的程序而不使用预定义函数进行字符串反转。但这会引发我的分段错误。我相信我正在访问正确的内存地址。
编辑:
#include<stdio.h>
#include<malloc.h>
#include<string.h>
#define SUCCESS 0
#define FAILURE -1
int str_rev(char *s, char **d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
s++;count++;
}
s--;
while(count > 0){
printf("\n *s:%c \n",*s); // prints the values correctly in the reverse order
*(*d)++ = *s--;count--;
printf("\n **d:%c \n",*((*d)-1)); // doesnt print the values, after the assignement
}
**d = '\0';
printf("\n s:%s *d:%s \n",s,*d); // both s and d doesnt print the values copied
return SUCCESS;
}
}
int main(){
int ret_val = SUCCESS;
char *a = "angus";
char *b,*x;
b = malloc((strlen(a) * sizeof(*a)) + 1);
x = b;
if(b == NULL){
}
ret_val = str_rev(a,&b);
if(ret_val == FAILURE){
printf("\n String is not reversed! going to quit! \n");
free(b);
return FAILURE;
}
printf("\n b:%s \n",b);
free(b);
return SUCCESS;
}
我改变了上面的代码,因为'a'包含字符串。因此,单个指针足以指向该位置,因为不需要进行任何更改。但即使经过上述更改,'s'中的内容也不会被复制到'd'。打印“printf(”\ n b:%s \ n“,b)后,我遇到了一个段错误;”
答案 0 :(得分:4)
除了内存分配问题,您的代码中还存在第二个问题:
<强>第一强>
复制循环后:
while(count > 0){
**d++ = **s--;count--;
}
您不会终止d
字符串ny null
添加
**d= '\0';
第一次循环后第二次
while(**s != '\0'){
**s++;count++;
}
你从Null do目的地复制第一个字符变为'\ 0'然后如何使用%s
打印
你应该递减s
以指回最后一个char而不是null char。按--s
。
第三次
内存分配如下:
char *a = "angus";
char *b;
b = malloc(strlen(a)*sizeof(*a) + 1);
不要忘记b
<强>四强>
接下来,您忘记从return SUCCESS;
str_rev()
Firth
你是将指针传递给指针,该指针在调用函数时改变了b
和's'值。当您使用&s
致电并修改s
时,没有字符串指向“angus”字符串。
如下所示,我使用单指针编码您的逻辑。
int str_rev(char *s, char *d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
s++;
count++;
}
count;
--s;
while(count > 0){
*d = *s;
// printf("\n %c %c", *d, *s);
d++ ;
s--;
count--;
}
*d = '\0';
}
return SUCCESS;
}
在主要呼叫中:
ret_val = str_rev(a, b);
我注意到你对我使用单指针两者的建议不满意!
在你的第二个(EDIT)中有一些重复错误:
(1):从功能str_rev()
再次忘记return SUCCESS
。
(2): str_rcv函数的语法是int str_rev(char *s, char **d)
,第一个参数是char*
,但在main()
中,您将其称为ret_val = str_rev(&a,&b);
,这是错误的指针分配不兼容。你应该打电话给:
ret_val = str_rev(a, &b);
(3):对您而言重要:在第二个参数中,您正在传递&b
在str_rev()
函数中,您正在更新d
指针因此更新{您通过b
分配了内存的{1}},您不能这样做!
这也会导致错误:malloc()
你应该纠正你的代码,如下所示:(请阅读评论)
memory clobbered before allocated block
(4):虽然我以前的代码也可以使用新版本:
b = malloc((strlen(a) * sizeof(*a)) + 1);
if(b == NULL){
return FAILURE; // added this line too
}
char* x = b; // first assign b to x, notice x and b are of
// same type char*
ret_val = str_rev(a,&x); // know pass &x instead of &b
主要功能():
#define SUCCESS 0
#define FAILURE -1
int str_rev(char *s, char **d){
int count = 0;
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
s++;count++;
}
s--;
while(count > 0){
*(*d)++ = *s--;
printf("\n *s:%c And **d: %c\n",*(s+1), *((*d)-1)); // for bug finding
// because s decremented and d incremented
count--;
}
**d = '\0';
return 0;
}
}
其工作输出是:
int main(){
int ret_val = SUCCESS;
char *a = "angus";
char *b;
b = malloc((strlen(a) * sizeof(*a)) + 1);
if(b == NULL){
return -1;
}
char* x = b;
ret_val = str_rev(a,&x);
if(ret_val == FAILURE){
printf("\n String is not reversed! going to quit! \n");
free(b);
return FAILURE;
}
printf("\n b:%s \n",b);
free(b);
return SUCCESS;
}
答案 1 :(得分:3)
下面:
**s++
您正在递增char **
s
。这会将其改为指向您的程序中没有意义的下一个char *
。
由于运算符优先级,**s++
与(*(*(s++))
相同。也就是说,它返回char
指向的char *
所指向的s
的值,并作为副作用递增s
指向'next'char *
(由于你没有char *
的数组,所以没有明确定义。
C字符串操作中的典型习惯用法是*p++
,与(*(p++))
相同。这将返回char
指向的p
的值,并将副作用设置为p
以指向下一个char
,这将是字符串中的下一个字符。要对char **
进行相同操作,必须写*(*p)++
,或更明确地(*((*p)++))
。
此外,没有必要使用char **
来反转字符串;它只能用char *
s。
答案 2 :(得分:1)
在这一行
b = malloc(sizeof(b));
sizeof(b)
只是一个指针的大小,并不适合整个字符串。
将您想要的大小传递给malloc
b = malloc(42);
b = malloc(strlen(a) + 1);
或将b
更改为数组而不是指针
char b[42];
除此之外,我强烈建议学习使用像gdb或valgrind这样的工具来调试这些分段错误。至少他们会告诉你什么行是segfaulting,这将有很大的帮助。
答案 3 :(得分:0)
将ret = str_rev(&a,&b);
更改为ret_val = str_rev(&a,&b);
答案 4 :(得分:0)
请找到以下重新设计的功能
int str_rev(char **sinp, char **dout){
int count = 0;
char *s = *sinp; // Dereference the starting address of source
char *d = *dout; // Dereference the starting address of destination
if(s == NULL || d == NULL){
printf("\n Invalid address received! \n");
return FAILURE;
}
else{
while(*s != '\0'){
*s++;count++;
}
s--; // Requires a decrement as it is pointing to NULL
while(count > 0){
*d++ = *s--;
count--;
}
}
*d = '\0'; // Need a NULL terminator to convert it to string
return SUCCESS; // Requires a return as all branches of function should return values
}
答案 5 :(得分:0)
char str[] = "hello";
char *foo = foo;
*foo++
相当于*(foo++)
,而不是(*foo)++
。 foo++
导致foo指向下一个char
。
char str[] = "hello";
char *foo = str;
char **bar = &foo;
**bar++
相当于**(bar++);
,而不是(**bar)++
。 bar++
导致栏指向下一个char *
...你看到了问题吗?
(*bar)++
会导致foo指向下一个char
。在ret_val = str_rev(&a,&b);
,(*s)++;
和(*d)++
中考虑您对来电者的a和b变量所做的事情。