実行結果
******* MENU *******
1:データ入力
2:データ表示
0:終了
********************
---->1
NAME-- 河野太郎
Tel.No.--080-3960-xxxx
******* MENU *******
1:データ入力
2:データ表示
0:終了
********************
---->2
Name-- 河太郎
Tel.No.-- 080-3960-xxxx
******* MENU *******
1:データ入力
2:データ表示
0:終了
********************
---->0
20行目で構造体変数を宣言すると同時に初期化しています。また21行目で、この構造体変数のアドレスを、この構造体へのポインタ lpMydata に代入しています。
そのあと、while の無限ループ突入です。
menu 関数の戻り値を selection に代入し、switch 文で場合分けしています。selection が1ならば、meibo_input 関数を呼び出します。2ならば、meibo_output 関数を呼び出します。その他であれば、loopend 変数に1に代入して switch 文抜けます。
loopend が真(0以外)であれば(36行目)、break文が実行されて while ループを抜けます。もし、「if(loopend)」という書きかたが分かりにくければ、「if(loopend != 0)」としても同じことです。
menu 関数の中で使われている atoi は文字列を int 型の数値に変換する関数です。例えば"123"は文字列ですが、これを atoi 関数で変換すると数値の123を得ることがえきます。menu 関数では、string を int 型の整数に変換して戻り値としています。「atoi」というのは変な名前の関数ですが「Ascii TO Integer」と覚えておきます。
atoi関数
int atoi(
const char *string
);
atof関数
double atof(
const char *string
);
もし53行目の「return atoi(ret);」が分かりにくければ、変数 int no; を用意して置いて、
no = atoi(ret);
return no;
と書き換えてみてください。
引数の lpData には mydata 構造体のアドレスが入っています。lpData->name は、name メンバです。
gets(lpData->name);
は、これでよいのでしょうか。gets の引数にはバッファのアドレスを指定します。name は配列の名前なので、これでよいのですね。電話番号(lpData->tel)についても同様です。
構造体からデータを読み出す関数です。特に説明は不要です。
これでは、ちょっとあないですね、何人ものデータを入れられるようにするにはどうしたらよいでしょうか。構造体の配列を使えばいいですね。では、改造しましょう。
ソースコード
源文件
1|
2|
3|#include <stdio.h>
4|#include <stdlib.h>
5|#include <string.h>
6|
7|typedef struct DATA {
8| char name[32];
9| char tel[32];
10|} MYDATA, *LPMYDATA;
11|
12|int menu();
13|int meibo_input(LPMYDATA);
14|int meibo_output(LPMYDATA);
15|
16|int main(void)
17|{
18| int selection, loopend = 0;
19|
20| MYDATA mydata[10];
21| LPMYDATA lpMydata = mydata;
22|
23| memset (mydata, '\0', sizeof(MYDATA[10]));
24|
25| while(1){
26| selection = menu();
27|
28| switch (selection){
29| case 1:
30| meibo_input(lpMydata);
31| break;
32| case 2:
33| meibo_output(lpMydata);
34| break;
35| default:
36| loopend = 1;
37| break;
38| }
39| if (loopend)
40| break;
41| }
42| return 0;
43|}
44|
45|int menu()
46|{
47| char ret[8];
48|
49| printf("******* MENU *******\n");
50| printf("1:データ入力\n");
51| printf("2:データ表示\n");
52| printf("0:終了\n");
53| printf("********************\n");
54| printf("---->");
55| scanf("%s", ret);
56| return atoi(ret);
57|}
58|
59|int meibo_input(LPMYDATA lpData)
60|{
61| char strno[8];
62| int no;
63|
64| printf("何番のデータを入力しますか(0-9)--");
65| scanf("%s", strno);
66| if (strno[0] < '0' || strno[0] > '9'){
67| printf("入力が不正です\n");
68| return -1;
69| }
70| strno[1] = '\0';
71| no = atoi(strno);
72|
73| printf("NAME--");
74| scanf("%s", lpData->name);
75| printf("Tel.No.--");
76| scanf("%s,", lpData->tel);
77|
78| return 0;
79|}
80|
81|int meibo_output(LPMYDATA lpData)
82|{
83| char strno[8];
84| int no;
85|
86| printf("何番のデータを読み出しますか(0-9)--");
87| scanf("%s", strno);
88| if (strno[0] < '0' || strno[0] > '9'){
89| printf("入力が不正です\n");
90| return -1;
91| }
92| strno[1] = '\0';
93| no = atoi(strno);
94|
95| if (!strcmp( (lpData + no)->name, "\n") ){
96| printf("データがありません\n");
97| return -1;
98| }
99|
100| printf("Name-- %s\n", lpData->name);
101| printf("Tel.No.-- %s\n", lpData->tel);
102|
103| class="keyword">return 0;
104|}
|
実行結果
20〜21行目の
MYDATA mydata[10];
LPMYDATA lpMydata = mydata;
を何をしているのでしょうか。mydataは配列の名前ですね。配列の名前は先頭要素のアドレスでした。したがって21行目は
LPMYDATA lpMydata = &mydata[0];
と同じことです。DATA型構造体へのポインタlpMydataに、mydata[0]のアドレスを代入しているわけです。
23行目の memset は見慣れない関数ですね。でも、メモリ(mem)に何かをセットする関数ではないかな、と想像できませんか。実はその通りなのです。
void *memset(
void *dest,
int c,
size_t count
);
この関数は指定したいパッファ(dest)を、指定した文字(c)count 個で埋め尽くす関数なのです。なお、この関数を使うときは string.h をインクルードする必要があります。
ここでは、構造体メンバをすべてヌル文字で埋め尽くしています。なぜこのような処理が必要かというと、データ読み出しのとき、データの収められていない構造体配列の要素を指定したときに「データがありません」と表示するときの判断材料にしているからです。
meibo_input 関数を見てみましょう。
「何番のデータを入力しますか(0-9)--」と表示した後、ユーザーが入力した文字列をgets関数で取得して strno に格納します。データの番号とは配列添字のことです。
次に strno の最初の1文字を調べます。これが'0'から'9'の範囲に入っていなければ「入力が不正です」と表示して return します。
次に strno[1] に '\0' を代入しています。たとえばユーザーが「112」と入力した場合でも、strno[1]にヌル文字を代入すればこの文字列は"1"と見なされますね。あとは、この文字列を整数値に変換して no に代入します。
さて、引数の lpData は main 関数の mydata[0] のアドレスです。mydata[n]のアドレスは(mydata + n)ですね。したがって mydata[n] の name メンバは
(mydata + n)->name
となります。telメンバについても同様です。
Chapte8 @ C言語目録 @ HomeWork List @ 昭亮's Homepage
| |