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'には文字列が含まれているため、上記のようにコードを変更しました。したがって、変更を行う必要がないため、その場所を指すには1つのポインタで十分です。ただし、上記の変更を行った後でも、「s」の内容は「d」にコピーされません。そして、 "printf(" \ nb:%s \ n "、b);"を出力した後、セグメンテーション違反が発生します。。

4

6 に答える 6

4

メモリ割り当ての問題に加えて、コードの2番目の問題もあります。

最初
にコピーループの後:

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

d文字列nyを終了しませんnull

追加

**d= '\0';

2番目:最初のループの後

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

Nullからコピーして宛先の最初の文字を「\0」にし、次に次を使用して印刷する方法%s

snull文字ではなく最後の文字を指すようにデクリメントする必要があります。によって--s

第3

メモリ割り当ては次のようになります。

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

のメモリをfree()することを忘れないでくださいb

フォーネクストはあなたがから
戻るのを忘れた return SUCCESS;str_rev()

ファース

関数を呼び出すときに、自身の値と's'の値を変更するポインタにポインタを渡しbます。で呼び出して&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);

編集:2番目のコード

両方に単一のポインタを使用するという私の提案に満足していないことに気づきました。

さてあなたの2番目(編集)にはいくつかの繰り返しエラーがあります:

(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):重要:2番目の引数で渡すのは、関数&bの場合と同様に、ポインタを更新しているため、メモリを割り当てた先を更新しているため、それを行うことはできません。 これにより、次のエラーも発生します。str_rev()dbmalloc()
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;
  }
}

main function():

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つまり、が指すの値を返し、副作用として「次へ」を指すようになります(これchar *は、の配列がないため、明確に定義されていません)。)。sschar *char *

C文字列操作の一般的なイディオムは*p++、です。これは。と同じ(*(p++))です。charこれは、によってポイントされた値を返し、p副作用pが次を指すように設定されcharます。これは、文字列内の次の文字になります。同じことを行うには、、またはより明示的にchar **書く必要があります。*(*p)++(*((*p)++))

また、文字列を逆にするためにsを使用する必要はありません。char **sだけで実行できますchar *

于 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などのツールを使用してこれらのセグメンテーション違反をデバッグすることを強くお勧めします。少なくとも、彼らはどの行がsegfaultingであるかを教えてくれ、それだけで大いに役立ちます。

于 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

以下のように作り直された関数を見つけてください

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 に答える
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ます。、およびの呼び出し元のa変数とb変数ret_val = str_rev(&a,&b);に対して何をするかを検討します。(*s)++;(*d)++

于 2013-03-09T06:03:46.940 に答える