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

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

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

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

1008閲覧

構造体内の配列の処理が分からない

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

0クリップ

投稿2020/06/19 10:11

前提・実現したいこと

C言語を用いて住所登録プログラムを作成しています。
名前・郵便番号・住所・電話番号の配列をそれぞれ作り、これらを引数にした関数を作りました。以下は成功例です。

#include<stdio.h> #include<stdlib.h> #include<string.h> #define SIZE 100 //名前・郵便番号・住所・電話番号を構造体にまとめる typedef struct{ char name[500]; char zipcode[500]; char address[500]; char tel[500]; }Info; //IDの入力を関数化する int InputID(){ int ID = 0; printf("IDは?(1~%d)\n",SIZE); while(ID == 0){ scanf("%d", &ID); if(ID < 1 || SIZE < ID){ ID = 0; printf("IDが正しくありません。再入力して下さい。\n"); }else{ printf("IDの認証に成功しました。\n"); return ID; } } } //名前・郵便番号・住所・電話番号の入力を関数化する void InputInfo(char name[500], char zipcode[500], char address[500], char tel[500]){ printf("名前を入力して下さい。\n"); scanf("%s", name); printf("郵便番号を入力して下さい。(ハイフンなし)\n"); scanf("%s", zipcode); printf("住所を入力してください。\n"); scanf("%s", address); printf("電話番号を入力してください。(ハイフンなし)\n"); scanf("%s", tel); } //名前・郵便番号・住所・電話番号を登録する void Register(char list1[SIZE][500], char list2[SIZE][500], char list3[SIZE][500], char list4[SIZE][500]){ printf("登録したい"); int ID = InputID(); char name[500], zipcode[500], address[500], tel[500]; InputInfo(name, zipcode, address, tel); memcpy(list1[ID],name,sizeof(list1[ID])); memcpy(list2[ID],zipcode,sizeof(list2[ID])); memcpy(list3[ID],address,sizeof(list3[ID])); memcpy(list4[ID],tel,sizeof(list4[ID])); printf("登録に成功しました。\n"); } //IDから個人情報を検索する void Search(char list1[SIZE][500], char list2[SIZE][500], char list3[SIZE][500], char list4[SIZE][500]){ printf("検索したい"); int ID = InputID(); printf("名前:%s\n",list1[ID]); printf("郵便番号:%s\n",list2[ID]); printf("住所:%s\n",list3[ID]); printf("電話番号:%s\n",list4[ID]); } //全データの閲覧 void ListAll(char list1[SIZE][500], char list2[SIZE][500], char list3[SIZE][500], char list4[SIZE][500]){ int i; for(i=1;i<=SIZE;i++){ printf("ID:%dの情報-------------------------------\n",i); printf("名前:%s\n",list1[i]); printf("郵便番号:%s\n",list2[i]); printf("住所:%s\n",list3[i]); printf("電話番号:%s\n",list4[i]); } } //データの削除 void Delete(char list1[SIZE][500], char list2[SIZE][500], char list3[SIZE][500], char list4[SIZE][500]){ int select = 0; printf("削除したいデータの"); int ID = InputID(); printf("データを削除しますか? 1.yes 2.no\n"); while(select != 1 || select != 2){ scanf("%d", &select); if(select == 1){ memset(list1[ID],'\0',strlen(list1[ID])); memset(list2[ID],'\0',strlen(list2[ID])); memset(list3[ID],'\0',strlen(list3[ID])); memset(list4[ID],'\0',strlen(list4[ID])); printf("データを削除しました。\n"); break; }else if(select == 2){ printf("削除を中止しました。\n"); break; }else{ printf("1か2を再入力して下さい。\n"); } } } //メインメニュー int main(){ char NameList[SIZE][500], ZipCodeList[SIZE][500], AddressList[SIZE][500], TelList[SIZE][500]; int Menu = 0; while(Menu != 5){ printf("---------------住所録プログラム--------------\n"); printf("1:登録\n"); printf("2:検索\n"); printf("3:閲覧\n"); printf("4:削除\n"); printf("5:終了\n"); printf("行う操作の番号を入力して下さい。\n"); scanf("%d", &Menu); system("cls"); switch(Menu){ case 1: Register(NameList, ZipCodeList, AddressList, TelList); break; case 2: Search(NameList, ZipCodeList, AddressList, TelList); break; case 3: ListAll(NameList, ZipCodeList, AddressList, TelList); break; case 4: Delete(NameList, ZipCodeList, AddressList, TelList); break; case 5: break; default: printf("不正な番号です。再入力して下さい。\n"); break; } } return 0; }

上記の関数の引数が4つもあり煩雑だと思い、構造体を用いて簡潔にしようと思ったのですが、以下のソースコードを試してみるとRegister関数で情報を登録しましたが、Search関数実行時に表示されません。ポインタの問題だと思ったのですが、C言語を学び始めて2か月の私には解決策が思いつきませんでした。そこで対処法を教えて頂きたいです。 
また、ID以外の情報からも検索できるように改良しましたので、誤っている箇所があれば教えて頂きたいです。
初投稿なので拙いですが、ご容赦ください。
宜しくお願い致します。

発生している問題・エラーメッセージ

Register関数で名前・郵便番号・住所・電話番号を入力した後、Search関数で検索しても登録したはずの 4つの情報が出力されない。エラーメッセージは出ない。

該当のソースコード

C

1#include<stdio.h> 2#include<stdlib.h> 3#include<string.h> 4#define SIZE 100 5#define LENGTH 500 6 7//名前・郵便番号・住所・電話番号を構造体にまとめる 8typedef struct{ 9 char name[LENGTH]; 10 char zipcode[LENGTH]; 11 char address[LENGTH]; 12 char tel[LENGTH]; 13}Info; 14 15typedef struct{ 16 char NameList[SIZE][LENGTH]; 17 char ZipCodeList[SIZE][LENGTH]; 18 char AddressList[SIZE][LENGTH]; 19 char TelList[SIZE][LENGTH]; 20}InfoList; 21 22//IDの入力を関数化する 23int InputID(){ 24 int ID = 0; 25 printf("IDは?(1~%d)\n",SIZE); 26 while(ID == 0){ 27 scanf("%d", &ID); 28 if(ID < 1 || SIZE < ID){ 29 ID = 0; 30 printf("IDが正しくありません。再入力して下さい。\n"); 31 }else{ 32 printf("IDの認証に成功しました。\n"); 33 return ID; 34 } 35 } 36} 37 38//名前・郵便番号・住所・電話番号の入力 39void InputInfo(Info *info){ 40 printf("名前を入力して下さい。\n"); 41 scanf("%s", info->name); 42 printf("郵便番号を入力して下さい。(ハイフンなし)\n"); 43 scanf("%s", info->zipcode); 44 printf("住所を入力してください。\n"); 45 scanf("%s", info->address); 46 printf("電話番号を入力してください。(ハイフンなし)\n"); 47 scanf("%s", info->tel); 48} 49 50//名前・郵便番号・住所・電話番号の格納 51void SetInfo(InfoList *list, Info *info, int ID){ 52 memcpy(list->NameList[ID],info->name,sizeof(list->NameList[ID])); 53 memcpy(list->ZipCodeList[ID],info->zipcode,sizeof(list->ZipCodeList[ID])); 54 memcpy(list->AddressList[ID],info->address,sizeof(list->AddressList[ID])); 55 memcpy(list->TelList[ID],info->tel,sizeof(list->TelList[ID])); 56} 57 58//ID・名前・郵便番号・住所・電話番号の出力 59void OutputInfo(InfoList *list, int ID){ 60 printf("ID:%d", ID); 61 printf("名前:%s\n",list->NameList[ID]); 62 printf("郵便番号:%s\n",list->ZipCodeList[ID]); 63 printf("住所:%s\n",list->AddressList[ID]); 64 printf("電話番号:%s\n",list->TelList[ID]); 65} 66 67//名前・郵便番号・住所・電話番号の登録 68void Register(InfoList *list){ 69 printf("登録したい"); 70 int ID = InputID(); 71 Info *info; 72 InputInfo(info); 73 SetInfo(list, info, ID); 74 printf("登録に成功しました。\n"); 75} 76 77//個人情報の検索 78void Search(InfoList *list){ 79 int i, ID, cnt = 0; 80 char string[500]; 81 char element[5][10] = {"ID", "名前", "郵便番号", "住所", "電話番号"}; 82 printf("何で検索しますか?\n1.ID 2.名前 3.郵便番号 4.住所 5.電話番号\n"); 83 scanf("%d", &i); 84 while(i<1 || 5<i){ 85 printf("不正な番号です。再入力してください。\n"); 86 printf("何で検索しますか?\n1.ID 2.名前 3.郵便番号 4.住所 5.電話番号\n"); 87 scanf("%d", &i); 88 } 89 if(i == 1){ 90 printf("検索したい"); 91 ID = InputID(); 92 OutputInfo(list, ID); 93 }else{ 94 printf("検索する%sを入力して下さい。\n", element[i]); 95 gets(string); 96 for(ID=1;ID<=SIZE;ID++){ 97 switch(i){ 98 case 2: 99 if(strcmp(list->NameList[ID], string) == 0) OutputInfo(list, ID); 100 break; 101 case 3: 102 if(strcmp(list->ZipCodeList[ID], string) == 0) OutputInfo(list, ID); 103 break; 104 case 4: 105 if(strcmp(list->AddressList[ID], string) == 0) OutputInfo(list, ID); 106 break; 107 case 5: 108 if(strcmp(list->TelList[ID], string) == 0) OutputInfo(list, ID); 109 break; 110 default: 111 cnt += 1; 112 break; 113 } 114 } 115 if(cnt == SIZE) printf("そのような%sは存在しません。\n", element[i]); 116 } 117} 118 119//全データの閲覧 120void ListAll(InfoList *list){ 121 int i; 122 for(i=1;i<=SIZE;i++){ 123 printf("ID:%dの情報-------------------------------\n",i); 124 OutputInfo(list, i); 125 } 126} 127 128//既存のデータを空白に書き換え 129void Blank(InfoList *list, int ID){ 130 memset(list->NameList[ID],'\0',strlen(list->NameList[ID])); 131 memset(list->ZipCodeList[ID],'\0',strlen(list->ZipCodeList[ID])); 132 memset(list->AddressList[ID],'\0',strlen(list->AddressList[ID])); 133 memset(list->TelList[ID],'\0',strlen(list->TelList[ID])); 134} 135 136//データの削除 137void Delete(InfoList *list){ 138 int select = 0; 139 printf("削除したいデータの"); 140 int ID = InputID(); 141 printf("データを削除しますか? 1.yes 2.no\n"); 142 while(select != 1 || select != 2){ 143 scanf("%d", &select); 144 if(select == 1){ 145 Blank(list, ID); 146 printf("データを削除しました。\n"); 147 break; 148 }else if(select == 2){ 149 printf("削除を中止しました。\n"); 150 break; 151 }else{ 152 printf("1か2を再入力して下さい。\n"); 153 } 154 } 155} 156 157//メインメニュー 158int main(){ 159 InfoList *list; 160 int MenuID = 0; 161 while(MenuID != 5){ 162 printf("---------------住所録プログラム--------------\n"); 163 printf("1:登録\n"); 164 printf("2:検索\n"); 165 printf("3:閲覧\n"); 166 printf("4:削除\n"); 167 printf("5:終了\n"); 168 printf("行う操作の番号を入力して下さい。\n"); 169 scanf("%d", &MenuID); 170 system("cls"); 171 switch(MenuID){ 172 case 1: 173 Register(list); 174 break; 175 case 2: 176 Search(list); 177 break; 178 case 3: 179 ListAll(list); 180 break; 181 case 4: 182 Delete(list); 183 break; 184 case 5: 185 break; 186 default: 187 printf("不正な番号です。再入力して下さい。\n"); 188 break; 189 } 190 191 } 192 return 0; 193} 194

試したこと

InfoとInfoListをポインタ型にしたり、アロー演算子を用いて構造体メンバを取り出そうとした。

補足情報(FW/ツールのバージョンなど)

Visual Studioを用いてgccでコンパイラした。

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

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

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

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

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

anndonut

2020/06/19 13:30

Visual Studioを用いてgccでコンパイラした。 > Visual Studio Codeとgccを使ったんですか?
退会済みユーザー

退会済みユーザー

2020/06/19 14:11

その通りです。 説明不足で申し訳ありませんでした。
guest

回答2

0

ベストアンサー

質問内容とちょっと違いますが、以下に示すソースコードのように構造体の配列にすれば処理がスッキリしますよ。

構造体は値型で、関数に渡すと構造体のコピーが渡され、関数の中で構造体の内容を変更しても呼び出し元の構造体内容は変更されません。
コピーせずに構造体を共有したい場合は構造体のアドレスを引き渡すようにします。関数の仮引数はポインタ変数で引き受けます。関数の中で構造体の内容を変更すると呼び出し元の構造体が変更されます。

配列は参照型で、関数に渡すとアドレス(ポインタ)が引き渡ります。関数の仮引数はポインタ変数で引き受けることもできますが、配列定義で引き受けとることもできて配列として処理を書けます。
配列はコピーされずに共有されているので、関数内で配列内容を変更すると呼び出し元の配列内容が変更されます。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <stdbool.h> 4#include <string.h> 5#define SIZE 100 6#define LENGTH 500 7 8//名前・郵便番号・住所・電話番号を構造体にまとめる 9typedef struct { 10 char name[LENGTH]; 11 char zipcode[LENGTH]; 12 char address[LENGTH]; 13 char tel[LENGTH]; 14} Info; 15 16typedef Info InfoList[SIZE + 1]; // [1]~[SIZE]を使用, [0]は使わない 17 18// IDの入力を関数化する 19int InputID() 20{ 21 printf("IDは?(1~%d)\n", SIZE); 22 while (true) { 23 int ID; 24 if (scanf("%d", &ID) != 1) exit(1); 25 if (1 <= ID && ID <= SIZE) { 26 printf("IDの認証に成功しました。\n"); 27 return ID; 28 } 29 printf("IDが正しくありません。再入力して下さい。\n"); 30 } 31} 32 33//名前・郵便番号・住所・電話番号の入力 34void InputInfo(Info *info) 35{ 36 printf("名前を入力して下さい。\n"); 37 if (scanf("%s", info->name) != 1) exit(1); 38 printf("郵便番号を入力して下さい。(ハイフンなし)\n"); 39 if (scanf("%s", info->zipcode) != 1) exit(1); 40 printf("住所を入力してください。\n"); 41 if (scanf("%s", info->address) != 1) exit(1); 42 printf("電話番号を入力してください。(ハイフンなし)\n"); 43 if (scanf("%s", info->tel) != 1) exit(1); 44} 45 46// ID・名前・郵便番号・住所・電話番号の出力 47void OutputInfo(InfoList list, int ID) 48{ 49 printf("ID:%d\n", ID); 50 printf("名前:%s\n", list[ID].name); 51 printf("郵便番号:%s\n", list[ID].zipcode); 52 printf("住所:%s\n", list[ID].address); 53 printf("電話番号:%s\n", list[ID].tel); 54} 55 56//名前・郵便番号・住所・電話番号の登録 57void Register(InfoList list) 58{ 59 printf("登録したい"); 60 int ID = InputID(); 61 InputInfo(&list[ID]); 62 printf("登録に成功しました。\n"); 63} 64 65//個人情報の検索 66void Search(InfoList list) 67{ 68 int select, ID; 69 char *element[] = {"", "ID", "名前", "郵便番号", "住所", "電話番号" }; 70 while (true) { 71 printf("何を検索しますか?\n1.ID 2.名前 3.郵便番号 4.住所 5.電話番号\n"); 72 if (scanf("%d", &select) != 1) exit(1); 73 if (1 <= select && select <= 5) 74 break; 75 printf("不正な番号です。再入力してください。\n"); 76 } 77 if (select == 1) { 78 printf("検索したい"); 79 ID = InputID(); 80 OutputInfo(list, ID); 81 return; 82 } 83 printf("検索する%sを入力して下さい。\n", element[select]); 84 char target[500]; 85 if (scanf("%s", target) != 1) exit(1); 86 bool found = false; 87 for (ID = 1; ID <= SIZE; ID++) { 88 char *field = ""; 89 switch (select) { 90 case 2: field = list[ID].name; break; 91 case 3: field = list[ID].zipcode; break; 92 case 4: field = list[ID].address; break; 93 case 5: field = list[ID].tel; break; 94 default: break; 95 } 96 if (strcmp(field, target) == 0) { 97 OutputInfo(list, ID); 98 found = true; 99 } 100 } 101 if (!found) printf("そのような%sは存在しません。\n", element[select]); 102} 103 104//全データの閲覧 105void ListAll(InfoList list) 106{ 107 for (int ID = 1; ID <= SIZE; ID++) { 108 if (list[ID].name[0] == '\0') continue; 109 printf("------------------------------\n"); 110 OutputInfo(list, ID); 111 } 112} 113 114//既存のデータを空白に書き換え 115void Clear(Info *info) 116{ 117 memset(info, 0, sizeof(*info)); 118} 119 120//データの削除 121void Delete(InfoList list) 122{ 123 printf("削除したいデータの"); 124 int ID = InputID(); 125 printf("データを削除しますか? 1.yes 2.no\n"); 126 while (true) { 127 int select = 0; 128 if (scanf("%d", &select) != 1) exit(1); 129 if (select == 1) { 130 Clear(&list[ID]); 131 printf("データを削除しました。\n"); 132 return; 133 } 134 if (select == 2) { 135 printf("削除を中止しました。\n"); 136 return; 137 } 138 printf("1か2を再入力して下さい。\n"); 139 } 140} 141 142//メインメニュー 143int main() 144{ 145 InfoList list; 146 memset(list, 0, sizeof(list)); 147 148 void (*menu[])() = { NULL, Register, Search, ListAll, Delete }; 149 while (true) { 150 printf("---------------住所録プログラム--------------\n"); 151 printf("1:登録\n"); 152 printf("2:検索\n"); 153 printf("3:閲覧\n"); 154 printf("4:削除\n"); 155 printf("5:終了\n"); 156 printf("行う操作の番号を入力して下さい。\n"); 157 int MenuID = 0; 158 if (scanf("%d", &MenuID) != 1) exit(1); 159 system("cls"); 160 switch (MenuID) { 161 case 1: Register(list); break; 162 case 2: Search(list); break; 163 case 3: ListAll(list); break; 164 case 4: Delete(list); break; 165 case 5: return 0; 166 default: printf("不正な番号です。再入力して下さい。\n"); break; 167 } 168 } 169}

投稿2020/06/19 17:12

編集2020/06/20 09:32
shiracamus

総合スコア5406

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

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

退会済みユーザー

退会済みユーザー

2020/06/20 02:12

ご回答有り難うございます。 詳しい解説と他の部分の修正案も提案して頂き、ご親切に有り難うございました。 学習の糧にさせて頂きます。
guest

0

  • Register()Info* info;
  • main()InfoList* list;

ポインタ変数が宣言されているだけで、入力された値を格納するための領域が確保されていません。


メモリを動的に確保するならmallocfreeを使用します。


ポインタで渡したいだけなら

diff

1void Register(InfoList* list) { 2 printf("登録したい"); 3 int ID = InputID(); 4- Info* info; 5+ Info info; 6- InputInfo(info); 7+ InputInfo(&info); 8- SetInfo(list, info, ID); 9+ SetInfo(list, &info, ID); 10 printf("登録に成功しました。\n"); 11} 12int main() { 13- InfoList* list; 14+ InfoList list; 15 int MenuID = 0; 16 while (MenuID != 5) { 17 printf("---------------住所録プログラム--------------\n"); 18 printf("1:登録\n"); 19 printf("2:検索\n"); 20 printf("3:閲覧\n"); 21 printf("4:削除\n"); 22 printf("5:終了\n"); 23 printf("行う操作の番号を入力して下さい。\n"); 24 scanf("%d", &MenuID); 25 system("cls"); 26 switch (MenuID) { 27 case 1: 28- Register(list); 29+ Register(&list); 30 break; 31 case 2: 32- Search(list); 33+ Search(&list); 34 break; 35 case 3: 36- ListAll(list); 37+ ListAll(&list); 38 break; 39 case 4: 40- Delete(list); 41+ Delete(&list); 42 break; 43 case 5: 44 break; 45 default: 46 printf("不正な番号です。再入力して下さい。\n"); 47 break; 48 } 49 50 } 51 return 0; 52}

投稿2020/06/19 10:30

編集2020/06/19 10:40
SHOMI

総合スコア4079

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

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

退会済みユーザー

退会済みユーザー

2020/06/19 10:39

ご回答有り難うございます。 入力された値を格納するにはどう記述すれば良いのでしょうか? 初心者なので詳しく書いて頂けると幸いです。
退会済みユーザー

退会済みユーザー

2020/06/20 02:11 編集

有り難うございます。 Register関数を実行させたところ正しく作動しました。 本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.39%

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

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

質問する

関連した質問