質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

776閲覧

C言語 realloc関数に関する質問

Alyn

総合スコア50

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/08/22 13:44

編集2018/08/22 13:55

質問内容

入力文字数制限なしで文字を入力していくプログラムを作っています。
デバックなしで実行で、文字列中に数値以外が含まれる入力を3,4回繰り返すと全く動かなくなりました。
どこで止まったのか調べたところ29行目のrealloc(number, i + 2);で止まってました。
ちなみにデバックで実行したところ問題なく動作しました。

realloc関数、malloc関数、free関数は使ったことがなく、何がおかしいのかもわかりません。
このプログラムをどう書き直したらエラーや停止状態にならなくできるのか教えてください。

※CheckNumber関数は省略しています。

該当のソースコード

C言語

1#include <stdio.h> 2#include <stdlib.h> 3 4int CheckNumber(char *); // 文字列に数字だけが含まれている時に1を返す。それ以外は0。 5 6void main() 7{ 8 char *number = 0; 9 char c = 0; 10 int jdg = 0; 11 int i = 0; 12 13 while (jdg != 1) 14 { 15 printf("数値を入力してください。\n"); 16 printf("> "); 17 18 number = (char *)malloc(1); 19 jdg = 0; 20 i = 0; 21 22 while (1) 23 { 24 c = getchar(); 25 26 if (c != '\n') 27 { 28 *(number + i) = c; 29 realloc(number, i + 2); //ここで止まってました 30 i++; 31 } 32 else 33 { 34 *(number + i) = '\0'; 35 break; 36 } 37 } 38 39 if (*(number + 0) != '\0') 40 { 41 jdg = CheckNumber(number); 42 if (jdg == 0) 43 { 44 printf("\n数値以外が入力されています。\n"); 45 free(number); 46 } 47 } 48 else 49 { 50 printf("\n数字を入力されていません。\n"); 51 free(number); 52 } 53 } 54 55 printf("入力された数字は %s です。\n", number); 56 free(number); 57}

エラーメッセージ

Expression:_CrtlsValidHeapPointer(block) ※エラーメッセージの有無は環境によって異なるようで、エラーメッセージが出るものと出ないものがあるようです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

既に回答がついていますが、一応、、、。

realloc()関数はあまり使った事が無いので、調べてみました。
この辺の解説が分かり易いでしょうか。 realloc関数
(MS サイトは、怪しい日本語だった)

realloc(number, i + 2); //ここで止まってました

こんな感じでしょうか。

C

1 // 適当なところで、 char *old_buff; を宣言 2 old_buff = number; 3 number = realloc(number, i + 2); 4 if (number == NULL) { 5 // 確保失敗。 なんかのエラー処理 6 // free(old_buff); exit(1); 7 }

あと、ポインタですが、

*(number + i) = c; => number[i] = c;

とした方が、見易いと思いますが、どうでしょうか。

投稿2018/08/22 14:35

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Alyn

2018/08/22 14:39

if (number == NULL)はどういった時に実行される処理なのでしょうか? 私のソースコードにも加えるべきでしょうか?
pepperleaf

2018/08/22 14:46

realloc()でのメモリ割り当てが失敗した場合です。 この程度のコードだと発生する可能性は低いですが、エラー処理として必要と思います。
Alyn

2018/08/22 14:49

number = (char *)realloc(number, i+2); if (number == NULL){ free(number); } ですか?
pepperleaf

2018/08/22 14:50

free()するは良いですが、そのデータは使えませんので、異常終了として、プログラムを終了すべきかと思います。
Alyn

2018/08/22 15:04

異常終了ということもあるのですね。 if文の中身はgoto以外で終了されるにはどうしたらよいでしょうか?
guest

0

ベストアンサー

reallocは割当てなおした新しいポインタを返すのでそちらで上書きしないとダメです。

number = realloc(number, i+2);

この処理をおこたり古いアドレスを使い続けてしまうと
書き込んではいけないとこに書き込んでしまいます。

投稿2018/08/22 13:50

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Alyn

2018/08/22 14:18 編集

ありがとうございます。 キャストしたnumber = (char *)realloc(number, i+2);でよろしいのでしょうか? またmalloc関数、free関数に誤りはありませんか?
asm

2018/08/22 20:55

C++ではキャストが必要ですが、C言語の場合はvoid*は任意のポインタ型にキャストなしで代入できます。 malloc/freeに誤りはありませんが、 強いていえば、運用としてメモリの割当というのは若干時間の掛かる処理なので 1バイトずつ増やして再割り当てしていくのは無駄に感じます。 C++にはstd::vectorという可変長配列があり そちらでは割り当ててある容量を超えると、容量を2倍に増やす感じで実装される事が多いです。
Alyn

2018/08/22 23:16

ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問