• 締切済み

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

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

関連するQ&A

  • 改行文字について

    #include<iostream> using namespace std; int main(void) { char c; while (cin.get(c)) if (c == '\n') cout << "[RET]\n"; else cout << c; return(0); } これのif (c == '\n')の改行文字と等しいとは何のことを指すのでしょうか? よろしくお願いします。

  • コマンドプロンプトからのコンパイル

    PCに「Visual Studio .NET」が入っています。 ソフト上から↓のようなプログラムを実行する方法は友達に教えてもらったのですが コマンドプロンプトからコンパイルして実行するにはどうしたらよいのでしょうか。 よろしくお願いします。 ---------------------------- #include <iostream> using namespace std; int main() { cout << "ようこそc++へ!\n"; return 0; }

  • 配列の練習問題

    #include<iostream> using namespace std; //count関数の宣言 int count(char str[], char ch); int main() { char str[100]; char ch; cout << "文字列を入力して下さい。\n"; cin >> str; cout << "文字列から探す文字を入力して下さい。\n"; cin >> ch; int c = count(str, ch); cout << str << "の中に" << ch << "は" << c << "個あります。\n"; return 0; } //count関数の定義 int count(char str[], char ch) { int i = 0; int c = 0; while (str[i]) { if (str[i] == ch) c++; i++; } return c; } こんにちは。 この問題の解答のプログラムの意味がイマイチ解らないので良かったら教えて下さい。 確認がてらに質問します。 よろしくお願いします。

  • c++での入出力がうまくいきません;

    初心者ですが独習c++でプログラミングについて勉強している者です。 なんとか環境設定もできたと思いきや、うまくコンパイルすることができなくて困っています。具体的には、 #include <iostream> using namespace std; int main() { int i, j; double d; i = 10; j = 20; d = 99.101; cout << "値を表示: "; cout << i << ' ' << j << ' ' << d; return 0; } という値を表示するプログラムではコンパイルもうまくいったのですが、次の #include <iostream> using namespace std; int main() { int i; cout << "値を入力: "; cout >> i; cout << "入力した値: " << i << "\n"; return 0; } という入力のプログラムをコンパイルしようとすると、コマンドプロンプトに演算子が使われたクラス ostream では int型の定義が存在しないとなりコンパイルエラーとなってしまいます。 理由が考えてもわからないので、質問してみました。 どのようにすれば、このエラーを解消できるのか知りたいので、どうかご意見をよろしくお願いします。

  • 入力に出現する数字文字をカウントするプログラム

    こんにちは、毎度お世話になります。 #include<iostream> using namespace std; int main(void){ char c; int cnt[10] = {0}; while(cin.get(c)){ if(c >= '0' && c <= '9') cnt[c - '0']++; } for (int = 0; i < 10; i++) cout << i << "の出現回数:" << cnt[i] << '\n'; return(0); } [/code] ここで質問なんですが、このプログラムの中で数字文字をカウントしているのはどこでしょうか? そして while(cin.get(c)){ if(c >= '0' && c <= '9') cnt[c - '0']++; } ここの部分が何を表しているのか解りません。 よろしくお願いします。

  • プログラムの動作

    10文字をスキップするプログラムなのですが、どのようにスキップしているのかわからないので教えてください。 下にソースコードを書きます。 #include <iostream> using namespace std; //10文字をスキップする istream &skipchar(istream &stream) { int i; char c; for(i=0; i<10; i++)stream >> c; return stream; } int main() { char str[80]; cout << "いくつかの文字を入力する:"; cin >> skipchar >> str; cout << str << endl; return 0; } よろしくおねがいします。

  • MingwでC++のソースがコンパイルできない。

    質問があるのですがよろしくお願いしします。 プラットフォームは Windows HOME です。 MinGWでC++のhelloworld.cppという名前のプログラム ------ここから----------- #include <iostream> using namespace std; int main(){ cout <<"Hello World!!\n"; return 0; } -------ここまで----------- を、gcc helloworld.cpp とWindowsのコマンドプロンプトから打ってコンパイルしようとしたのですが、 undefined reference to std string::size() const undefined reference to std string::operator[](using int) const undefinrd reference to std::cout undefinrd reference to std::basic_ostream<char, std::char traits<char> >&, char const*) undefinrd reference to std::ios_base::Init::() undefinrd reference to std::ios_base::~Init::() などのエラーが出て、コンパイルできません・・ hello.cという名前のC言語プログラム --------ここから------ #include<stdio.h> int main(void){ printf("Hello GCC World on Windows!!\n"); } ------ここまで------- は、gcc hello.c で正常にコンパイルでき、生成したexeファイルも正常に動きます。 また、eclipse CDT上からc++プログラムをMinGWでコンパイルすることもできるのですが・・ なぜかWindowsのコマンドプロンプトからc++プログラムをコンパイルしようとするとエラーが出てしまいます。(C言語のプログラムでもエラーが出ることが時々あります。) どなたか詳しい方いらっしゃいましたらご教授頂けると幸いです。 よろしくお願いします。

  • 文字列検索について

    下記のようなC++プログラムにおいて、Good Morning! の「r」以後が、 検索にひっかからないで、-1を返します。 何故なのか、どうぞよろしくお願いします。 -------------------------------------------------------- #include <iostream> #include <cstring> using namespace std; int flag = 0; // 該当文字があったかどうかのフラグ int strch_idx(const char* s, char c){ int temp; cout << strlen(s) << endl; for(int i=0; i<(signed)strlen(s); i++){ if(*s == c){ temp=i+1; // 配列のインデックスは0オリジンだが、インデックスは1からだから1+する flag = 1; break; } s++; } if(flag == 1) return temp; else return -1; } int main(){ const char* s = "Good Morning!"; int idx = strch_idx(s, 'i'); cout << "検索文字のインデックス:" << idx << endl; return 0; }

  • コンパイルできるのですが実行途中でエラーが

    #include<iostream> #include<cstdlib> using namespace std; class stack{ char *stck; int tos; int size; public: stack(char c); void push(char ch); char *pop(); ~stack(); }; stack::stack(char c){ tos=0; stck=(char*)malloc(c); size=c; cout<<"生成スタック\n"; if(!stck){ cout<<"メモリ割り当てエラー\n"; exit(1); } } void stack::push(char ch){ if(tos==size){ cout<<"スタックは一杯です\n"; return; } *stck=ch; stck++; tos++; } char *stack::pop(){ if(tos==0){ cout<<"スタックは空です\n"; return 0; } stck--; tos--; return stck; } stack::~stack(){ free(stck); } int main(){ stack s1(10),s2(10); int i; char *o; s1.push('a'); s2.push('x'); s1.push('b'); s2.push('y'); s1.push('c'); s2.push('z'); for(i=0;i<5;i++){ o=s1.pop(); cout<<"s1をポップする"<<*o<<"\n"; } for(i=0;i<5;i++){ o=s2.pop(); cout<<"s2をポップする"<<*o<<"\n"; } return 0; } なんですが、実行した所 生成スタック 生成スタック s1をポップするc s1をポップするb s1をポップするa スタックは空です までで止まってしまいます。 たぶんreturn 0の戻り値の型がポインタだから止まってしまうのだろうと思います。 正しく実行するにはどうすればいいのでしょうか? お願いします。

  • 配列のプログラムですが

    #include <iostream> using namespace std; int main() { int a[100],b=-9999; int i=0,j; do { cout << "整数値を入力してください\n"; cin >> a[i]; b += a[i]; i++; }while( a[i-1] != 9999); cout << b << '\n'; for(j=0;j<i-1;j=j+1) cout << a[j] * 3 << '\n'; return 0; } このプログラムってどんな計算をしてるんですか?誰か分かる人いますか 整数値を入れてくださいって出るだけなんですが

専門家に質問してみよう