【掲示板ご利用上の注意】

 ※題名は具体的に!
 ※学校の課題の丸投げ禁止!
 ※ソースの添付は「HTML変換ツール」で字下げ!
 ※返信の引用は最小限に!
 ※環境(OSとコンパイラ)や症状は具体的に詳しく!
 ※マルチポスト(多重投稿)は謹んで!

 詳しくはこちら



 本当はこんなに大きく書きたくはないのですが、なかなか守っていただけなくて…。
 守ってくださいね。お願いします。(by管理人)

C言語ソース⇒HTML形式ツール   掲示板2こちら


管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.19512

自己参照構造体のソートのやりかた
投稿者---Kei(2005/01/26 16:20:22)


まず最初に、過去ログに同じ質問があるのにすみません。
過去ログのサンプルを見てもどうしても分からなかったので、
質問させてください。

まず、ディレクトリ内にあるファイル一覧を取得し、そのファイルの更新日付で昇順ソートさせたいのですが、
コンパイル後、ソート処理の部分でメモリのエラーになってしまいます。
1個ずつ調べた結果ソート処理をしてるwhile文で落ちているのまでは終えたのですが、解決策が分かりません。
ご教授お願いします。
typedef struct sort{
    char sort_time[MAX_STRING];
    struct sort *next;
}SORT;

<pre>int folder(char *dir)
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hScanPointer = NULL;
    SYSTEMTIME writeTime;

    SORT *head = NULL;          /* リストの先頭データアドレス */
    SORT *before = NULL;                /* 1つ前のアドレス */
    SORT *point;                        /* 確保した領域のアドレス */

    char filename[MAX_PATH];
    char filepath[MAX_PATH];
    char editname[20+1];
    char editpath[MAX_PATH];
    char select[MAX_STRING];
    char edittime[MAX_STRING];
    char list_buf[MAX_STRING];
    int ret;
    int i = 0;
    int flag;

    memset(filename, '\0', sizeof(filename));
    strcpy(filename, dir);
    strcat(filename, &quot;\\*.txt&quot;);            /* テキストだけ検索 */

    printf(&quot;フォルダ名:%s\n&quot;, filename);
    
    hScanPointer = FindFirstFile(filename, &amp;FindFileData);
    
    if(hScanPointer == INVALID_HANDLE_VALUE){
        return OK;
    }
    flag = 0;
    do{
        memset(editname, '\0', sizeof(editname));
        memset(edittime, '\0', sizeof(edittime));
        /* ファイル時間取得 */
        FileTimeToSystemTime( &amp;FindFileData.ftLastWriteTime, &amp;writeTime);
        /* 更新時間ソート用に時間を編集 */
        sprintf(edittime, &quot;%d%02d%d%d%d%d&quot;, writeTime.wYear, writeTime.wMonth, writeTime.wDay, writeTime.wHour, writeTime.wMinute, writeTime.wSecond);

        /* 一覧ソート用記憶領域確保 */
        if( (point = (sort*)malloc(sizeof(sort) ) ) == NULL){
            printf(&quot;領域確保失敗\n&quot;); 
            return NG;
        }
        memset(point-&gt;sort_time, '\0', sizeof(point-&gt;sort_time));
        memcpy(point-&gt;sort_time, edittime, strlen(edittime));
        if(flag == 0){
            head = point;         /* 構造体ポインタに先頭アドレスを設定 */
            before = point;
            flag = 1;
        } else {
            before-&gt;next = point;      /* 今までの先頭ポインタを次のポインタに入れる */
            before = point;
        }

        printf(&quot;前時間:%s\t次時間:%s\n&quot;, point-&gt;sort_time, before);
        

        ret = nameedit(FindFileData.cFileName, editname);
        if(ret != OK){
            printf(&quot;ファイル名編集失敗\n&quot;);
            return OK;
        }
    } while(FindNextFile(hScanPointer, &amp;FindFileData));
    FindClose(hScanPointer);
    /* ソート処理 */
    point = head;   /* 先頭のポインタを元に戻す */
    before = point-&gt;next;
    while(point-&gt;next != NULL){
        while(before != NULL){
            if(memcmp(point-&gt;sort_time, before-&gt;sort_time, strlen(point-&gt;sort_time)) &gt; 0){
                memcpy(list_buf, point-&gt;sort_time, strlen(point-&gt;sort_time));
                memcpy(point-&gt;sort_time, before-&gt;sort_time, strlen(point-&gt;sort_time));
                memcpy(before-&gt;sort_time, list_buf, strlen(point-&gt;sort_time));
            }
            before = before-&gt;next;
        }
        point = point-&gt;next;
        before = point-&gt;next;
    }
    while(head != NULL){
        printf(&quot;ファイル名:%s\t更新日付:%s\n&quot;, editname, head-&gt;sort_time);
    }
}
</pre>






この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> 「HTML変換ツール」の使い方 19517 管理人 2005/01/26 17:34:41
<子記事> ソース修正して再投稿 19541 Kei 2005/01/27 07:45:06


No.19517

「HTML変換ツール」の使い方
投稿者---管理人(2005/01/26 17:34:41)


当掲示板の管理人です。ご投稿ありがとうございます。

さて、題名の件ですが、上記掲示板ご利用上の注意からリンクしております「HTML変換ツール」は、「ConvHTML」ボタンを2度押すと、No.19512のご投稿のようにソースが文字化け状態になってしまいます。
「ConvHTML」ボタンは1度のみ押し、必ず投稿フォームの確認画面をご確認の上ご投稿ください。

なお、No.19512のような文字化け状態の添付ソースは、そのままコピーし、「HTML変換ツール」のフォームに貼り付け、「Preview」ボタンを押すと、正しく読むことができます。

下記に正しく変換したソースを添付します。


typedef struct sort{
char sort_time[MAX_STRING];
struct sort *next;
}SORT;

int folder(char *dir)
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hScanPointer = NULL;
    SYSTEMTIME writeTime;

    SORT *head = NULL;          /* リストの先頭データアドレス */
    SORT *before = NULL;                /* 1つ前のアドレス */
    SORT *point;                        /* 確保した領域のアドレス */

    char filename[MAX_PATH];
    char filepath[MAX_PATH];
    char editname[20+1];
    char editpath[MAX_PATH];
    char select[MAX_STRING];
    char edittime[MAX_STRING];
    char list_buf[MAX_STRING];
    int ret;
    int i = 0;
    int flag;

    memset(filename, '\0', sizeof(filename));
    strcpy(filename, dir);
    strcat(filename, "\\*.txt");            /* テキストだけ検索 */

    printf("フォルダ名:%s\n", filename);
    
    hScanPointer = FindFirstFile(filename, &FindFileData);
    
    if(hScanPointer == INVALID_HANDLE_VALUE){
        return OK;
    }
    flag = 0;
    do{
        memset(editname, '\0', sizeof(editname));
        memset(edittime, '\0', sizeof(edittime));
        /* ファイル時間取得 */
        FileTimeToSystemTime( &FindFileData.ftLastWriteTime, &writeTime);
        /* 更新時間ソート用に時間を編集 */
        sprintf(edittime, "%d%02d%d%d%d%d", writeTime.wYear, writeTime.wMonth, writeTime.wDay, writeTime.wHour, writeTime.wMinute, writeTime.wSecond);

        /* 一覧ソート用記憶領域確保 */
        if( (point = (sort*)malloc(sizeof(sort) ) ) == NULL){
            printf("領域確保失敗\n"); 
            return NG;
        }
        memset(point->sort_time, '\0', sizeof(point->sort_time));
        memcpy(point->sort_time, edittime, strlen(edittime));
        if(flag == 0){
            head = point;         /* 構造体ポインタに先頭アドレスを設定 */
            before = point;
            flag = 1;
        } else {
            before->next = point;      /* 今までの先頭ポインタを次のポインタに入れる */
            before = point;
        }

        printf("前時間:%s\t次時間:%s\n", point->sort_time, before);
        

        ret = nameedit(FindFileData.cFileName, editname);
        if(ret != OK){
            printf("ファイル名編集失敗\n");
            return OK;
        }
    } while(FindNextFile(hScanPointer, &FindFileData));
    FindClose(hScanPointer);
    /* ソート処理 */
    point = head;   /* 先頭のポインタを元に戻す */
    before = point->next;
    while(point->next != NULL){
        while(before != NULL){
            if(memcmp(point->sort_time, before->sort_time, strlen(point->sort_time)) > 0){
                memcpy(list_buf, point->sort_time, strlen(point->sort_time));
                memcpy(point->sort_time, before->sort_time, strlen(point->sort_time));
                memcpy(before->sort_time, list_buf, strlen(point->sort_time));
            }
            before = before->next;
        }
        point = point->next;
        before = point->next;
    }
    while(head != NULL){
        printf("ファイル名:%s\t更新日付:%s\n", editname, head->sort_time);
    }
}





この投稿にコメントする

削除パスワード

No.19540

Re:「HTML変換ツール」の使い方
投稿者---Kei(2005/01/27 07:41:37)


>当掲示板の管理人です。ご投稿ありがとうございます。
>
>さて、題名の件ですが、上記掲示板ご利用上の注意からリンクしております「HTML変換ツール」は、「ConvHTML」ボタンを2度押すと、No.19512のご投稿のようにソースが文字化け状態になってしまいます。
>「ConvHTML」ボタンは1度のみ押し、必ず投稿フォームの確認画面をご確認の上ご投稿ください。

すみません、気づかずに投稿してしまいました。
ありがとうございます。


この投稿にコメントする

削除パスワード

No.19541

ソース修正して再投稿
投稿者---Kei(2005/01/27 07:45:06)


デバッグして値を見てみてもやはりエラー原因が分かりません。
指摘お願いします。

typedef struct sort{
char sort_time[MAX_STRING];
struct sort *next;
}SORT;


int folder(char *dir)
{
    WIN32_FIND_DATA FindFileData;
    HANDLE hScanPointer = NULL;
    SYSTEMTIME writeTime;

    SORT *head = NULL;          /* リストの先頭データアドレス */
    SORT *before = NULL;                /* 1つ前のアドレス */
    SORT *point;                        /* 確保した領域のアドレス */

    char filename[MAX_PATH];
    char filepath[MAX_PATH];
    char editname[20+1];
    char editpath[MAX_PATH];
    char select[MAX_STRING];
    char edittime[MAX_STRING];
    char list_buf[MAX_STRING];
    int ret;
    int i = 0;
    int flag;

    memset(filename, '\0', sizeof(filename));
    strcpy(filename, dir);
    strcat(filename, "\\*.txt");            /* テキストだけ検索 */

    printf("フォルダ名:%s\n", filename);
    
    hScanPointer = FindFirstFile(filename, &FindFileData);
    
    if(hScanPointer == INVALID_HANDLE_VALUE){
        return OK;
    }
    flag = 0;
    do{
        memset(editname, '\0', sizeof(editname));
        memset(edittime, '\0', sizeof(edittime));
        /* ファイル時間取得 */
        FileTimeToSystemTime( &FindFileData.ftLastWriteTime, &writeTime);
        /* 更新時間ソート用に時間を編集 */
        sprintf(edittime, "%d%02d%d%d%d%d", writeTime.wYear, writeTime.wMonth, writeTime.wDay, writeTime.wHour, writeTime.wMinute, writeTime.wSecond);

        /* 一覧ソート用記憶領域確保 */
        if( (point = (sort*)malloc(sizeof(sort) ) ) == NULL){
            printf("領域確保失敗\n"); 
            return NG;
        }
        memset(point->sort_time, '\0', sizeof(point->sort_time));
        memcpy(point->sort_time, edittime, strlen(edittime));
        if(flag == 0){
            head = point;         /* 構造体ポインタに先頭アドレスを設定 */
            before = point;
            flag = 1;
        } else {
            before->next = point;      /* 今までの先頭ポインタを次のポインタに入れる */
            before = point;
        }

        printf("前時間:%s\t次時間:%s\n", point->sort_time, before);
        

        ret = nameedit(FindFileData.cFileName, editname);
        if(ret != OK){
            printf("ファイル名編集失敗\n");
            return OK;
        }
    } while(FindNextFile(hScanPointer, &FindFileData));
    FindClose(hScanPointer);
    /* ソート処理 */
    point = head;   /* 先頭のポインタを元に戻す */
    before = point->next;
    while(point->next != NULL){
        while(before != NULL){
            if(memcmp(point->sort_time, before->sort_time, strlen(point->sort_time)) > 0){
                memcpy(list_buf, point->sort_time, strlen(point->sort_time));
                memcpy(point->sort_time, before->sort_time, strlen(point->sort_time));
                memcpy(before->sort_time, list_buf, strlen(point->sort_time));
            }
            before = before->next;
        }
        point = point->next;
        before = point->next;
    }
    while(head != NULL){
        printf("ファイル名:%s\t更新日付:%s\n", editname, head->sort_time);
    }
}




この投稿にコメントする

削除パスワード

No.19546

Re:ソース修正して再投稿
投稿者---REE(2005/01/27 09:57:03)


>デバッグして値を見てみてもやはりエラー原因が分かりません。
>指摘お願いします。

・文字列の比較ならmemcmpより、strcmpを使いましょう。

・strlen(point->sort_time)の長さだけコピーしても文字列をコピーしたことになりません。
 (末尾のNUL文字がコピーされないため)
 さらにコピーするサイズを間違えていませんか?
 すべて、strlen(point->sort_time)になっていますが・・
 どちらもstrcpyを使えば解決です。

・そもそも普通はリスト構造のデータをソートする時には、データを入れ替えるのではなく、
 リストを繋ぎかえることで位置を入れ替えます。



この投稿にコメントする

削除パスワード

No.19551

Re:ソース修正して再投稿
投稿者---Kei(2005/01/27 12:08:18)


ありがとうございます。
教えて頂いた事を考慮してサンプル、過去ログを見て
何とか自分なりに解決できました。(まだ不安ですが・・・

ここでレスをくださる方はどのような勉強をして知識を増やしているのか
教えていただきたいです・・・。


この投稿にコメントする

削除パスワード

No.19569

Re:ソース修正して再投稿
投稿者---Craft(2005/01/27 14:54:13)


>ここでレスをくださる方はどのような勉強をして知識を増やしているのか
>教えていただきたいです・・・。

おそらく多くの人は、
(1) 作ったプログラムが正常に動かない
(2) 地道に修正しては、printf()などを多用して原因を探る
(3) 標準ライブラリの結果が期待したものにならない場合は関数仕様を調べて正しい使い方を探る
(4) (2),(3)の結果を元にプログラムを修正する。
→アルゴリズムを修正したり、関数の使い方を見直したり、プログラムの構造をみなおしたりなど。
(5) 期待した結果が得られるまで(1)〜(4)を繰り返す。

という経験を積んで覚えていっていると思います。

あとは、興味をもつ、のみ重要かも?
printf()っていろいろ書式があるなあ→%d, %s, %f 等片っ端から使ってどうなるのか試してみる とか。


この投稿にコメントする

削除パスワード

No.19595

Re:ソース修正して再投稿
投稿者---Kei(2005/01/27 18:24:33)


なるほど・・・
やっぱり地道な努力が結果に繋がるのですね。
自分も質問に答えられるように頑張ります!
先は果てしなく長そうですが・・・(苦笑


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧