c中的字符串反转

时间:2013-03-09 03:30:46

标签: c

#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)后,我遇到了一个段错误;”

6 个答案:

答案 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

的free()内存

<强>四
接下来,您忘记从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):对您而言重要:在第二个参数中,您正在传递&bstr_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;
}

Here your running code at Codpad

答案 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变量所做的事情。