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

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

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

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

Q&A

解決済

1回答

14207閲覧

構造体配列の動的なメモリ確保の仕方を教えて下さい

dec5798

総合スコア74

C

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

0グッド

0クリップ

投稿2016/11/03 05:34

編集2016/11/03 06:26

先ほどは失礼いたしました
質問のプログラムを変えました
構造体型配列への動的メモリ確保について教えてください

前提条件:mallocかcallocの使用、構造体配列でデータを持つ事

以上の条件下で動的にメモリを確保しようと
下記プログラムを実行した所
初期値が0以外になってしまい
プログラムが誤作動を起こします。

わからない事:mallocをどのように構造体配列のデータに参照させるか
(動的メモリ確保は190行目付近に有ります)
以上ですよろしくお願い致します。

c

1 2#define _CRT_SECURE_NO_WARNINGS 3#define MAX_LINE 5 4#define MAX_DATA 50 5#define MAX_NAME_LEN 24 6#define MAX_ANOTHER_NAME_LEN 24 7#define MAX_TEL_LEN 18 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11#include <ctype.h>///////////数字判定用 12 13/* 顧客住所録構造体 */ 14typedef struct tag_CustomerData { 15 long lId; // 顧客番号 16 char szName[MAX_NAME_LEN + 1]; // 顧客名 17 char szAnotherName[MAX_NAME_LEN + 1]; // ふりがな 18 char szTel[MAX_TEL_LEN + 1]; // 電話番号 19 20} CUSTOMER_DATA; 21 22void openMenu(int nInputnum); 23void addData(CUSTOMER_DATA head[]); 24 25int main() 26{ 27 char str[128]; 28 int len; 29 int nInputnum;//////////登録の天井処理で使う 30 int i; 31 32 while (1) { 33 system("cls"); 34 printf("顧客情報がありません。何件分確保しますか?(1 - 50)"); 35 fgets(str, sizeof(str), stdin); 36 37 /* 改行文字が含まれているかの確認 */ 38 /* 改行文字を終端記号に置換する */ 39 /* else時バッファはクリアする */ 40 if (strchr(str, '\n') != NULL) { 41 str[strlen(str) - 1] = '\0'; 42 43 }else{ 44 while (getchar() != '\n'); 45 } 46 len = strlen(str); 47 48 str[0] = toupper(str[0]); 49 if (len == 1 && str[0] == 'Q') { 50 return 0; 51 } 52 /* 不正文字混入時はループを抜けるので */ 53 /* lenとiの差異で分岐させる */ 54 for (i = 0; i < len; i++) { 55 if (!(isdigit(str[i]))) { 56 break; 57 } 58 } 59 if (len == 0 || i != len) { 60 printf("<<入力範囲にありません>>"); 61 getchar(); 62 continue; 63 } 64 65 nInputnum = atoi(str); 66 if (!(nInputnum >= 1 && nInputnum <= 50)) { 67 printf("<<入力範囲にありません>>"); 68 getchar(); 69 continue; 70 } 71 openMenu(nInputnum); 72 return 0; 73 } 74} 75 76void openMenu(int nInputnum) 77{ 78 long lId = 0; 79 char str[128]; 80 int len; 81 int num; 82 int i; 83 int nCountup; 84 CUSTOMER_DATA *head; 85 86 while (1) { 87 system("cls"); 88 printf("***** 顧客情報管理 *****\n"); 89 printf("1:登録\n"); 90 printf("2:一覧表\示\n"); /* '表'文字エスケープ処理で\挿入 */ 91 printf("3:削除\n"); 92 printf("4:ファイル出力\n"); 93 printf("5:終了\n"); 94 printf("************************\n"); 95 printf("(処理区分)>"); 96 fgets(str, sizeof(str), stdin); 97 98 /* 改行文字が含まれているかの確認 */ 99 /* 改行文字を終端記号に置換する */ 100 /* else時バッファはクリアする */ 101 if (strchr(str, '\n') != NULL) { 102 str[strlen(str) - 1] = '\0'; 103 }else{ 104 while (getchar() != '\n'); 105 } 106 len = strlen(str); 107 108 /* 不正文字混入時はループを抜けるので */ 109 /* lenとiの差異で分岐させる */ 110 for (i = 0; i < len; i++) { 111 if (!(isdigit(str[i]))) { 112 break; 113 } 114 } 115 if (len == 0 || i != len) { 116 printf("<<入力した文字が不正です>>"); 117 getchar(); 118 continue; 119 } 120 num = atoi(str); 121 if (!(num >= 1 && num <= 5)) { 122 printf("<<処理区分エラー>>\n"); 123 getchar(); 124 continue; 125 } 126 switch (num) { 127 case 1: addData(head); 128 continue; 129 130 case 2: for (i = 0; i < 128; i++) { 131 if (head[i].lId != 0 && head[i].lId != -1) { 132 nCountup++; 133 }; 134 } 135 if(nCountup == 0){ 136 printf("表\示するデータがありません\n"); 137 getchar(); 138 continue; 139 } 140 showData(head, nInputnum); 141 continue; 142 143 case 3: for (i = 0; i < 128; i++) { 144 if (head[i].lId != 0 && head[i].lId != -1) { 145 nCountup++; 146 }; 147 } 148 if(nCountup == 0){ 149 printf("表\示するデータがありません\n"); 150 getchar(); 151 continue; 152 } 153 showData(head, nInputnum); 154 continue; 155 156 case 4: for (i = 0; i < 128; i++) { 157 if (head[i].lId != 0 && head[i].lId != -1) { 158 nCountup++; 159 }; 160 } 161 if(nCountup == 0){ 162 printf("表\示するデータがありません\n"); 163 getchar(); 164 continue; 165 } 166 ////////// 167 continue; 168 169 case 5: return; 170 } 171 } 172} 173 174void addData(CUSTOMER_DATA acList[]) 175{ 176 int nCountup = 0; 177 char achName[128]; 178 char achAnotherName[128]; 179 char achTel[128]; 180 int len; 181 int i; 182 183 CUSTOMER_DATA *pnL;///////////////////////////////////////////////////////////////////////////////////////////////////////////////// 184 185 if ((pnL = (CUSTOMER_DATA *)malloc(sizeof(CUSTOMER_DATA))) == NULL) { /* 記憶領域の確保 */ 186 exit(EXIT_FAILURE); 187 } 188 189 acList = pnL;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 190 191 for (i = 0; i < 128; i++) { /*0の値以外の登録済み及び */ 192 if (acList[i].lId != 0) { /*削除済みの値はカウントアップする */ 193 nCountup++; 194 }; 195 } 196 197 while (1) { 198 system("cls"); 199 printf("***** 顧客登録画面 *****\n"); 200 printf("氏名 :"); 201 202 fgets(achName, sizeof(achName), stdin); 203 if (strchr(achName, '\n') != NULL) { 204 achName[strlen(achName) - 1] = '\0'; 205 206 }else{ 207 while (getchar() != '\n'); 208 } 209 len = strlen(achName); 210 211 if (len == 0) { 212 printf("<<入力した文字が不正です>>\n"); 213 getchar(); 214 continue; 215 } 216 if (len > MAX_NAME_LEN) { 217 printf("<<入力した文字の長さが大きすぎます>>\n"); 218 getchar(); 219 continue; 220 } 221 break; 222 } 223 224 while (1) { 225 system("cls"); 226 printf("***** 顧客登録画面 *****\n"); 227 printf("氏名 :%s\n", achName); 228 printf("ふりがな:"); 229 230 fgets(achAnotherName, sizeof(achAnotherName), stdin); 231 if (strchr(achAnotherName, '\n') != NULL) { 232 achAnotherName[strlen(achAnotherName) - 1] = '\0'; 233 }else{ 234 while (getchar() != '\n'); 235 } 236 len = strlen(achAnotherName); 237 238 if (len == 0) { 239 printf("<<入力した文字が不正です>>\n"); 240 getchar(); 241 continue; 242 } 243 if (len > MAX_ANOTHER_NAME_LEN) { 244 printf("<<入力した文字の長さが大きすぎます>>\n"); 245 getchar(); 246 continue; 247 } 248 break; 249 } 250 251 while (1) { 252 system("cls"); 253 printf("***** 顧客登録画面 *****\n"); 254 printf("氏名 :%s\n", achName); 255 printf("ふりがな:%s\n", achAnotherName); 256 printf("電話番号:"); 257 258 fgets(achTel, sizeof(achTel), stdin); 259 if (strchr(achTel, '\n') != NULL) { 260 achTel[strlen(achTel) - 1] = '\0'; 261 }else{ 262 while (getchar() != '\n'); 263 } 264 len = strlen(achTel); 265 266 if (len > MAX_TEL_LEN) { 267 printf("<<入力した文字の長さが大きすぎます>>\n"); 268 getchar(); 269 continue; 270 } 271 272 for (i = 0; i < len; i++) { 273 if (achTel[i] == '-' || achTel[i] == '(' || achTel[i] == ')' || achTel[i] == '0' 274 || achTel[i] == '1' || achTel[i] == '2' || achTel[i] == '3' 275 || achTel[i] == '4' || achTel[i] == '5' || achTel[i] == '6' 276 || achTel[i] == '7' || achTel[i] == '8' || achTel[i] == '9') { 277 continue; 278 } 279 break; 280 } 281 /* 不正文字混入時はループを抜けるので */ 282 /* lenとiの差異で分岐させる */ 283 if (len == 0 || i != len) { 284 printf("<<入力した文字が不正です>>\n"); 285 getchar(); 286 continue; 287 } 288 /*------------------------------*/ 289 acList[nCountup].lId = nCountup + 1; /* 顧客番号を構造体に登録する */ 290 /*------------------------------*/ 291 for (i = 0; achName[i] != '\0'; i++) { /*------------------------------*/ 292 acList[nCountup].szName[i] = achName[i]; /* 氏名を構造体に登録する */ 293 } /*------------------------------*/ 294 acList[nCountup].szName[i] = '\0'; 295 296 for (i = 0; achAnotherName[i] != '\0'; i++) { /*------------------------------*/ 297 acList[nCountup].szAnotherName[i] = achAnotherName[i]; /* ふりがなを構造体に登録する */ 298 } /*------------------------------*/ 299 acList[nCountup].szAnotherName[i] = '\0'; 300 301 for (i = 0; achTel[i] != '\0'; i++) { /*------------------------------*/ 302 acList[nCountup].szTel[i] = achTel[i]; /* 電話番号を構造体に登録する */ 303 } /*------------------------------*/ 304 acList[nCountup].szTel[i] = '\0'; 305 306// printf("\n%s%s%s\n", acList[nCountup].szName, acList[nCountup].szAnotherName, acList[nCountup].szTel); ////////////////デバッグ 307// printf("\n%ld%s%s%s\n", acList[0].lId, acList[0].szName, acList[0].szAnotherName, acList[0].szTel); ////////////////デバッグ 308// printf("\n%ld%s%s%s\n", acList[1].lId, acList[1].szName, acList[1].szAnotherName, acList[1].szTel); ////////////////デバッグ 309// printf("\n%ld%s%s%s\n", acList[2].lId, acList[2].szName, acList[2].szAnotherName, acList[2].szTel); ////////////////デバッグ 310 printf("\n登録しました。\n"); 311 getchar(); 312 return; 313 } 314} 315

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

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

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

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

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

guest

回答1

0

ベストアンサー

まず、
}```c /構造体配列の動的なメモリ確保/

の部分改行をいれてください、レイアウト崩れていて見づらいです。

内容ですが、何をされたいのかかなり分からないソースになっています。

SEI []seito;
???
SEI型の配列を宣言したい?
のであれば
SEI seito[16];
のようにサイズも必要、でもそうなるとmalloc等での動的確保と矛盾する部分があるのでこの行じたいいらないのでは?

(pns = (SEI *)malloc(sizeof(SEI)))
の部分、これではSEI構造体1個分のメモリしか確保できていませんが、配列でとかかれているので違うのでは?

sizeof(SEI) * 8 のように要素分確保するべき?

seito = pns;
seitoは宣言しないのでいらない、もし宣言していてもメモリ確保すみのseitoのポイントを別に置き換えているというよくわからない処理になっている。

seito.[0] = {100,"あああ",47}
書き方おかしい。。。

ざっとみてもこれだけ??の部分がありそうです。

配列の中身(int型)が0で初期化されないので

問題が発生する。

という問題ではないような気がします。

##追記

質問のタイトルに戻って動的なメモリの確保といことで

c

1typedef struct seiseki { 2 int no; /* 学生番号 */ 3 char name[128]; /* 氏名 */ 4 int kokugo; /* 国語点数 */ 5 6}SEI,*lpSEI; 7 8としておいて 9 10lpSEI pns; 11 12pns = (lpSEI)malloc(sizeof(SEI) * 10); 13 14

で10個分確保です

質問文修正後への追記

全文は読んでません、mallocが使われている周辺だけ読んでのコメントですが

void addData(CUSTOMER_DATA acList[]) 〜略〜 if ((pnL = (CUSTOMER_DATA *)malloc(sizeof(CUSTOMER_DATA))) == NULL) { 〜略〜 acList = pnL;

void addData(CUSTOMER_DATA acList[])
多分私なら
void addData(CUSTOMER_DATA *acList)
かな

そして

if ((pnL = (CUSTOMER_DATA *)malloc(sizeof(CUSTOMER_DATA))) == NULL)
ではなく

if ((acList = (CUSTOMER_DATA *)malloc(sizeof(CUSTOMER_DATA) * 128)) == NULL) {

この部分で1要素分しか確保してないので

for (i = 0; i < 128; i++) { /*0の値以外の登録済み及び */
if (acList[i].lId != 0) {

こんな風にfor分で回すと未確保のメモリにいってします気がします。

###追記

メモリの静的確保、と動的確保、またポインタと配列あたりの理解が曖昧になっている気がします。

静的確保と動的確保

c

1 2// 静的確保 3char buff[12]; 4

c

1 2char *buff; 3 4// 動的確保 5buff = (char *)malloc(sizeof(char)*12); 6

の二つは等価です。どちらか片方行えばOKです。

そして動的に確保したbuffも配列同様
buff[0],buff[1]などの使い方もできます。

しかし

c

1 2char *buff; 3 4buff = (char *)malloc(sizeof(char));// char1要素分を確保(char buff[1];と等価) 5 6にたいして 7 8buff[0] = 'a'; 9// ここまではOK 10// ここから下はできません、メモリ破壊です 11buff[1] = 'b'; 12buff[2] = 'c'; 13buff[3] = 'd'; 14

投稿2016/11/03 05:55

編集2016/11/03 06:48
hiim

総合スコア1689

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

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

dec5798

2016/11/03 06:52

御指摘の通り 動的なメモリと静的なメモリで 大きな勘違いをしていました。 もう一度調べ直して曖昧な部分を解消します。 アドバイス大変ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問