dポイントプレゼントキャンペーン実施中!

WindowsXPでBCB5を使用しています。
柴田望洋氏著、新版明解C++入門編の演習8-14ですが
「文字列sの文字の並びを反転する関数str_rvsを作成せよ。
char* str_rvs(char* s);
たとえば、文字列sが"abc"であれば、その文字列を"cba"に更新する。受け取ったsの値をそのまま返却すること。」
と言う問題で、下記の様に作成したんですが、
char* s="a"、または"ab"、または"abc"とすると正常に終了しますが
"abcd"とすると、

文字列[abcd]を反転します。
dcba
文字列[dcba]を反転します。
abcd

が繰り返された後、「EAccessViolationクラスの例外を生成しました。~」が表示されて停止します。
s="abcde"とすると

文字列[abcde]を反転します。
edcba

と1回表示されて、同様のエラーが発生しますが、何が悪いのかわかりません。ご教授願います。

//---------------------
#include <iostream>
#include <cstring>
using namespace std;

char* str_rvs(char* s){
int len=strlen(s);
char* tmp;

for(int i=0;i<len;i++)
*(tmp+i)=*(s+len-1-i);
*(tmp+len)=NULL;

for(int i=0;i<len;i++)
*(s+i)=*(tmp+i);

return s;
}

int main(){
char* s="abcd";

cout << "文字列[" << s << "]を反転します。\n";
cout << str_rvs(s) << '\n';

//getchar();
}

A 回答 (5件)

> 文字列のコピーを作りたかったので、char* tmp="";等と初期化してやってみてどうしてもうまく行きませんでした



ANo.4 でも書きましたが,この場合 tmp (が指している先)を書き換えてはいけません。
(const char* tmp=""; とすべき)

コピー元の文字列(終端のナル文字含む)を格納するのに十分なサイズのコピー先を自分で用意してやる必要があります。

const char *src = "abcd"; // コピー元
char dst[256];         // コピー先

strcpy(dst, src);  // src (が指している先にある文字列)を dst にコピー
    • good
    • 0
この回答へのお礼

度々の回答ありがとうございます。

>ANo.4 でも書きましたが,この場合 tmp (が指している先)を書き換えてはいけません。
>(const char* tmp=""; とすべき)


char dst[256];
strcpy(dst, src);
とすると正常に目的の結果が得られました。  
ポインタはこういうものだと理解しておきます。

お礼日時:2010/12/14 01:42

他にもまずいところがあって,


 char* s="abcd";
と宣言した場合,s の内容を書き換えてはいけません。
 char s[] = "abcd";
なら OK。


# 文字列の先頭と末尾から,文字単位で入れ替えていけば,
# 文字列のコピーを作らなくても大丈夫ですよ。
    • good
    • 0
この回答へのお礼

ありがとうございます。

文字列のコピーを作りたかったので、char* tmp="";等と初期化してやってみてどうしてもうまく行きませんでしたが、おっしゃられる通り
char tmp;
for(int i=0;i<=(len/2-1);i++){
tmp=*(s+i);
*(s+i)=*(s+len-1-i);
*(s+len-1-i)=tmp;
}
として、文字単位で入れ替えてみると正常に終了しました。

お礼日時:2010/12/13 12:48

tmpが参照するべき実体がありません。



実体がないので

> *(tmp+i)=*(s+len-1-i);

は「どことも知れないメモリ」にアクセスしようとします。結果としてOS側で不正なメモリアクセスを検知して例外を送出します。

あと、どうでもいい部類には入りますが、

> *(tmp+len)=NULL;

「ヌルポインタ(NULL)」と「ヌル文字('\0')」は(C++の範疇では)同じ値を示しますが、概念としては別モノです。
文字列終端のヌル文字の代用にNULLを使うのは避けた方がいいでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございます。

>>「ヌルポインタ(NULL)」と「ヌル文字('\0')」は(C++の範疇では)同じ値を示しますが、
>>概念としては別モノです。
>>文字列終端のヌル文字の代用にNULLを使うのは避けた方がいいでしょう。

まだポインタの概念を良く理解してない為、参考にさせていただきます。

お礼日時:2010/12/13 12:42

# ご参考: C++なんだからそんなものわざわざ自作せんでも...



#include <iostream>
#include <cstring>
#include <algorithm> // 追加

using namespace std;

char* str_rvs(char* s){
 std::reverse(s, s+strlen(s)); // これでオシマイ
 return s;
}

int main(){
 char s[] = "abcd";
 cout << "文字列[" << s << "]を反転します。\n";
 cout << str_rvs(s) << '\n';
}
    • good
    • 0
この回答へのお礼

ありがとうございます。
勉強中なのでrevrese()は知りませんでしたが、うまく行きました。
revrese()無しでもやってみます。

お礼日時:2010/12/13 12:38

tmpが領域確保されてないのに、未初期化のままデレファレンスしてるからでは。



詳しいことは、他の人が回答してくれるかと。
    • good
    • 0
この回答へのお礼

ありがとうございます。他の人の回答も参考にさせていただきます。

お礼日時:2010/12/13 12:36

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!