複数の構造体について

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

Re: 複数の構造体について

#61

投稿記事 by 小岩井 » 6年前

コード:

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

struct Student_Entry
{
    char number[10];
    int count;
    struct Student_Entry *next;
    struct Date_Entry *datelist;
};


struct Date_Entry
{
    char year[10];
    char month;
    char day;
    struct Date_Entry *next;
};




struct Student_Entry *addStudent(char *addnumber, struct Student_Entry *ptr,int a)
{
    struct Student_Entry *p;
    p = (struct Student_Entry *)malloc(sizeof(struct Student_Entry));
    strcpy(p->number,addnumber);
    p->next = NULL;        

    int j;
    int tmp;
    for(j=0;j<a;j++,a++)
    {
        int n;
        if (n = strcmp(ptr->number,(ptr+1)->number) != 0)
        {
            tmp = *ptr->number;
            *ptr->number = *(ptr+1)->number;
            *(ptr+1)->number = tmp;
            return ptr;
        }
    }
    if(ptr == NULL)
    {
        return p;    
    }
    else
    {
        struct Student_Entry *q = ptr;        
        while (q->next != NULL)
        {            
            q = q->next;        
        }                    
        q->next = p;               
        return ptr;    
    }        
}


struct Date_Entry* addDate(char date[], struct Date_Entry *ptr)
{
    
    struct Date_Entry *p;
    p = (struct Date_Entry *)malloc(sizeof(struct Date_Entry));
    strcpy(p->year,date);
    p->next  = NULL;


    if(ptr == NULL)
    {
        p->next = NULL;
        return p;
    }
    else
    {
        struct Date_Entry *q = ptr;
        while(q->next != NULL)
        {
            q = q->next;
        }
        q->next = p;
        return ptr;
    }
}


void dispStudent (struct Student_Entry *ptr)
{
    while(ptr != NULL)
    {
        printf("%s\n", ptr -> number);
        ptr = ptr -> next;
    }
}

void dispDate(struct Date_Entry *ptr)
{
    while(ptr != NULL)
    {
        printf("%s\n", ptr-> year);
        ptr = ptr->next;
    }
}

 
int main()
{
    FILE *fp;
    char buffer[1024];
    
    struct Student_Entry *StudentList = NULL;
    struct Date_Entry *DateList = NULL;
    DateList  = (struct Date_Entry *)malloc(sizeof(struct Date_Entry));
    int a;


    fp = fopen("text.txt", "r"); 
    while(fscanf(fp, "%s", buffer) != EOF)
    {
        if(buffer[0]=='B')
        {
             StudentList = addStudent(buffer,StudentList,a);
        }
    }
    dispStudent(StudentList);
    fclose(fp);	
    return 0;
}
とりあえず文字列の比較まで見様見真似でやってみました。
比較する出席番号が同じでない場合の場合分けです。
実行結果は

コード:

B0000064
B0000005
B0000064
B0000005
B0000094
B0000117
B0000117
になりました。
if(buffer[0] == 'B')のところを!=に変えると日付が出てきます(日付はもちろん重複しません)。
比較したときの場合分けがうまく入ったと思ったのですが、出力結果を見るかぎりそうでもないようです...。
返り値の値が不適切なためだと私は推測しています。
参考にしたページはhttp://dixq.net/forum/viewtopic.php?f=3&t=13101です。
そのページのnumbersort関数を参考に追加してみましたが、型の不一致(参考ページはint、課題はchar)もうまくいかなかった原因のひとつでしょうか?

アバター
usao
記事: 1546
登録日時: 6年前

Re: 複数の構造体について

#62

投稿記事 by usao » 6年前

なんかもう 悪夢の様相を呈してきていますね…

addStudent()の引数aは一体何なのか?
34行目から始まるforループは何をしたいのか?
ここに来たとき,aの値はいくつで,この先どうなってしまうのか…

どこかのコードを「参考にする」には,
・そのコードのやっていることを完全に理解し,
・自分の問題に流用できる 処理方法やコーディング方法 は何か? を判断したうえで,
・自分の問題に見合う形にきちんと修正して取り込む
ことが必要ではないでしょうか. 参考=中途半端にコピペしてくること ではないと思います.

どの助言に耳を傾けるか の取捨選択は小岩井さんの自由ですが,
私は再度 以下の事柄をお勧めしておきます.
>ばかばかしいと思われるかもしれませんが,
>自身が書いたコードに存在する個々の要素(関数,構造体,変数)毎に,
>・それがなんなのか(役割.何のために必要で用意したのか)
>を書いてみると 頭の中の整理の助けになったりしないでしょうか?
特に,各関数内の変数の役割や 処理の意味 を自分で書いてみることです.
前述した addStudent() の引数aの役割を説明できますか?
「自分で考えた処理内容をコーディングしている」のだから,自分で説明できない要素が
その中に出てくるはずはないのです.普通は.


とりあえず ごく普通に addStudent()でやるべき処理を 考えたならば,私なら
  既存リストの要素の学籍番号と,追加しようとしている学籍番号とを
  strcmp()で比較した結果=戻り値 の値から,
   (case1)ここはまだ追加場所ではない→次の要素へ
   (case2)ちょうどここに追加すればいいようだ→ここに追加
   (case3)この学籍番号は既にリストにあるようだ→追加しない
  という3通りに分岐することになるだろうな,
とかと思うわけです.そしたら,その流れをコード化すれば良いわけで…

non
記事: 1097
登録日時: 8年前

Re: 複数の構造体について

#63

投稿記事 by non » 6年前

今日、明日は忙しいのでusaoさんにパス。しっかり絵を書いてくださいね。とても書いているとは思えないから。
non

かずま

Re: 複数の構造体について

#64

投稿記事 by かずま » 6年前

struct Student_Entry の count は何?
struct Date_Entry で、char year[10]; char month; char day; となっているのはなぜ?
ptrが配列の要素を指しているわけでもないので、ptr+1 は意味がありません。

次のサンプルを完璧に理解できますか?

コード:

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

struct Node {
    char name[10];
    struct Node *next;
};

struct Node *addName(struct Node *head, char *name)
{
    struct Node *node, *cur, *pre;
    for (cur = head; cur != NULL; cur = cur->next) {
        int diff = strcmp(cur->name, name);
        if (diff > 0) break;  // 挿入場所が見つかったのでループを抜ける
        if (diff == 0) {  // 既に存在するのが見つかった
            // やるべきことをやる
            return head;
        }
        pre = cur;
    }
    node = malloc(sizeof(struct Node));  // リストにはなかったので追加
    strcpy(node->name, name);
    // やるべきことをやる
    node->next = cur;  // node に cur をつなぐ
    if (cur == head) return node;  // node が新たなリストの先頭
    pre->next = node;  // pre に node をつなぐ
    return head;       // head がリストの先頭
}

void printList(struct Node *head)
{
    struct Node *cur;
    for (cur = head; cur != NULL; cur = cur->next)
        printf("%s\n", cur->name);
}

int main(void)
{
    char name[10];
    struct Node *nameList = NULL;

    while (scanf("%9s", name) == 1)
        nameList = addName(nameList, name);
    printList(nameList);
    return 0;
}
実行結果

コード:

kiko   (入力)
mako
kako
mako
kiko
^Z     (Windows なら行頭で Ctrl+Z、Linux なら行頭で Ctrl+D で入力終わり)
kako   (出力)
kiko
mako

小岩井

Re: 複数の構造体について

#65

投稿記事 by 小岩井 » 6年前

すみません、遅くなりました…。
かずまさんのサンプルをそのまま使用させていただきました。

コード:

#include <stdio.h>
#include <stdlib.h>
 
struct Node {
    char name[10];
    struct Node *next;
};
 
struct Node *addName(struct Node *head, char *name)
{
    struct Node *node, *cur, *pre;
    for (cur = head; cur != NULL; cur = cur->next) {
        int diff = strcmp(cur->name, name);
        if (diff > 0) break;  // 挿入場所が見つかったのでループを抜ける
        if (diff == 0) {  // 既に存在するのが見つかった
            // 日付を返す?
            return head;
        }
        pre = cur;
    }
    node = malloc(sizeof(struct Node));  // リストにはなかったので追加
    strcpy(node->name, name);
    node->next  = node; //追加部分
    node->next = cur;  // node に cur をつなぐ
    if (cur == head) return node;  // node が新たなリストの先頭
    pre->next = node;  // pre に node をつなぐ
    return head;       // head がリストの先頭
}
 
void printList(struct Node *head)
{
    struct Node *cur;
    for (cur = head; cur != NULL; cur = cur->next)
        printf("%s\n", cur->name);
}
 
int main(void)
{
    char name[10];
    struct Node *nameList = NULL;
 
    while (scanf("%9s", name) == 1)
        nameList = addName(nameList, name);
    printList(nameList);
    return 0;
}
新しいnodeが指す先は既存のnodeの次に加えればいいので、node->next = nodeとしました。
既にあった場合はそのときの日付を返せばいいのかなあ、と思いましたが日付のリストがないし、
追加しなければいいのでループから出ればいいのでは、とも考えたのですがその時返すものがないのでいよいよわからなくなりました…。
かずまさんのサンプルは理解できました!ありがとうございます。

かずま

Re: 複数の構造体について

#66

投稿記事 by かずま » 6年前

小岩井 さんが書きました: 新しいnodeが指す先は既存のnodeの次に加えればいいので、node->next = nodeとしました。
全く理解されていなくて悲しい。

head は、既存のリストの先頭のノードを指すポインタ。
cur は、既存のリストの各ノードを先頭から順に指していくポインタ。
pre は、cur の指すノードの一つ前のノードを指すポインタ。
node は、新しく確保したノードを指すポインタ。

新しいノード node は、既存のノード pre と既存のノード cur の間に
挿入しなければなりません。
それが、node->next = cur; と pre->next = node; です。
ただし、node が新しいリストの先頭になるときは、
pre->next = node; は要らないから
if (cur == head) return node; が間にあるのです。

ところで、

node->next = node;
node->next = cur;

ですが、node->next という「同じ変数」に、連続して異なる値を代入しても
最初の代入に意味がないことに気づかないのが不思議でなりません。
なぜそんなことを平気で書くのですか?

他の質問にも答えてください。
- addStudent() の引数 a は何?
- struct Student_Entry の count は何?
- struct Date_Entry の char year[10] は何?
- (p+1)->number の p+1 は何?

小岩井

Re: 複数の構造体について

#67

投稿記事 by 小岩井 » 6年前

かずま さんが書きました: node->next = node;
node->next = cur;

ですが、node->next という「同じ変数」に、連続して異なる値を代入しても
最初の代入に意味がないことに気づかないのが不思議でなりません。
なぜそんなことを平気で書くのですか?
リストを辿っていき、比較している番号がすでにあったらそのとき先頭を示しているポインタの次に追加すればいいと思いそのように書きました。
先頭を示すポインタが何であるかをきっちりわかっていませんでした。
かずま さんが書きました: 他の質問にも答えてください。
- addStudent() の引数 a は何?
- struct Student_Entry の count は何?
- struct Date_Entry の char year[10] は何?
- (p+1)->number の p+1 は何?
参考サイトのプログラムを特に理解もせずそのまま写したので皆さんにご迷惑おかけしました……。
(p+1)はポインタpのさす次のノードのつもりでした。
夜遅くにごめんなさい……。

アバター
usao
記事: 1546
登録日時: 6年前

Re: 複数の構造体について

#68

投稿記事 by usao » 6年前

>usaoさんにパス
どうやら私は 取捨選択の「捨」の側に分類されているように見受けられるので パス先としては無理ではないかとw
(でも他の方がそのパスを受けてくれた模様)

…というのは まぁ 半分冗談としても
「理解しよう」という意気込みというか姿勢がどうにも見られないようなので,個人的にはもう無理(無駄?)かな,とか.
(私はこの掲示板を見るようになって日は浅いですが,これまでのやりとりの雰囲気から)
この掲示板は「わかんないけど動けばOK」の達成を手伝う場ではない…んだろうな,と感じているので.

小岩井

Re: 複数の構造体について

#69

投稿記事 by 小岩井 » 6年前

usao さんが書きました:>usaoさんにパス
どうやら私は 取捨選択の「捨」の側に分類されているように見受けられるので パス先としては無理ではないかとw
(でも他の方がそのパスを受けてくれた模様)

…というのは まぁ 半分冗談としても
「理解しよう」という意気込みというか姿勢がどうにも見られないようので,個人的にはもう無理(無駄?)かな,とか.
(私はこの掲示板を見るようになって日は浅いですが,これまでのやりとりの雰囲気から)
この掲示板は「わかんないけど動けばOK」の達成を手伝う場ではない…んだろうな,と感じているので.
決してそんなつもりはありません。なぜ動かないか、リスト構造の仕組みなどをここで教わりつつ理解できたらと思っています。
usaoさんの助言のおかげで頭のなかは整理できました。ありがとうございます。

ここでの私の行いを振り返るとまわりに聞いてばかりで、自分でろくに考えていませんでした。これでは理解しようという態度もないに等しいですよね。
これ以上皆さんに迷惑はかけたくないので、途中ではありますがここで解決にしたいと思います。
残りは自力で考えます。
本当にご迷惑をおかけしました。指摘、助言などしてくださった方々、ありがとうございました。

アバター
usao
記事: 1546
登録日時: 6年前

Re: 複数の構造体について

#70

投稿記事 by usao » 6年前

迷惑だ,とか 何で俺の言うのことを聞かないんだ! とか言ってるわけではなく
あまつさえあなたを排除しよう とかいう意図があるわけではないので その点は誤解なきよう.

ただ,多くの方が回答してくれているのに,その内容がほとんど反映されることもなく
むしろ他所からの部分コピペと思われる記述が追加されていく, という状況が謎というか,
だったら何で訊いたの? っていうか…うまく言えないけどそんな感じです.
仮に,もらった回答の内容がよくわからないのであれば,そのことについて
「ちょっとここが何言ってるかわからないです.もっと詳しく教えてください」とかいった方向で再度質問するなりして
とにかく問題点を一個一個解決していけば進展すると思うのですが
なんかというか,不明点が不明なまま次に進んでしまっていて,全体として進展がほとんどないように見受けられます.

続けるのも打ち切るのも自由ですが,どちらにせよ
多くの方に回答して頂いた内容を再度丁寧に読み返してみるとよいかと思います.
(提出期限がある状況下では,私が書いてきたような 急がば回れ 的な話は,
 不親切でかえって迷惑なものに感じられるかもしれませんが…)

ISLe
記事: 2645
登録日時: 8年前
連絡を取る:

Re: 複数の構造体について

#71

投稿記事 by ISLe » 6年前

「好き」の反対は「嫌い」ではなく「無関心」。

「分かりませんでした」は「分かりました」と同じ価値があります。

指摘された間違いを何度も繰り返せば、関心がない(から覚えない)という印象を植え付けます。

「自分なりに調べてやってみました」というのもある意味コミュニケーションの拒絶です。

自分で考えているかどうか、理解できたかどうかは、この際関係ありません。

「ご迷惑をかけるので自分で考えます」もコミュニケーションの拒絶で、しかも一方的なものです。
けっしてやる気を認められることにはなりません。


プログラミングに必要なのは、国語(日本語)の読解力とコミュニケーション力と想像力だと思います。

たいちう
記事: 418
登録日時: 8年前

Re: 複数の構造体について

#72

投稿記事 by たいちう » 6年前

本人はそれなりに頑張ってたつもりなのに、(本人の為を思ってのことでしょうが)
やる気がないように書かれたら退散したくもなるのではないかと。
結構、努力はしていたと思いますよ。


以下は質問者宛て。もう読まないかもしれないけど。
深く考えることなく安易に理解したつもりになることが一番の問題だと思います。

> かずまさんのサンプルは理解できました!ありがとうございます。
↑とか↓とか。
> usaoさんの助言のおかげで頭のなかは整理できました。ありがとうございます。

「理解したつもりであったが実は殆ど理解していなかった」という経験は誰にでもあります。
多いか少ないかだけの違いですが、プログラミングではあまり、ごまかしが効きませんので、
しっかり理解しておかないと先に進めません。
「理解」という言葉をもっと「理解」するように努めましょう。


# この掲示板では常に質問は歓迎されていますので、いつでも書き込んで下さい。
# もし反省すべき点が見つかり、反省した後ならば尚更大歓迎です。
# (回答も含めてですよ)

## 普段ROMってるだけの私が書くのもなんですが、
## このような方針の掲示板だったと理解しています。

non
記事: 1097
登録日時: 8年前

Re: 複数の構造体について

#73

投稿記事 by non » 6年前

あらま、投げ出してよいの。それは、それで回答者に失礼だな。
ちょっと、課題が難しかったね。質問者のレベルでは、難しいと思う。
もう少し、前から勉強した方がいいと思います。その方が、本当に勉強するつもりなら、かえって早いでしょう。
急がば回れ!!
non

閉鎖

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