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

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

ただいまの
回答率

89.06%

listでinsert文を挿入したいのですが、上手くデータが挿入されません

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,293

sanchu52

score 179

http://ppp-lab.sakura.ne.jp/ProgrammingPlacePlus/algorithm/data_struct/003.html#library
にあるlistのプログラムで要素を挿入するinsert_elem()文があるのですが、
listのプログラムに組み込んで動作させたいのですが、上手くデータが挿入されません。
どこが悪いのでしょうか。教えてください。下が私が書き変えたコードです。

コード
> 
//単方向線形リスト 

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

// コマンド 
enum Cmd_tag {
    CMD_ADD,
    CMD_INSERT,
    CMD_DELETE,
    CMD_SEARCH,
    CMD_CLEAR,
    CMD_PRINT,
    CMD_EXIT,

    CMD_NUM
};

// コマンド文字列の種類 
enum CmdStr_tag {
    CMD_STR_SHORT,
    CMD_STR_LONG,

    CMD_STR_NUM
};

// コマンドの戻り値 
enum CmdRetValue_tag {
    CMD_RET_VALUE_CONTINUE,
    CMD_RET_VALUE_EXIT,
};

// コマンド文字列 
static const char* const CMD_STR[CMD_NUM][CMD_STR_NUM] = {
    { "a", "add" },
    { "i", "insert" },
    { "d", "delete" },
    { "s", "search" },
    { "c", "clear" },
    { "p", "print" },
    { "e", "exit" }
};

static void init_head(void);
static void print_explain(void);
static void print_blank_lines(void);
static enum CmdRetValue_tag get_cmd(void);
static enum CmdRetValue_tag cmd_add(void);
static enum CmdRetValue_tag cmd_insert(void);
static enum CmdRetValue_tag cmd_delete(void);
static enum CmdRetValue_tag cmd_search(void);
static enum CmdRetValue_tag cmd_clear(void);
static enum CmdRetValue_tag cmd_print(void);
static enum CmdRetValue_tag cmd_exit(void);
static void add_elem_front
(int value);
static int insert_elem(int value,int pos);
static int delete_elem(int value);
static void clear_list(void);
static void print_list(void);
static struct LinkedList_tag* search_elem(int value);
static void get_line(char* buf, size_t size);

// コマンド実行関数 
typedef enum CmdRetValue_tag (*cmd_func)(void);
static const cmd_func CMD_FUNC[CMD_NUM] = {
    cmd_add,
    cmd_insert,
    cmd_delete,
    cmd_search,
    cmd_clear,
    cmd_print,
    cmd_exit
};

// 連結リスト型 
struct LinkedList_tag {
    int                         value;
    struct LinkedList_tag*      next;
};

static struct LinkedList_tag gHead;  

int main(void)
{
    init_head();
    //グローバル変数gHead のメンバを初期化しています。 

    while( 1 ){
        print_explain();

        if( get_cmd() == CMD_RET_VALUE_EXIT ){
            break;
        }

        print_blank_lines();
    }

    return 0;
}

// 先頭要素を初期化 
void init_head(void)
{
    gHead.value = 0;
    gHead.next = NULL;

}

//    説明文を出力
void print_explain(void)
{
    puts( "コマンドを入力して下さい。" );
    printf( " 連結リストに要素を追加する: %s (%s)\n", CMD_STR[CMD_ADD][CMD_STR_SHORT], CMD_STR[CMD_ADD][CMD_STR_LONG] );
    printf( " 連結リストに要素を挿入する: %s (%s)\n", CMD_STR[CMD_INSERT][CMD_STR_SHORT], CMD_STR[CMD_INSERT][CMD_STR_LONG] );
    printf( " 連結リストから要素を削除する: %s (%s)\n", CMD_STR[CMD_DELETE][CMD_STR_SHORT], CMD_STR[CMD_DELETE][CMD_STR_LONG] );
    printf( " 連結リストから要素を探す: %s (%s)\n", CMD_STR[CMD_SEARCH][CMD_STR_SHORT], CMD_STR[CMD_SEARCH][CMD_STR_LONG] );
    printf( " 連結リストを空にする: %s (%s)\n", CMD_STR[CMD_CLEAR][CMD_STR_SHORT], CMD_STR[CMD_CLEAR][CMD_STR_LONG] );
    printf( " 連結リストの中身を出力する: %s (%s)\n", CMD_STR[CMD_PRINT][CMD_STR_SHORT], CMD_STR[CMD_PRINT][CMD_STR_LONG] );
    printf( " 終了する: %s(%s)\n", CMD_STR[CMD_EXIT][CMD_STR_SHORT], CMD_STR[CMD_EXIT][CMD_STR_LONG] );
    puts( "" );
}

//空白行を出力
void print_blank_lines(void)
{
    puts( "" );
    puts( "" );
}

//コマンドを受け付ける
enum CmdRetValue_tag get_cmd(void)
{
    char buf[20];
    enum Cmd_tag cmd;
    int i;

    get_line( buf, sizeof(buf) );
    //print_explain()の中から
    //コマンドを選ぶ

    cmd = CMD_NUM;    //
    for( i = 0; i < CMD_NUM; ++i ){
        if( strcmp( buf, CMD_STR[i][CMD_STR_SHORT] ) == 0
         || strcmp( buf, CMD_STR[i][CMD_STR_LONG] ) == 0
        ){
            cmd = i;   //ここでコマンドを受け取る
            break;
        }
    }

    if( 0 <= cmd && cmd < CMD_NUM ){
        return CMD_FUNC[i]();
        //コマンドを返している
    }
    else{
        puts( "そのコマンドは存在しません。" );
    }

    return CMD_RET_VALUE_CONTINUE;
    //そのコマンドは存在しないときはget_cmdを続ける
}

//addコマンドの実行
enum CmdRetValue_tag cmd_add(void)
{
    char buf[40];
    int value;

    puts( "追加する数値データを入力して下さい。" );
    fgets( buf, sizeof(buf), stdin );
    sscanf( buf, "%d", &value );
    //文字列bufから書式format( "%d")にしたがって、
    //scanf関数と同様の変換を行った入力を、
    //指定されたアドレス(&value )に格納します。

    add_elem_front( value );
    //要素を追加する

    return CMD_RET_VALUE_CONTINUE;
}

//insertコマンドの実行
enum CmdRetValue_tag cmd_insert(void)
{
    char buf[40],buf2[40];
    int value,pos;

    puts( "挿入する数値データを入力して下さい。" );
    fgets( buf, sizeof(buf), stdin );
    sscanf( buf, "%d", &value );
    //文字列bufから書式format( "%d")にしたがって、
    //scanf関数と同様の変換を行った入力を、
    //指定されたアドレス(&value )に格納します。
    puts( "挿入する数値データをどこの数値の後に入力するか入力して下さい。" );
    fgets( buf, sizeof(buf), stdin );
    sscanf( buf2, "%d", &pos );

    insert_elem( value,pos);
    //要素を挿入する

    return CMD_RET_VALUE_CONTINUE;
}

//deleteコマンドの実行
enum CmdRetValue_tag cmd_delete(void)
{
    char buf[40];
    int value;

    puts( "削除する数値データを入力して下さい。" );
    fgets( buf, sizeof(buf), stdin );
    sscanf( buf, "%d", &value );

    if( delete_elem(value) >= 1 ){
        puts( "要素を削除しました。" );
    }
    else{
        puts( "削除する要素は見つかりませんでした。" );
    }

    return CMD_RET_VALUE_CONTINUE;
}

//searchコマンドの実行
enum CmdRetValue_tag cmd_search(void)
{
    char buf[40];
    int value;

    puts( "探索する数値データを入力して下さい。" );
    fgets( buf, sizeof(buf), stdin );
    sscanf( buf, "%d", &value );

    if( search_elem(value) == NULL ){
        printf( "%d は連結リスト中に存在しません。\n", value );
    }
    else{
        printf( "%d は連結リスト中に存在します。\n", value );
    }

    return CMD_RET_VALUE_CONTINUE;
}

//clearコマンドの実行
enum CmdRetValue_tag cmd_clear(void)
{
    clear_list();

    return CMD_RET_VALUE_CONTINUE;
}

//printコマンドの実行
enum CmdRetValue_tag cmd_print(void)
{
    print_list();

    return CMD_RET_VALUE_CONTINUE;
}

//exitコマンドの実行
enum CmdRetValue_tag cmd_exit(void)
{
    puts( "終了します。" );

    return CMD_RET_VALUE_EXIT;
}

//    要素を追加する
//    引数:
//        value:    追加する要素の数値データ。
void add_elem_front(int value)
{
    struct LinkedList_tag* elem;//新しいデータの先頭アドレス

    // 追加する要素を作る 
    elem = malloc( sizeof(struct LinkedList_tag) );
    if( elem == NULL ){
        fputs( "メモリ割り当てに失敗しました。", stderr );
        exit( 1 );
    }
    elem->value = value;
    elem->next = gHead.next;
    // 先頭に追加するといっても、ダミーの先頭要素よりも手前に置くのではなくて、
    // ダミーの直後に挿入します。 
    // ダミーが持つ nextポインタの値を、追加する要素の nextポインタに代入し、 
    // ダミーの nextポインタは、追加した要素を指すように書き換えます。 

    gHead.next = elem;
    // ダミーの先頭要素の次は、追加した要素になる 
}

//    要素を挿入する
//    引数:
//        value:    挿入する要素の数値データ。
//      pos  :  挿入場所の前の数値データ。この値の直後に挿入する
int insert_elem(int value,int pos)
{
    struct LinkedList_tag* p;
    struct LinkedList_tag* elem;

    // 挿入位置を探す 
    p = search_elem(pos);
    if( p == NULL ){
        return 0;
    }

    // 挿入する要素を作る 
    elem = malloc( sizeof(struct LinkedList_tag) );
    if( elem == NULL ){
        fputs( "メモリ割り当てに失敗しました。", stderr );
        exit( 1 );
    }
    elem->value = value;
    elem->next = p->next;  // p と p->next の隙間に挿入する 

    p->next = elem;

    return 1;
}

int delete_elem(int value)
{
    struct LinkedList_tag* p = gHead.next;
    struct LinkedList_tag* prev = &gHead;

    int count = 0;

    while( p != NULL ){
        if( p->value == value ){
            prev->next = p->next;
            free( p );
            p = prev->next;
            ++count;
        }
        else{
            prev = p;
            p = p->next;
        }
    }

    return count;
}


//要素を空にする
void clear_list(void)
{
    struct LinkedList_tag* p = gHead.next;
    struct LinkedList_tag* prev = &gHead;

    while( p != NULL ){
        prev->next = p->next;

        free( p );

        p = prev->next;

    }
}

//要素を出力する
void print_list(void)
{
    struct LinkedList_tag* p = gHead.next;

    if( p == NULL ){
        puts( "リストは空です。" );
        return;
    }

    while( p != NULL ){
        printf( "%d\n", p->value );
        p = p->next;
    }
}



struct LinkedList_tag* search_elem(int value)
{
    struct LinkedList_tag* p = gHead.next;
  while( p != NULL ){
        if( p->value == value ){
            return p;
        }
        p = p->next;
    }

    return NULL;
}

void get_line(char* buf, size_t size)
{
    fgets(buf, size, stdin);

    char* p = strchr(buf, '\n');

    if (p != NULL) {
        *p = '\0';
    }
}

 実行結果
naka@naka ~/kadai/kadai9-8
$ gcc -o LST15 LST15.c -Wall

naka@naka ~/kadai/kadai9-8
$  LST15
a
追加する数値データを入力して下さい。
4
コマンドを入力して下さい。
 連結リストに要素を追加する: a (add)
 連結リストに要素を挿入する: i (insert)
 連結リストから要素を削除する: d (delete)
 連結リストから要素を探す: s (search)
 連結リストを空にする: c (clear)
 連結リストの中身を出力する: p (print)
 終了する: e(exit)

a
追加する数値データを入力して下さい。
5
コマンドを入力して下さい。
 連結リストに要素を追加する: a (add)
 連結リストに要素を挿入する: i (insert)
 連結リストから要素を削除する: d (delete)
 連結リストから要素を探す: s (search)
 連結リストを空にする: c (clear)
 連結リストの中身を出力する: p (print)
 終了する: e(exit)
a
追加する数値データを入力して下さい。
9


コマンドを入力して下さい。
 連結リストに要素を追加する: a (add)
 連結リストに要素を挿入する: i (insert)
 連結リストから要素を削除する: d (delete)
 連結リストから要素を探す: s (search)
 連結リストを空にする: c (clear)
 連結リストの中身を出力する: p (print)
 終了する: e(exit)

p
9
5
4


コマンドを入力して下さい。
 連結リストに要素を追加する: a (add)
 連結リストに要素を挿入する: i (insert)
 連結リストから要素を削除する: d (delete)
 連結リストから要素を探す: s (search)
 連結リストを空にする: c (clear)
 連結リストの中身を出力する: p (print)
 終了する: e(exit)

i
挿入する数値データを入力して下さい。
6
挿入する数値データをどこの数値の前に入力するか入力して下さい。
5
コマンドを入力して下さい。
 連結リストに要素を追加する: a (add)
 連結リストに要素を挿入する: i (insert)
 連結リストから要素を削除する: d (delete)
 連結リストから要素を探す: s (search)
 連結リストを空にする: c (clear)
 連結リストの中身を出力する: p (print)
 終了する: e(exit)

p
9
5
4
変化なし(6が挿入されない)


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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

check解決した方法

0

//insertコマンドの実行
enum CmdRetValue_tag cmd_insert(void)
{
char buf[40],buf2[40];
int value,pos;

puts( "挿入する数値データを入力して下さい。" );
fgets( buf, sizeof(buf), stdin );
sscanf( buf, "%d", &value );
//文字列bufから書式format( "%d")にしたがって、
//scanf関数と同様の変換を行った入力を、
//指定されたアドレス(&value )に格納します。
puts( "挿入する数値データをどこの数値の後に入力するか入力して下さい。" );
fgets( buf, sizeof(buf), stdin );
sscanf( buf2, "%d", &pos );

insert_elem( value,pos);
//要素を挿入する

return CMD_RET_VALUE_CONTINUE;
}
の下から6行目fgets( buf, sizeof(buf), stdin );をfgets( buf2, sizeof(buf), stdin );に変更しました。単純なミスでした。それでも1日かかりました。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

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

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

関連した質問

同じタグがついた質問を見る