- ベストアンサー
malloc関数について質問です。
整数を入力してその分だけ動的にメモリを確保し、その後文字列を入力して確保した領域に格納し、表示するプログラムなんですが、 int main(void) { int n; char *p; puts("整数を入力"); scanf("%d", &n); p = malloc(sizeof(char) *(n+1)); puts("文字を入力"); scanf("%s", p); printf("文字列は%s\n", p); free(p); return 0; } としたら、ちゃんとプログラムは動くんですが、 問題の意図にあっているんでしょうか?
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
mallocの使い方の例文としてはあっていると思います。 でも、実用のプログラムとしては不合格です。 この差は、基本的なエラー処理ができているかどうかです。 まず、mallocの呼び出しですが、意図通りの領域が確保できている限りは、そのままでちゃんと動きます。 でも、何らかの事情で領域が確保できなかったとき(たとえば、入力した数値が巨大だったとか、OSと環境の都合でメモリー領域に空きがなかったとか・・・まぁ様々な理由でmallocは失敗します。)、この関数はnullを返します。 あなたのプログラムのままですと、このとき、pにnullが入りますから、scanf(%s,p)のところで、nullアドレスへの書き込みが発生しますから、運がよければランタイムエラーで落ちます。運が悪ければ何が起こっても文句はつけられませんという状況になります。 mallocの次の行に、 if (p == null) { /* エラーの表示とプログラムの終了 */ } を必ず入れるようにしましょう。 次に、scanf("%s", p); のところですが、これはちょっと問題があります。 このプログラムを使った人が、問題文に合わせて、最初に入力した数字以下の文字数の文字を入力してくれている間は問題ありません。でも、ソフトを作るときには、「使う人は、自分の思う以外の入力をするかもしれない」と考えて作るのが基本です。「人が入力した値は決して信用してはいけない」とも言います。 もし、入力した整数より大きな文字列を入力したらどうなるでしょう。もちろん、pの領域をはみ出して文字列が格納されますから、その結果は未定義です。(これをバッファオーバーフローと言います。この手のエラーがあると、これを利用して、システムを乗っ取ろうとする輩が多数発生します(笑)) これを解決するのは、実は、少々骨です。この類の文字列の入力には、基本的に、scanfの使用は向いていないと言うのが実は結論です。たとえば、getcで一文字ずつ文字を受け入れ、バッファの大きさになるか、リターンキーが入力されるまでループするとかいうのが基本かなと思います。 ほかにもたとえば、 ・負の整数を入力されたらどうなるでしょう? ・整数が0だったら? ・整数と指定しているのに、「abc」と入力する人が出れば? などが考えられます。 この解消策は、自分で一度考えてみてください。
その他の回答 (4)
- JaritenCat
- ベストアンサー率37% (122/322)
こんな感じ? #include <stdio.h> #include <stdlib.h> /* malloc free */ int main(void) { int i,n,ch; char *s; /* メモリ確保 */ puts("確保する文字数"); scanf("%d%*[^\n]%*c",&n); /* 数字のあと改行まで読み飛ばして改行を捨てる */ if (n<1) { puts("out of range"); return -1; } if ((s=malloc(n+1))==NULL) { /* 終端文字の分までメモリ確保 */ puts("malloc error"); return -1; } /* 文字入力して表示 */ puts("文字を入力してください"); for (i=0; i<n; i++) { /* 確保した分まで読み込む */ ch=getchar(); if (ch==EOF || ch=='\n') break; /* エラーか改行なら終わり */ s[i]=ch; } s[i]='\0'; /* 文字の最後 */ printf("[%s]",s); /* メモリ開放 */ free(s); return 0; }
- TT414
- ベストアンサー率18% (72/384)
>整数を入力してその分だけ動的にメモリを確保し、 とあるので、 >malloc(sizeof(char) *(n+1)); はまずいのではないでしょうか? その分だけとあるのにn+1としています。一個余分に確保しています。
- jacta
- ベストアンサー率26% (845/3158)
エラーチェックはともかく、scanf("%s", p);とすると空白類文字の入力ができなくなります。
- asuncion
- ベストアンサー率33% (2127/6289)
必要なヘッダーファイルをインクルードしてくださいね。 nの値と、入力文字列の長さとの組み合わせによっては、 正しく動くこともあったり(この場合は問題の意図に合っているといえるでしょう)、 たまたま動いているように見えてどこかの領域を壊していることもあったり、 はたまたプログラムが落ちてしまうことがあったりするかもしれません。