• 締切済み

コンパイルはできるのですが

C++入門者です。C言語の範疇です。 コンパイルはできるのですが、実行すると ”問題が発生したため、*****.exe を終了します。 ご不便をおかけして申し訳ありません。” というウィンドウがででしまします。 どこで誤っているのかわからなくて困っています。 どなたかご教授願えないでしょうか。 どうかよろしくお願いいたします。 -----プログラム内容です。----- #include<iostream> using namespace std; int main() { char *s1 ,*s2; cin >> s1; for (int i=0;i <= strlen(s1)-1;i++) { *(s2+i) = *(s1 + strlen(s1) - 1 - i); } *(s2+strlen(s1)) = '\0'; cout << s1 << '\n'; cout << *(s2) << '\n'; return 0; } --------------------------------------

みんなの回答

  • otn
  • ベストアンサー率66% (14/21)
回答No.2

プログラムでポインタを使用していますが、まずはポインタと変数の違いを説明したいと思います。 ポインタとは簡単に言うと実体(変数以外に関数等の場所も指定できます)の場所を指定するものです。 アスタリスクをつけることで中身をのぞいたり書き込んだりすることができるのですが、最初にやらなければならないのは場所(変数や関数の実体のアドレス)の指定です。つまりアドレスを指定しないポインタやNULLポインタをいきなり使ってはいけないのです。 ポインタのアドレス代入には実体を直接指すものと動的確保があります。 実体を直接指す例としては、 char a[10]; char *ap; ap = a; がそれにあたります。この代入の場合どちらもポインタのように見えますが、右辺は &a[0] の省略系(このように書いてもコンパイルは通ります。)になっています。実体とポインタの最大の違いはアドレスを変更することができないということです。(ap++と言うコードはOKだけどa++というコードはコンパイルエラーになる) そして動的確保ですが、これはアドレスが決まっていないポインタに対してアドレスとサイズを決定して先頭アドレスを返してくれるものです。 C言語では calloc(),malloc()、C++では new 等がそれにあたります。この場合プログラム実行時にアドレスとサイズが決定されるため、自動的に解放を行うことができません。従って解放するというコードを自分で書かなければならないのです。(動的確保には必ず対で解放の命令が存在します。)もし、解放せずにEXEを終了させるとその確保した場所はロックがかかったままになり、他のアプリが使用できる状態にならなくなります。これをメモリリークと言います。 また、動的確保で絶対にやってはいけないのが確保後にアドレスを変更することです。例えばこんな感じです。 char *a; a = new char[256]; a++; // <-アドレスを変更している delete [] a; // 1byteだけ解放されない また、これも駄目な例です。 a = new char[256]; a = new char[300];// <- 解放する前に変更してしまった delete [] a; // これでは前行の解放ができない これもメモリリークと言います。 元がポインタであるため、アドレスの変更が許されるのでこのようなコードが書けます。これを解決するには確保した変数は絶対にいじらず別のポインタを用意するか、[]を使ってアクセスします。 char *a; char *b; a = new char[256]; b = a; b[100] = '0'; b++; // これは全く問題ない *b = '\n'; delete [] a; // 正しく解放できる 最後にポインタと配列が全く別物と言われているのは、ポインタは配列のように書けますが、配列はポインタのようには書けないというところにあります。

jeffmills
質問者

お礼

周りに聞ける人間がいないのでダメ元で初めて投稿してみたのですが、正直驚いています。 ご親切に、ちょうど私のレベルに必要な知識をご教授いただけました。本当にありがとうございました。

回答No.1

char *の変数s1,s2をnew演算子等で領域確保を行っください。 修正後のプログラムを書いておきます。 なお、確保する容量は(プログラム上256)は 必要であれば増やしてください。 #include<iostream> using namespace std; int main() { char *s1 ,*s2; // ここから s1 = new char[256]; s2 = new char[256]; // ここまで追加 cin >> s1; for (int i=0;i <= strlen(s1)-1;i++) { *(s2+i) = *(s1 + strlen(s1) - 1 - i); } *(s2+strlen(s1)) = '\0'; cout << s1 << '\n'; cout << *(s2) << '\n'; // ここから delete []s1; delete []s2; // ここまで追加 return 0; }

jeffmills
質問者

お礼

malloc()のようなものなんですね。基礎がなくてお恥ずかしい限りです。 簡潔に的確なアドバイスをいただきありがとうございました。感謝いたします。