![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?e8efa67)
前回は部分的に質問を投稿したのですが、あまりにもわからないのでもう少し範囲を広げて投稿することにしました。よろしくお願いします。
課題は構造体で顧客情報を確保(顧客情報入力の前に、キーボードで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;
}
おかしなところがたくさんあるとおもいますが、ご指摘よろしくお願いします。
No.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)を表示としたところうまくいきました。ありがとうございました。
まだ、削除や出力がうまくいってませんがもうすこしヒントを参考にがんばろうと思います。また質問することがあると思いますが、この質問も長くなりましたのでそのときは改めて投稿することにします。
そのときは改めてよろしくお願いします。
そして、ここまでありがとうございました。
お礼遅くなりました。
一覧表示はスペースが空けられるようになりました。
しかし、idの代入がうまくいかなく意味のわからない数字が表示されたままです。
ファイル出力と削除のほうはもうちょっとがんばってみます。
No.2
- 回答日時:
> 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
またまたご指摘ありがとうございます。
いまは
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とわけのわからないすうじになってしまいます。うまく代入できずに、そのままの中身が出てるのでしょうが原因がよくわからないです。それと、理想のようにスペースをそれぞれの変数のサイズの分確保したいのですがどうすれば。。。
何度も質問してしまって申し訳ないです。
No.1
- 回答日時:
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)
もし、件数の入力でとんでもない値(十億件とか)が
入力されたらどうなるでしょう?
ご指摘ありがとうございます。
固定長で配列を確保しました。変数名も変えました。
>もし、件数の入力でとんでもない値(十億件とか)が
>入力されたらどうなるでしょう?
すごくめんどくさいことになるところでしたね^^;
顧客の数を確認した後に
kok = (struct kokyaku *)malloc( sizeof(struct kokyaku) * (a));
を書くようにしました。
memsetがまだよく理解できないです。
もう少し頭が良くなりたいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# 10個の実数に対する降順ソート結果を出力するプログラムを作りたいのですが、以下のプログラムをどう直せ 1 2022/07/09 22:16
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
【C言語】全角文字の配列を、全...
-
printf による16進表示について
-
#defineが使用するメモリ領域に...
-
reallocでエラー
-
char型2つを結合し、short型に...
-
ファイル操作で全角空白を消す
-
ファイルの置換
-
WinInetのInternetOpenUrl関数...
-
至急お願いします!!
-
C言語でファイルから複素数の値...
-
構造体メンバの初期化
-
Ç言語でファイルサイズを変更す...
-
課題ができず困っています。
-
2÷3などの余りについて
-
信頼区間の1.96や1.65ってどこ...
-
マイナスからプラスへ転じた時...
-
C言語での引数の省略方法
-
「指定されたキャストは有効で...
-
数字以外が入力されたらエラー...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
C言語で複数列のデータを1列の...
-
printf による16進表示について
-
C言語のプログラムで、途中で止...
-
char型2つを結合し、short型に...
-
矢印キーを押下してコンソール...
-
#defineが使用するメモリ領域に...
-
【C言語】全角文字の配列を、全...
-
終了条件Ctrl+zについて,結果表...
-
空白を含んだ文字列がうまく格...
-
プログラミングの授業の課題です
-
リストの作成と出力(C言語)
-
c言語で文書を読み込み、単語の...
-
構造体メンバの初期化
-
エラーについて質問です。
-
reallocでエラー
-
C言語でのCSVファイルの読み出...
-
なぜ無限ループになるかが分か...
-
Cプログラムについて
-
C++で指定文字列のカウント方法...
おすすめ情報