EAccessViolationクラス例外
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();
}
投稿日時 - 2010-12-11 23:45:39
> 文字列のコピーを作りたかったので、char* tmp="";等と初期化してやってみてどうしてもうまく行きませんでした
ANo.4 でも書きましたが,この場合 tmp (が指している先)を書き換えてはいけません。
(const char* tmp=""; とすべき)
コピー元の文字列(終端のナル文字含む)を格納するのに十分なサイズのコピー先を自分で用意してやる必要があります。
const char *src = "abcd"; // コピー元
char dst[256]; // コピー先
strcpy(dst, src); // src (が指している先にある文字列)を dst にコピー
投稿日時 - 2010-12-13 21:58:24
度々の回答ありがとうございます。
>ANo.4 でも書きましたが,この場合 tmp (が指している先)を書き換えてはいけません。
>(const char* tmp=""; とすべき)
char dst[256];
strcpy(dst, src);
とすると正常に目的の結果が得られました。
ポインタはこういうものだと理解しておきます。
投稿日時 - 2010-12-14 01:42:54
このQ&Aは役に立ちましたか?
0人が「このQ&Aが役に立った」と投票しています
回答(5)
他にもまずいところがあって,
char* s="abcd";
と宣言した場合,s の内容を書き換えてはいけません。
char s[] = "abcd";
なら OK。
# 文字列の先頭と末尾から,文字単位で入れ替えていけば,
# 文字列のコピーを作らなくても大丈夫ですよ。
投稿日時 - 2010-12-12 13:22:49
ありがとうございます。
文字列のコピーを作りたかったので、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:48
tmpが参照するべき実体がありません。
実体がないので
> *(tmp+i)=*(s+len-1-i);
は「どことも知れないメモリ」にアクセスしようとします。結果としてOS側で不正なメモリアクセスを検知して例外を送出します。
あと、どうでもいい部類には入りますが、
> *(tmp+len)=NULL;
「ヌルポインタ(NULL)」と「ヌル文字('\0')」は(C++の範疇では)同じ値を示しますが、概念としては別モノです。
文字列終端のヌル文字の代用にNULLを使うのは避けた方がいいでしょう。
投稿日時 - 2010-12-12 11:56:03
ありがとうございます。
>>「ヌルポインタ(NULL)」と「ヌル文字('\0')」は(C++の範疇では)同じ値を示しますが、
>>概念としては別モノです。
>>文字列終端のヌル文字の代用にNULLを使うのは避けた方がいいでしょう。
まだポインタの概念を良く理解してない為、参考にさせていただきます。
投稿日時 - 2010-12-13 12:42:37
# ご参考: 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';
}
投稿日時 - 2010-12-12 08:05:32
ありがとうございます。
勉強中なのでrevrese()は知りませんでしたが、うまく行きました。
revrese()無しでもやってみます。
投稿日時 - 2010-12-13 12:38:27