テキストファイルの在庫の更新

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
ぴぴ

テキストファイルの在庫の更新

#1

投稿記事 by ぴぴ » 1年前

途中まで書いたのですがエラーがあり、もう少し簡単なコードもあるのではないかと思ってます。
問題文はこちらです。

寄付金の数量を更新する。システムは、従業員が特定の寄付を選択し、受領済みまたは分配済みの数量を示すことができるようにする必要があります。どちらの場合でも、選択された寄付の数量はdonation.txtファイルでそれに応じて更新される必要があります。

例:donation.txt ファイルにあるフェイスマスクの初期数量が100万個であるとします。社会が新しい在庫を受け取った場合、この数量はdonation.txtファイル内の既存の数量100万に追加されなければならない。また、病院への配付の場合は、donation.txt の数量から配付数量を差し引きます。

注:病院に寄付を配布する場合、寄付のコードと配布数をdist.txtという名前のテキストファイルに記録する必要があります。また、各寄付は病院間で共有することができます。

私の書いたコードはこちらなんですが、間違えているところともっといいやり方があれば教えてください。お願いします。

void Received() {
FILE *fp;
fp = fopen("donation.txt", "r+");

struct quantity;

char SupplyCode[6];
char amount[1];

printf("Choose from CT, HS, FM, SM, OM:");
scanf("%s", SupplyCode);
printf("How many do you get:");
scanf("%s", amount);

switch (SupplyCode) {
case 1:
if (strcmp(SupplyCode, "CT") == 0)
quantity.CT = quantity.CT + amount;
break;

case 2:
if (strcmp(SupplyCode, "HS") == 0)
qa.HS = qa.HS + amount;
break;

case 3:
if (strcmp(SupplyCode, "FM") == 0)
qa.FM = qa.FM + amount;
break;

case 4:
if (strcmp(SupplyCode, "SM") == 0)
qa.SM = qa.SM + amount;
break;

case 5:
if (strcmp(SupplyCode, "OM") == 0)
qa.OM = qa.OM + amount;
break;
}
}


void Distributed() {
FILE *fp;
fp = fopen("donation.txt", "r+");

char SupplyCode[6];
char amount;

struct quantity qa;

printf("Choose from CT, HS, FM, SM, OM:");
scanf("%s", SupplyCode);
printf("How many do you send:");
scanf("%s", amount);

switch (SupplyCode) {
case 1:
if (strcmp(SupplyCode, "CT") == 0)
qa.CT = qa.CT - amount;
break;

case 2:
if (strcmp(SupplyCode, "HS") == 0)
qa.HS = qa.HS - amount;
break;

case 3:
if (strcmp(SupplyCode, "FM") == 0)
qa.FM = qa.FM - amount;
break;

case 4:
if (strcmp(SupplyCode, "SM") == 0)
qa.SM = qa.SM - amount;
break;

case 5:
if (strcmp(SupplyCode, "OM") == 0)
qa.OM = qa.OM - amount;
break;
}
}

ぴぴ

Re: テキストファイルの在庫の更新

#2

投稿記事 by ぴぴ » 1年前

ぴぴ さんが書きました:
1年前
途中まで書いたのですがエラーがあり、もう少し簡単なコードもあるのではないかと思ってます。
問題文はこちらです。

寄付金の数量を更新する。システムは、従業員が特定の寄付を選択し、受領済みまたは分配済みの数量を示すことができるようにする必要があります。どちらの場合でも、選択された寄付の数量はdonation.txtファイルでそれに応じて更新される必要があります。

例:donation.txt ファイルにあるフェイスマスクの初期数量が100万個であるとします。社会が新しい在庫を受け取った場合、この数量はdonation.txtファイル内の既存の数量100万に追加されなければならない。また、病院への配付の場合は、donation.txt の数量から配付数量を差し引きます。

注:病院に寄付を配布する場合、寄付のコードと配布数をdist.txtという名前のテキストファイルに記録する必要があります。また、各寄付は病院間で共有することができます。

私の書いたコードはこちらなんですが、間違えているところともっといいやり方があれば教えてください。お願いします。

void Received() {
FILE *fp;
fp = fopen("donation.txt", "r+");

struct quantity qa;

char SupplyCode[6];
char amount[1];

printf("Choose from CT, HS, FM, SM, OM:");
scanf("%s", SupplyCode);
printf("How many do you get:");
scanf("%s", amount);

switch (SupplyCode) {
case 1:
if (strcmp(SupplyCode, "CT") == 0)
qa.CT = qa.CT + amount;
break;

case 2:
if (strcmp(SupplyCode, "HS") == 0)
qa.HS = qa.HS + amount;
break;

case 3:
if (strcmp(SupplyCode, "FM") == 0)
qa.FM = qa.FM + amount;
break;

case 4:
if (strcmp(SupplyCode, "SM") == 0)
qa.SM = qa.SM + amount;
break;

case 5:
if (strcmp(SupplyCode, "OM") == 0)
qa.OM = qa.OM + amount;
break;
}
}


void Distributed() {
FILE *fp;
fp = fopen("donation.txt", "r+");

char SupplyCode[6];
char amount;

struct quantity qa;

printf("Choose from CT, HS, FM, SM, OM:");
scanf("%s", SupplyCode);
printf("How many do you send:");
scanf("%s", amount);

switch (SupplyCode) {
case 1:
if (strcmp(SupplyCode, "CT") == 0)
qa.CT = qa.CT - amount;
break;

case 2:
if (strcmp(SupplyCode, "HS") == 0)
qa.HS = qa.HS - amount;
break;

case 3:
if (strcmp(SupplyCode, "FM") == 0)
qa.FM = qa.FM - amount;
break;

case 4:
if (strcmp(SupplyCode, "SM") == 0)
qa.SM = qa.SM - amount;
break;

case 5:
if (strcmp(SupplyCode, "OM") == 0)
qa.OM = qa.OM - amount;
break;
}
}

アバター
あたっしゅ
記事: 664
登録日時: 13年前
住所: 東京23区
連絡を取る:

Re: テキストファイルの在庫の更新

#3

投稿記事 by あたっしゅ » 1年前

東上☆海美☆「

> 途中まで書いたのですがエラーがあり、もう少し簡単なコードもあるのではないかと思ってます。

排他処理をすると、もっとコードが複雑になると思います。

VTuber:
東上☆海美☆(とうじょう・うみみ)
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。

中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。

ぴぴ

Re: テキストファイルの在庫の更新

#4

投稿記事 by ぴぴ » 1年前

なんでエラーになってるかわかりますか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: テキストファイルの在庫の更新

#5

投稿記事 by みけCAT » 1年前

ソースコードを提示する際は、BBCodeが有効な(無効にしない)状態で、
BBCodeのcodeタグの開始タグと終了タグの組(開始タグが先)で囲んでいただけると、
見やすくてありがたいです。
ぴぴ さんが書きました:
1年前
私の書いたコードはこちらなんですが、間違えているところともっといいやり方があれば教えてください。お願いします。
とりあえずパッと見で致命的に間違っていると考えられるのは
・fopenしたファイルをfcloseしていない
・amountの処理が不適切
・switchの使い方が不適切
ですね。

fopenしたファイルをfcloseしていない

そのまんまです。
開いたファイルは閉じるべきです。
開いたファイルを閉じないと、書き込んだ内容が反映されない場合がある、
並行でファイルを開ける件数を使い切ってしまいファイルが開けなくなる、
などの問題が生じる可能性があります。
fopenが成功したか (返り値がNULLでないか) もチェックするとさらによいでしょう。

amountの処理が不適切

Received関数では

コード:

char amount[1];
scanf("%s", amount);
となっていますが、これでは1文字以上の文字列が入力されると、
C言語では文字列は最後に終端を表すナル文字が追加されるため、
範囲外への書き込みが発生し、意図せずデータを破壊する原因となります。

また、Distributed関数では

コード:

char amount;
scanf("%s", amount);
となっていますが、これは未初期化で不定のamountの値を
読み込んだ文字列を書き込む位置(ポインタ)としてscanf関数に渡すため、
文字列を読み込むとアクセス違反が生じる可能性が高いです。

1文字を読み込むには、書式%cを用います。

コード:

char amount;
scanf("%c", &amount);
ただし、この後の処理を考えると、amountをint型にして書式%dで読み込むほうが自然と考えられます。

コード:

int amount;
scanf("%d", &amount);
scanfの戻り値をチェックし、本当に読み込んだかどうか確認するとさらに良くなるでしょう。

switchの使い方が不適切

SupplyCode (配列 → 先頭要素へのポインタに変換される) をswitchに渡すのは意味が無いと考えられます。
この場合、switch文は削除し、strcmpの返り値による分岐をelse ifで繋げるのがいいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: テキストファイルの在庫の更新

#6

投稿記事 by みけCAT » 1年前

関数の引数として(voidを書かずに)空文字列を指定していることから、このコードはC++でしょうか?
C言語の場合、qaの各メンバの値が初期化されずに計算に使われ、未定義動作になる可能性があります。
C++の場合(開示されていない)struct quantityのコンストラクタなどで初期化されている可能性が考えられるので、
未初期化の値が使われると断定することはできません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

返信

“C言語何でも質問掲示板” へ戻る