1
#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(”\nb:%s \n",b);”后出现段错误 .

4

6 回答 6

4

除了内存分配问题外,您的代码中还有第二个问题:

首先
在您的复制循环之后:

   while(count > 0){
    **d++ = **s--;count--;
   }

你不终止d字符串 nynull

添加

**d= '\0';

第二:在你的第一个循环之后

   while(**s != '\0'){
    **s++;count++;
   }

您从 Null 复制目标第一个字符变为 '\0' 然后如何使用打印%s

您应该递减s以指向最后一个字符而不是空字符。由--s.

第三

内存分配喜欢:

 char *a = "angus";
 char *b;
 b = malloc(strlen(a)*sizeof(*a) + 1);

不要忘记释放()内存b


下一个是你忘记 return SUCCESS;str_rev()

弗斯

您正在传递指向指针的指针,该指针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);

编辑:第二个代码

我注意到您对我对两者都使用单指针的建议不满意!

那么在你的第二个(编辑)中有一些重复的错误:

(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):对您很重要:在第二个参数中,您传递&bWhere 作为str_rev()函数,您正在更新d指针,因此更新b您通过分配内存的位置malloc(),您不能这样做!
这也会导致错误memory clobbered before allocated block

你应该纠正你的代码这样调用:(请阅读评论

 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 

(4):虽然我以前的代码也可以工作,但也可以得到新版本:

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

它的工作输出是:

 *s:s And **d: s

 *s:u And **d: u

 *s:g And **d: g

 *s:n And **d: n

 *s:a And **d: a

 b:sugna 

这是你在 Codpad 上的运行代码

于 2013-03-09T03:36:43.743 回答
3

这里:

**s++

你正在增加char ** s. 这会将其更改为指向char *在您的程序中没有意义的下一个。

由于运算符优先级,**s++与 相同(*(*(s++))。也就是说,它返回char指向 by 所char *指向的值s,并作为副作用递增s以指向“下一个” char *(它没有明确定义,因为您没有char *s的数组)。

C 字符串操作中的一个典型习惯用法是*p++,与(*(p++)). 这将返回char指向 by的值,p并且作为副作用设置p为指向 next char,这将是字符串中的下一个字符。要做同样的事情,char **必须写*(*p)++,或者更明确地说(*((*p)++))

此外,不必使用char **s 来反转字符串;只能用char *s 来完成。

于 2013-03-09T03:38:18.870 回答
1

在这一行

b = malloc(sizeof(b));

sizeof(b)只是指针的大小,不足以容纳整个字符串。

要么传递你想要 malloc 的大小

b = malloc(42);
b = malloc(strlen(a) + 1);

或更改b为数组而不是指针

char b[42];

除此之外,我强烈建议学习使用 gdb 或 valgrind 等工具来调试这些分段错误。至少他们会告诉你哪条线路出现了段错误,这将有很大帮助。

于 2013-03-09T03:35:00.933 回答
0

更改ret = str_rev(&a,&b);ret_val = str_rev(&a,&b);

于 2013-03-09T03:34:49.373 回答
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++导致 bar 指向下一个char *... 你看到问题了吗?

(*bar)++导致 foo 指向下一个char。考虑您将对调用者的 a 和 b 变量执行什么操作ret_val = str_rev(&a,&b);,(*s)++;(*d)++.

于 2013-03-09T06:03:46.940 回答
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
}
于 2013-03-09T03:57:23.380 回答