0

テキストファイルからリンクされたリストに読み込もうとしています。テキスト ファイルには、本のタイトル、著者、発行年が「:」で区切られています。各本は別の行にあります。テキストファイルのエントリは次のようになります。

Absalom, Absalom!:William Faulkner:1936
After Many a Summer Dies the Swan:Aldous Huxley:1939    
Ah, Wilderness!:Eugene O'Neill:1933

一から書き直しています。コメントをいただければ幸いです。

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

struct BookNode
{
    char linebuffer[128];
    char delim[]=":";
    char * Title[50];
    char * Author[50];
    char * Year[5];
    struct BookNode *next;
//    char *token = NULL;
};

int main(void)
{
    static const char booklist[]= "booklist.txt";
FILE *fr=fopen("booklist.txt", "r");
if ( fr != NULL)

{
char Title[50];
char Author[50];
char Year[5]
struct BookNode Booknode;
while (fgets(linebuffer,128, fr) != NULL &&
    sscanf(line, "%49s %49s %4s", 
        &BookNode.Title, BookNode.Author, BookNode.Year)==3)
    {
         printf("%50s %50s %5s", 
                BookNode.Title, BookNode.Author, BookNode.Year);
    }
}
4

4 に答える 4

5

現在、コードには複数の問題があります。

最初のもの (冗談じゃない) は、コードの書式設定とインデントに関するものです。貼り付けたサンプルには、通常の形式やインデントがありませんでした。このような短いサンプルであっても、コード フローをたどるのはより困難です。常にコードをインデントし、コーディング スタイル (いくつかあります) を選択し、それを固守してください。

コード フローに関して、最初の問題はエラー チェックにあります。つまり、戻りステータスをチェックしfopenますが、ファイルを開くことが失敗した場合に十分なアクションを実行しません。

2 番目の問題は、概念的な問題です。N 文字の配列は N-1 の長さの文字列しか保持できないことに気付いていないようです。したがって、char[4]年を文字列として格納するのに適した形式になることはほとんどありません。

これらの問題が処理されたので、いずれにしてもコードが機能しなくなる実際の欠陥を次に示します。

1)fgets関数は、バッファがいっぱいになるか、行末またはファイルの終わりの文字に到達するまで読み取ります。それでもfgets、ファイル内の 1 行のエントリを読み取ろうとするために 3 回呼び出します。あなたがやりたいことはほとんどありません。ループの内容を再考する必要があります。

2)「メイン」ループの状態に欠陥がある可能性があります。feofこれは、 & coの使用に関するよくある誤解です。データ ファイルの最後に改行が含まれていると仮定すると (そして、そうするのは通常のことです)、ループは 1 回実行されすぎます。

次のように行読みループを構成することをお勧めします。

while (fgets(buffer, BUF_SIZE, stdin)) { /* parse buffer */ }

3) コードのメモリ管理に基本的な問題があります。つまり、関数addEntryがレコードを格納するためのメモリを割り当てられません。代わりに、リンク リスト内のすべてのエントリが、関数で割り当てた同じ共有バッファーを指すことになりますmain

これを修正するにはいくつかの方法があります。1 つは、構造体 ( 、、および)mallocの各メンバーに対して複数の呼び出しを使用することです。別の、おそらく好ましい方法は、次のように可変サイズの構造体を使用することです。BookNodetitleauthoryear

struct BookNode {
    char *title;
    char *author;
    char *year;
    struct BookNode *next;
    char buffer[]; // this shorthand requires C99
};

それぞれstruct BookNodeに、共有バッファーの内容をそこにコピーできるように、それらの後に十分なストレージを割り当てます。titleauthor、そしてyearこの追加されたストレージを指します。このようにして、ループの次の反復で他の BookNode の内容を上書きすることはありません。freeまた、ノード全体を解放するために必要なのは 1 つだけです。

ここにコードのすべての問題をリストしていない可能性があります。おそらく、別の書き直しの代わりに、最初に単一のエントリを読み取ってstdinそこから構築するなど、より小さなサブ問題に取り組む必要がありますか?

于 2012-06-03T13:53:43.340 に答える
0

addEntryタイトル、著者、年にメモリを割り当てる必要があります。
また、fgets3回実行すると、3行が読み取られます。fgetsループごとに1つ必要であり、結果をさまざまな部分に分割します(例:を使用strtok_r)。

静的バッファへのポインタを保存します。次の行を読み取るときに、このバッファは新しいデータで上書きされます。

データを割り当てた場合は、最終的にデータを解放する必要があることに注意してください。エントリのデストラクタは解放する必要があります。

于 2012-06-03T12:50:42.467 に答える
0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct BookNode {
    char * Title;
    char * Author;
    char * Year;
    struct BookNode * next;
} * head;


void addEntry(char * T, char * A, char * Y);
void display();
int numEntries();
//void writeBookData(struct BookNode * selection);
void free_book(struct BookNode *bnp){
    if(bnp == NULL) return;
    free(bnp->Title);
    free(bnp->Author);
    free(bnp->Year);
    free_book(bnp->next);
    free(bnp);
}

int main() {
    FILE * fpointer;
    fpointer=fopen("booklist.txt","r");
    if(fpointer == NULL){
        printf("Booklist could not be opened.\n");
        exit(EXIT_FAILURE);
    }

    char Title[50+1];
    char Author[50+1];
    char Year[4+1];

    head = NULL;
    while (EOF!=fscanf(fpointer, "%50[^:]%*c%50[^:]%*c%4[^\n]%*c", Title, Author, Year)){
        //note:The input number of characters is limited (Eg50), it (because minutes in excess of the limit  is used in the following items) there must be large enough.

        addEntry(Title, Author, Year);
    }
    fclose(fpointer);

    int entryCount = numEntries();
    printf("There are %d entries in this Book list\n", entryCount);

    display();

    free_book(head);
    return 0;
}

void addEntry(char * T, char * A, char * Y){
    struct BookNode * tempNode, * iterator;
    tempNode = (struct BookNode *)malloc(sizeof(struct BookNode));
    tempNode->Title = (char *)malloc(strlen(T)+1);
    strcpy(tempNode->Title, T);

    tempNode->Author = (char *)malloc(strlen(A)+1);
    strcpy(tempNode->Author, A);

    tempNode->Year = (char *)malloc(strlen(Y)+1);
    strcpy(tempNode->Year, Y);

    tempNode->next = NULL;

    iterator = head;

    if (head == NULL){
        head = tempNode;
    } else {
        while(iterator->next != NULL){
            iterator = iterator->next;
        }
        iterator->next = tempNode;
    }
}

int numEntries(){
    if(head == NULL)
        return 0;
    else{
        int count;
        struct BookNode *iterator;
        for(count=0, iterator=head; iterator!=NULL; iterator = iterator->next, ++count)
            ;
        return count;
    }
}

void display(){
    if(head == NULL)
        return ;
    else{
        struct BookNode *iterator;
        for(iterator=head; iterator!=NULL; iterator = iterator->next)
            fprintf(stdout, "%s:%s:%s\n", iterator->Title, iterator->Author, iterator->Year);
    }
}
于 2012-06-03T16:21:33.097 に答える
0

example of strtok

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

int main(){
    char line[] = "Absalom, Absalom!:William Faulkner:1936\n";
    char *p;
    char * Title;
    char * Author;
    char * Year;

    p = strtok(line, ":");
    Title = strdup(p);
    Author = strdup(strtok(NULL, ":"));
    Year = strdup(strtok(NULL, ": \n"));
    printf("\"%s\",\"%s\",\"%s\"\n", Title, Author, Year);
    free(Title);
    free(Author);
    free(Year);
}
//result:"Absalom, Absalom!","William Faulkner","1936"
于 2012-06-03T16:54:51.147 に答える