電子書籍の厳選無料作品が豊富!

前回は部分的に質問を投稿したのですが、あまりにもわからないのでもう少し範囲を広げて投稿することにしました。よろしくお願いします。

課題は構造体で顧客情報を確保(顧客情報入力の前に、キーボードで1~50の顧客情報の数を入力し、その数の構造体を確保)し、分岐点(登録、一覧表示、削除、ファイル出力、終了)に行き、それぞれを行なうプログラムです。

登録では、名前、ふりがな、電話番号を入力(idは1から順につける)。名前、ふりがなの型はcharで確保して入力もそのままなんですが、電話番号の型はcharにして0~9までとハイフンのみ入力可能にし、他の文字を入力したらエラーを返すようにするみたいなんですが方法がわからないです。それと現段階ではビルドはうまくいくのですが、登録画面に行くとidをいれるところ(多分)で論理エラーが起きてexeが強制終了してしまいます。
ちなみに、それぞれの出力サイズはidが5、名前が24、ふりがなが24、電話番号が16です。

一覧表示では、id、名前、ふりがな、電話番号を改行なしで位置はidは左から1番目、名前は6番目、ふりがなは32番目、電話番号が57番目からそれぞれ表示します。
今記述している段階ではスペースがあくことなくすべて左詰で表示され、顧客番号が変な数字になってしまいます。

削除では、指定したidを削除し、削除したidは再利用はできないがその分新たなidで顧客情報を入力することができる。削除の仕方がわからないです。

ファイル出力では、csv形式で出力するみたいなんですが。記述してもエラーが返ってくるばかりでよくわからないです。

こんな感じでわからないことが多いのですが、部分的にでもかまいませんので教えていただければと思います。

ちなみに、わたしが記述したのは下記のとおりです。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <conio.h>
#include "top.h"
#include "ichiran.h"
#define size_id (5)
#define size_name (24)
#define size_huri (24)
#define size_tel (16)

struct kokyaku
{
long *id;
char *name;
char *huri;
char *tel;
};
int main()
{
int a , b , i , j; //顧客情報確保の件数 メニュー画面での分岐 顧客情報の件数と比較
long c = 1; //顧客番号
struct kokyaku *kok;
printf("顧客情報がありません。何件分確保しますか?(1 - 50)");
scanf("%d",&a);
kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (a));
system("cls");
if(a < 1 || a > 50)
{

printf("<<入力範囲にありません>>\n");
printf("<<処理を中断します>>\n");
return 0;
}else{
for(i = 0;i < a;i++){
kok[i].id = (long*)malloc(size_id);
kok[i].name = (char*)malloc(size_name);
kok[i].huri = (char*)malloc(size_huri);
kok[i].tel = (char*)malloc(size_tel);
memset(kok, '\0', sizeof(kok));
}
}
i = 0;
while(b = 5){
printf("%s", top1);
printf("処理区分>");

scanf("%d",&b);
system("cls");
switch(b) //メニュー画面での分岐
{
case 1: //登録
if(c <= a)
{
printf("***** 顧客登録画面 *****\n");
*(kok[i].id) = c;
printf("氏名  :");
scanf("%s", kok[i].name);
printf("ふりがな:");
scanf("%s", kok[i].huri);
printf("電話番号:");
scanf("%s", kok[i].tel);
c++;
i++;
}
else
{
printf("登録がいっぱいになりました");
}
break;

case 2: //一覧表示
printf("%s\n", ichiran1);
printf("%s\n", ichiran2);
j = i;
i = 0;
while(i < j)
{
printf("%d%s%s%s\n", kok[i].id , kok[i].name , kok[i].huri , kok[i].tel);
i++;
}
printf("%s\n", ichiran2);
break;

case 3:    //削除
break;

case 4:    //ファイル出力


break;

case 5:     //終了
break;

default: //エラー
printf("<<処理区分エラー>>");
break;
return 0;
}
}
return 0;
}

おかしなところがたくさんあるとおもいますが、ご指摘よろしくお願いします。

A 回答 (3件)

> こんな感じになっています。

良いのかはわかりませんが^^;
> エラーは消えましたが、ファイル出力や削除もわからないんですけど、特に一覧表示がうまくいきません。

まあ細かいこというときりがないので、とりあえずは良しとしましょう。
で、ファイル出力と削除も後回しにするとして、

> 登録でidの1にnameにabc、huriにdef、telに1234-5678といれると
>
> 4399008abcdef1234-5678

んー、 struct kokyaku の定義は今はどうなってますか?
そして出力している行はどんな感じですか?
idはとりあえずおいといて、name hrui tel がくっついて出てしまっているのは
%s%s%s のようにしているからでしょう。

> 1****abc*********************def*********************1234-5678*******
> *はスペースのことです。

> と表示したいのです

printf の書式指定のところを調べてみてください。
こんな感じにすると、全体で何桁分か確保した上で変数の変換結果が足りないときに
適当に埋めてくれます。

#include <stdio.h>
#include <stdlib.h>

int
main(int argc, char *argv[])
{
const char* str = "hello";

printf("<<%s>>\n");
printf("<<%10s>>\n");
printf("<<%-10s>>\n");

return 0;
}

出力結果:
<<hello>>
<< hello>>
<<hello >>

ファイル出力と削除がわからないということですけど、
ファイル出力の方は具体的に何がわかりませんか?
ファイルをオープンするのと、書き込みの手順はわかりますよね?

>記述してもエラーが返ってくるばかりでよくわからないです。
どんな書き方をして、どんなエラーになりましたか?

削除の方は、何らかの方法で「削除しました」って目印を
つけるようにすればよいです。
とりあえず自分でもどういう「目印」にすればいいか考えてみてください。

あ、まずは一覧表示を正しくできるようにするのを優先で。

この回答への補足

度々、すいません。
プログラムをいじっていてidがでてきたのでお知らせしました。

いままで、代入がうまくいってないとばかり思っていたのですが、もしかしたら表示の時うまくいってないのかと思い、いままでkok[i].idを表示としていたのですが、*(kok[i].id)を表示としたところうまくいきました。ありがとうございました。

まだ、削除や出力がうまくいってませんがもうすこしヒントを参考にがんばろうと思います。また質問することがあると思いますが、この質問も長くなりましたのでそのときは改めて投稿することにします。
そのときは改めてよろしくお願いします。
そして、ここまでありがとうございました。

補足日時:2008/02/26 00:09
    • good
    • 0
この回答へのお礼

お礼遅くなりました。
一覧表示はスペースが空けられるようになりました。
しかし、idの代入がうまくいかなく意味のわからない数字が表示されたままです。

ファイル出力と削除のほうはもうちょっとがんばってみます。

お礼日時:2008/02/25 22:57

> memsetがまだよく理解できないです。


> もう少し頭が良くなりたいです。

難しく考えすぎじゃないですか?
memsetがやっていることは、

memset(kok, '\0', sizeof(kok));
_______↑ このアドレスから sizeof (kok) だけ '\0' で埋める
ってことです。
そんだけ。

質問にあるやりかただと

+---+
|k |→ "七氏権兵衛"
|o |→ "ななしのごんべえ"
|k |→ "000-1234-5678"
+---+

こんなのが、kok[0] とか kok[1] になるわけです。
で、よーく質問にあるプログラムを見直してみると、

> kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (a));

これで、kokyaku の領域を人数分確保してます。これはいいですね。
で、構造体のメンバーもポインタで確保することにしていたので

kok[i].id = (long*)malloc(size_id);
kok[i].name = (char*)malloc(size_name);
kok[i].huri = (char*)malloc(size_huri);
kok[i].tel = (char*)malloc(size_tel);

としてそれぞれの分を確保している。これもいいです。
じゃあなにが問題かというと

memset(kok, '\0', sizeof(kok));

これ。
最初に書いたとおり、これは kok を先頭としてゼロを埋めていくわけですけど
その先頭はなにを指しているかというと、

> kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (a));

これですよね。
たぶん、一人分の領域を確保してそれを初期化したかったのだと思いますが、
それをするなら

kok[i].id = (long*)malloc(size_id);

こっちでmalloc したほうです。
結局

+---+
|k |→ "七氏権兵衛"
|o |→ "ななしのごんべえ"
|k |→ "000-1234-5678"
+---+

この箱の中身をゼロ埋めしちゃったわけです。
つまり、せっかく確保した名前とかを格納する領域を
指していたところをパーにしちゃったと。
そこをアクセスしたので異常終了したというわけです。

んー削除やら出力の説明を書くスペースがないなw
    • good
    • 0
この回答へのお礼

またまたご指摘ありがとうございます。
いまは
int main()
{
int kokyaku , bunki , i , j; //顧客情報確保の件数 メニュー画面での分岐 顧客情報の件数と比較
long id = 1; //顧客番号
struct kokyaku *kok;
printf("顧客情報がありません。何件分確保しますか?(1 - 50)");
scanf("%d",&kokyaku);
system("cls");
if(kokyaku < 1 || kokyaku > 50)
{

printf("<<入力範囲にありません>>\n");
printf("<<処理を中断します>>\n");
return 0;
}else{
kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (kokyaku));

}

こんな感じになっています。良いのかはわかりませんが^^;
エラーは消えましたが、ファイル出力や削除もわからないんですけど、特に一覧表示がうまくいきません。
登録でidの1にnameにabc、huriにdef、telに1234-5678といれると

4399008abcdef1234-5678

と表示されてしまいます。理想では、

1****abc*********************def*********************1234-5678*******
*はスペースのことです。

と表示したいのです。
idは、1でも2でも4399008とわけのわからないすうじになってしまいます。うまく代入できずに、そのままの中身が出てるのでしょうが原因がよくわからないです。それと、理想のようにスペースをそれぞれの変数のサイズの分確保したいのですがどうすれば。。。

何度も質問してしまって申し訳ないです。

お礼日時:2008/02/21 02:43

a, b, c なんて一文字の名前の変数を使わない。


きちんと何に使う変数なのか意味がわかる名前をつける
ただし、for ループでつかう i, j, k 辺りは例外。

kok[i].id = (long*)malloc(size_id);
kok[i].name = (char*)malloc(size_name);
kok[i].huri = (char*)malloc(size_huri);
kok[i].tel = (char*)malloc(size_tel);
memset(kok, '\0', sizeof(kok));
}

最後の memset で '\0'が埋められているのは一体どこなのか
よーーく考えてみてください。

つか、前回のアドバイスにあった通りに
構造体の中で固定長の配列でとるようにすればいいのに。


printf("顧客情報がありません。何件分確保しますか?(1 - 50)");
scanf("%d",&a);
kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (a));
system("cls");
if(a < 1 || a > 50)

もし、件数の入力でとんでもない値(十億件とか)が
入力されたらどうなるでしょう?
    • good
    • 0
この回答へのお礼

ご指摘ありがとうございます。

固定長で配列を確保しました。変数名も変えました。

>もし、件数の入力でとんでもない値(十億件とか)が
>入力されたらどうなるでしょう?

すごくめんどくさいことになるところでしたね^^;
顧客の数を確認した後に
kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (a));
を書くようにしました。

memsetがまだよく理解できないです。
もう少し頭が良くなりたいです。

お礼日時:2008/02/19 18:38

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!