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

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

ただいまの
回答率

89.12%

ヒントをください

受付中

回答 3

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,470

rura

score 62

C言語初心者です。2番の商品名検索で商品をキーボードから入力して在庫数を表示したいのだが、
C言語のスキャンフの後にどのようにすればよいのかが思い浮かばず困ってます。
そのまま答えずヒントだけをください。

###該当のソースコード
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 未使用
#define MAXITEM 20

// stock型構造体
typedef struct {
    int  id;                // 商品ID
    char name[64];    // 商品名
    int  quantity;    // 数量
} stock_t;

// グローバル変数
stock_t *stock;    // 後程mallocでメモリ確保
// stock_t stock[100];
int     item_count;

// メニュー表示
void menu(){
    printf("\n");
    printf("### 在庫管理システム ###\n");
    printf("\n");
    printf("1)商品一覧  参照\n");
    printf("2)商品名で在庫数を検索\n");
    printf("3)商品在庫数の増減\n");
    printf("4)新商品の登録機能\\n");
    printf("5)旧商品の削除機能\\n");
    printf("6)商品名の編集機能\\n");
    printf("\n");
    // printf("7)データの保存機能\\n");
    // printf("8)データの読み込み機能\\n");
    // printf("\n");
    printf("9)プログラム終了\n");
    printf("\n");
    printf("メニュー選択(1-9) > ");
}

// 1-numまでの数のキー入力
int read_number(int num){
    int n;
    do {
        scanf("%d", &n);
        while(getchar() != '\n');
    } while ( !(1 <= n && n <= num) );
}

// キー入力待ち
void hit_any_key(){
    printf("\nHit any key.\n");
    while(!getchar());
}

// 在庫一覧表示
void show_list(){
    printf("\n### 在庫一覧 ###\n");
    printf("\n");
    printf(" ID 商品名              数量\n");
    int i;
    for (i = 0; i < item_count; i++){
        printf("%3d %-20s %3d\n", stock[i].id, stock[i].name, stock[i].quantity);
    }
    hit_any_key();
}

// 商品名検索
void search_item(){
    printf("\n### 商品名検索 ###\n");
    printf("\n### 商品名で在庫検索します。 ###\n");


  char productname;//商品名検索用引数
    char productNam;//商品在庫数
    int productNamkye[] = stock.name;
  int product = getchar();
  int prodaut1;


  printf("### 商品名を入力してください ###\n");
  scanf("%s\n", &productname);//商品名をキーボード入力
    printf("商品名 %s\n", productname);

  prodaut1 = strrchr(stock[i].name, product);
    if (product != product) {
          //         printf("商品名 %s はありません\n", productname);
    }else if{
            printf("商品名 %s の在庫数は %d です", productname,productNam);
    }


    hit_any_key();
}

// 在庫数増減
set_quantity(){
    printf("\n### 在庫数増減 ###\n");
    hit_any_key();
}

// 新商品登録
create_new_item(){
    printf("\n### 新商品登録 ###\n");
    hit_any_key();
}

// 旧商品削除
destroy_old_item(){
    printf("\n### 旧商品削除 ###\n");
    hit_any_key();
}

// 商品名編集
edit_item_name(){
    printf("\n### 商品名編集 ###\n");
    hit_any_key();
}


// ファイルから読み込んだ文字列を返す(未使用)
char *read_text_file(char const *filename){
    // 変数宣言
    FILE *fp = NULL;
    char *str = NULL;
    char buffer[256];
    int  fsize;                    // ファイルサイズ

    // 読み取りモードでファイルを開く
    fp = fopen(filename, "r");
    if (fp == NULL){
        printf("Can't read '%s'\n", filename);
        exit(1);
    }

    // ファイルサイズの取得
    fseek(fp, 0L, SEEK_END);
    fsize = ftell(fp);
    // printf("fsize: %d\n", fsize);

    // メモリの動的確保
    str = (char*)malloc(fsize * sizeof(char));
    if (str == NULL){
        printf("Can't allocate memory. 'str' is NULL.\n");
        fclose(fp);
        exit(1);
    }

    // シーク位置を先頭に戻す
    fseek(fp, 0L, SEEK_SET);

    // テキストデータの読み込み
    str[0] = '\0';
    while (fgets(buffer, sizeof(buffer), fp) != NULL){
        strncat(str, buffer, strlen(buffer) + 1);
    }

    // ファイルクローズ
    fclose(fp);

    // 読み込んだ文字列を返す
    return str;

}

// ファイルから読み込んだレコードを、構造体に格納する
// 戻り値は、レコード数
int load_data_file(char const *filename){
    // 変数宣言
    FILE *fp = NULL;
    char buffer[256];
    int line_count;                    // 行数

    // 読み取りモードでファイルを開く
    fp = fopen(filename, "r");
    if (fp == NULL){
        printf("Can't read '%s'\n", filename);
        exit(1);
    }

    // 行数の取得
    // fseek(fp, 0L, SEEK_END);
    // fsize = ftell(fp);
    line_count = 0;
    while (fgets(buffer, sizeof(buffer), fp) != NULL){
        line_count++;
    }

    // メモリの動的確保
    stock = (stock_t*)malloc(line_count * sizeof(stock_t));
    // stock_t stock[5];

    if (stock == NULL){
        printf("Can't allocate memory. 'stock' is NULL.\n");
        fclose(fp);
        exit(1);
    }

    // シーク位置を先頭に戻す
    fseek(fp, 0L, SEEK_SET);

    // データの読み込み
    int i = 0;
    char *outlist[3];
    while (fgets(buffer, sizeof(buffer), fp) != NULL){
        // strncat(str, buffer, strlen(buffer) + 1);
        // 一行分bufferに読み込んだので、分離して、構造体に格納する
        split(buffer, ",", outlist);
        stock[i].id = atoi(outlist[0]);                // id
        strcpy(stock[i].name, outlist[1]);        // name
        stock[i].quantity = atoi(outlist[2]);    // quantity
        i++;
    }

    // ファイルクローズ
    fclose(fp);

    // 読み込んだ行数を返す(=構造体の要素数)
    return i;
}


// 区切り文字で分離する
int split(char *str, char const *delimiter, char *outlist[]){
        char *token;
        int  count = 0;

        token = strtok(str, delimiter);
        while (token != NULL && count < MAXITEM){
            outlist[count++] = token;
            // outlist[count] = token;
            // count++;
            token = strtok(NULL, delimiter);
        }

        return count;
}

int main(int argc, char const *argv[]) {
    int  i, count;

    // カンマ区切りサンプル
    char memo_str[] = "Milk, Eggs:Bread, Apple, Cheese";
    char *shopping_list[MAXITEM];
    // 処理前
    // printf("memo_str: %s\n", memo_str);
    // 区切り文字で分離する
    count = split(memo_str, ",:", shopping_list);
    // 結果表示
    for (i = 0; i < count; i++){
        // printf("%d: %s\n", i, shopping_list[i]);
    }

    // ファイルからの文字列読み込みサンプル
    char *data;
    data = read_text_file("stock_db.txt");
    // 結果表示
    // printf("stock_db.txt を読み込みました\n");
    // printf("%s\n", data);
    // malloc で確保したdataの解放
    free(data);

    //
    // ##### 本番 #####
    //

    int n;
    // データファイルの読み込み
    item_count = load_data_file("stock_db.txt");

    // メニュー表示繰り返し
    while(1){
        menu();
        n = read_number(9);
        switch (n){
            case 1:
                // printf("在庫一覧\n");
                show_list();
                break;
            case 2:
                // printf("商品名検索\n");
                search_item();
                break;
            case 3:
                // printf("在庫数増減\n");
                set_quantity();
                break;
            case 4:
                // printf("新商品登録\n");
                create_new_item();
                break;
            case 5:
                // printf("旧商品削除\n");
                destroy_old_item();
                break;
            case 6:
                // printf("商品名編集\n");
                edit_item_name();
                break;
            case 7:
                // printf("保存\n");
                // break;
            case 8:
                // printf("読み込み\n");
                // break;
            case 9:
                printf("プログラムを終了します\n");
                // malloc で確保した領域の解放
                free(stock);
                exit(1);
                break;
        }
    }

    return 0;
}

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

より詳細な情報
C言語、ATOM、構造体

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • masaya_ohashi

    2016/06/09 14:19

    ソースコードを```(Shift+@で出る`を3つつなげたもの)で囲んでください。コードが見やすくなります。

    キャンセル

  • rura

    2016/06/09 15:44

    分からないなりにやりましたが、どうでしょうか?

    キャンセル

  • masaya_ohashi

    2016/06/09 15:49

    質問文を修正してくださいという意味です。質問文に書くソースコードは```で囲んでやると、色がついたりフォントが等幅になって見やすくなるのです。質問文のエディタに</>というボタンが上のあたりにあります。「該当のソースコード」以下のコード部分をマウスで選択したあとに</>のボタンを押してください。

    キャンセル

  • rura

    2016/06/09 16:33

    まだテラテイルさんを使い始めて1週間ですが、こういうことなのですね

    キャンセル

回答 3

+1

こんにちは。

ソースの表示が見にくいため、ざっとしか見ていませんので気がついた点のヒントだけ。(masaya_ohashiさんの指摘通りにして頂けると見やすくできますよ。)

商品名をscanf()で入力していますね。商品名は何文字まで可能ですか?
現在のプログラムはscanf()で入力できる文字数は0文字です。その後の処理もこれが原因で間違った標準ライブラリ関数を使っているようです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/06/09 16:18

    商品番号 商品名  個数  
    1,     yasai,   10
    2,     niku,   100
    回答ありがとうございます。
    商品名の文字分だけ可能です。

    キャンセル

  • 2016/06/09 16:20 編集

    商品名ですが、それならば10文字までにします。

    キャンセル

  • 2016/06/09 16:31

    > 商品名の文字分だけ可能です。

    それは何文字ですか? 具体的な数字が判らないとプログラムできませんよ。

    > char productname;//商品名検索用引数

    scanf()で商品名を上記変数へ読み込んでいますね? この変数が記録できる文字数のことです。C言語の文字列はNULL終端していることはご存知ですね?

    それから、コメントにソースを貼り付けるのは止めましょう。インデントがなくなるので更に見難くなります。質問を編集して下さい。
    </>は手で入力するのではありません。masaya_ohashiさんのアドバスを良く読んで下さい。これ以上分かりやすい表現を私は思いつきませんので、頑張ってください。

    キャンセル

  • 2016/06/09 17:01

    > 商品名ですが、それならば10文字までにします。

    ということは、下記変数で10文字記録できるようにする必要はないですか?

    > char productname;//商品名検索用引数

    ところで、質問に見えてしまったようですね。すいません。
    正しいプログラムにするにはどのように変更するべきかについて考えるべき点を指摘しているつもりです。(全部ではないです。他にもあるかも知れません。)
    私の質問に直接答えるのではなく、私の質問の周辺にUmemuraYukaさんのプログラムは間違いがあるとご理解下さい。

    キャンセル

0

ヒント:charは文字列型ではない。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

気になったところをコメントいたします。
Chironian様と被っている箇所はご了承ください。

printf("### 商品名を入力してください ###\n");
scanf("%s\n", &productname);/*商品名をキーボード入力*/   ← productnameはchar型ですが大丈夫でしょうか?
printf("商品名 %s\n", productname);  ←productnameはchar型に対し%sですが大丈夫でしょうか

prodaut1 = strrchr(stock[i].name, product); ←「文字列」から「文字」を検索していますが大丈夫でしょうか
if (product != product) { ← productとproduct 同じものを比較していますが大丈夫でしょうか
 // printf("商品名 %s はありません\n", productname);
}else if{
    printf("商品名 %s の在庫数は %d です", productname,productNam); ←productnameはchar型に対し%sですが大丈夫でしょうか
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 89.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる