0

我正在编写一个程序,它将读取两个文件(hw8.data 和 codex.data) hw8.data 包含一首诗,而 codex.data 包含要替换该诗中的单词。我已经将要加载的文件保存在链接列表中。我无法找到匹配的单词并替换它们。例如,我也无法将标点符号从 hw8 转移到新替换的单词上。hw8: H​​ello World., codex: World sup,所以诗中的新词是Hello sup。这是 hw8.data

Eye have a spelling chequer, 
It came with my Pea Sea.
It plane lee marks four my revue, 
Miss Steaks I can knot sea.
Eye strike the quays and type a whirred,
And weight four it two say,
Weather eye am write oar wrong,
It tells me straight aweigh.
Eye ran this poem threw it,
Your shore real glad two no.
Its vary polished in its weigh.
My chequer tolled me sew.
A chequer is a bless thing,
It freeze yew lodes of thyme.
It helps me right all stiles of righting,
And aides me when eye rime.
Each frays come posed up on my screen,
Eye trussed too bee a joule.
The chequer pours over every word,
Two cheque sum spelling rule.

Codex.data(不是全部)

Eye I
eye I
chequer checker 
Pea P
Sea C
plane plainly
lee skip 
four for
revue review
Miss Mistakes
Steaks skip
knot not
sea see
quays keys
.
.
.

这是我的代码:

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

struct node {
    char * word;
    struct node* next;
};

struct codex {
    char *word1;
    char *word2;
    struct codex *next;
};

struct node *loadWords(FILE *stream);
struct codex *loadCodex(FILE *stream);
struct node *exchange(struct node *head, struct codex *headC);

int main()
{
    FILE *stream = NULL;
    struct node *head;
    struct node *temp;
    struct node *loop;

    struct codex *headC;
    struct codex *tempC;
    struct codex *loopC;

    head = loadWords(stream);
    if (head == NULL) {
        return 1;
    }
    temp = head;//print each word
    while (temp != NULL) {
        //printf ( "%s\n", temp->word);
        temp = temp->next;
    }


    headC = loadCodex(stream);
    if (headC == NULL) {
        return 1;
    }
    tempC = headC;//print each word
    while (tempC != NULL) {
        //printf ( "%s %s\n", tempC->word1, tempC->word2);
        tempC = tempC->next;
    }

    struct node *exchangedHead;
    struct node *temp2;

    exchangedHead = exchange(head, headC);
    if (exchangedHead == NULL) {
        return 1;
    }
    temp2 = exchangedHead;//print each word
    while (temp2 != NULL) {
        //printf ( "%s ", temp2->word);
        temp2 = temp2->next;
    }

    temp = head;// free memory
    while(temp != NULL) {
        loop = temp->next;
        free ( temp->word);
        free ( temp);
        temp = loop;
    }

    tempC = headC;// free memory
    while (tempC != NULL) {
        loopC = tempC->next;
        free ( tempC->word1);
        free ( tempC->word2);
        free ( tempC);
        tempC = loopC;
    }
    return 0;
}

/*
 * This function will go through and load the words from the text file and save it to
 * the struct and link the current struct to the next one
 */
struct node *loadWords(FILE *stream) {
    struct node *loop = NULL;
    struct node *temp = NULL;
    struct node *head = NULL;
    char *words = NULL;
    char *currentWord;
    size_t chrCount = 0;
    if ((stream = fopen("hw8.data", "r")) == NULL) {
        printf ("could not open file\n");
        return NULL;
    }

    while(getline( &words, &chrCount, stream) > 0) {//read a line from file
        currentWord = strtok(words, " ");//get first token
        while (currentWord != NULL) {//loop through tokens
            if((temp = calloc(1, sizeof(struct node))) == NULL) {
                printf("ERROR - Could not allocate memory.\n");
                exit(0);
            }
            temp->word = strdup ( currentWord);//allocate memory and copy token to word
            if ( head == NULL) {
                head = temp;//first structure
            }
            else {
                loop = head;
                while ( loop->next != NULL) {//loop to last structure
                    loop = loop->next;//add structure to end
                }
                loop->next = temp;
            }
            currentWord = strtok(NULL, " ");//next token
        }
        free (words);//release memory
        chrCount = 0;//so readline will allocate memory for next line
        words = NULL;
    }

    return head;
}

/*
 * This function will go through and load the words from the text file and save it to
 * the struct and link the current struct to the next one
 */
struct codex *loadCodex(FILE *stream) {
    struct codex *loop = NULL;
    struct codex *temp = NULL;
    struct codex *head = NULL;
    char *words = NULL;
    char *currentWord;
    char *currentWord2;
    size_t chrCount = 0;
    if (( stream = fopen("codex.data", "r")) == NULL) {
        printf ("could not open file\n");
        return NULL;
    }

    while(getline( &words, &chrCount, stream) > 0) {//read a line from file
        currentWord = strtok(words, " ");//get first token
        currentWord2 = strtok(NULL, "\n");
        while (currentWord != NULL && currentWord2 != NULL) {//loop through tokens
            if((temp = calloc(1, sizeof(struct node))) == NULL) {
                printf("ERROR - Could not allocate memory.\n");
                exit(0);
            }
            temp->word1 = strdup ( currentWord);//allocate memory and copy token to word
            temp->word2 = strdup ( currentWord2);
            if (head == NULL) {
                head = temp;//first structure
            }
            else {
                loop = head;
                while ( loop->next != NULL) {//loop to last structure
                    loop = loop->next;//add structure to end
                }
                loop->next = temp;
            }
            currentWord = strtok(NULL, " ");//next token
        }
        free (words);//release memory
        chrCount = 0;//so readline will allocate memory for next line
        words = NULL;
    }

    return head;
}

struct node *exchange(struct node *head, struct codex *headC) {
    struct node *temp;
    temp = head;
    while(head != NULL && headC != NULL) {
        if(strcmp(head->word, headC->word1)) {
            head->word = relloc(head->word, strlen(headC->word2));
            head->word = headC->word2;
            head->next = temp->next;
            headC = headC->next;
            temp = temp->next;
        }
    }
}
4

1 回答 1

0

您遇到的问题exchange(除了拼写错误realloc和未能返回值)是未能null-terminatingrealloc. (注意我没有检查列表操作的正确性)

head->word = realloc(head->word, strlen(headC->word2));

应该

head->word = realloc(head->word, strlen(headC->word2) + 1);

这可以解释为什么你会丢失1-char每行末尾的标点符号。

您还应该指向realloc一个tmp指针,并且仅head->word = tmp;在重新分配成功时才分配。(否则你会丢失 的原始内容head->word)另外,如果你不打算从 中返回值exchange,只需创建函数void(否则返回head)。如果这不能解决问题,请告诉我,我会更深入地研究。


更多问题

查看代码,我发现了更多问题(一些很重要)。首先,你的exchange功能是火车残骸。通常,在迭代链表时,您会创建一个用于迭代的临时指针,而不是使用列表地址(就像您在 中所做的那样main)。你为什么不这样做作为交换?鉴于此,我放弃了交换并重写了它。它包含在下面。在您的读取函数中,明智地选择使用getline,但无需重置chrCount = 0;words = NULL;为了getline分配下一行。它会自动完成。

words但是,当您将线路发送到时,您犯了犯规strtok- 没有先复制。为什么?getline分配空间并需要管理/释放它分配的内存块。当您发送wordsstrtok它时,它会修改内存,插入可能会在尝试阻止null-terminating时导致杂散错误的字符。在将线路发送到 之前,请务必复制分配的线路。此外,由于必须释放副本,因此请为您的副本创建一个,以便保留内存块的起始地址,以便在完成时传递给您。getlinefree/reallocgetlinestrtokpointerfree

无需将未打开的FILE*指针传递给您的读取函数。这可以在函数中声明。您需要传递的是 afilename这样您的读取函数才能知道要打开什么。我更改main为包含其参数,因此您现在将单词/codex 文件名作为参数传递。

注意:我刚刚使用了您的示例 codex 值进行测试。

查看修改和注释的代码:

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

struct node {
    char * word;
    struct node* next;
};

struct codex {
    char *word1;
    char *word2;
    struct codex *next;
};

struct node *loadWords(char *filename);
struct codex *loadCodex(char *filename);
struct node *exchange(struct node *head, struct codex *headC);

int main (int argc, char **argv)
{
    if (argc < 3) {
        fprintf (stderr, "error: insufficient input. Usage: %s nodefile codexfile\n", argv[0]);
        return 1;
    }

    // FILE *stream = NULL;
    struct node *head;
    struct node *temp;
    struct node *loop;

    struct codex *headC;
    struct codex *tempC;
    struct codex *loopC;

    head = loadWords(argv[1]);
    if (head == NULL) {
        return 1;
    }

    printf ("\nOriginal:\n\n");
    temp = head;//print each word
    while (temp != NULL) {
        printf ( " %s", temp->word);
        temp = temp->next;
    }
    printf ("\n");


    headC = loadCodex(argv[2]);
    if (headC == NULL) {
        return 1;
    }
    tempC = headC;//print each word
    while (tempC != NULL) {
        // printf ( "%s %s\n", tempC->word1, tempC->word2);
        tempC = tempC->next;
    }

    struct node *exchangedHead;
    struct node *temp2;

    exchangedHead = exchange(head, headC);
    if (exchangedHead == NULL) {
        return 1;
    }

    printf ("\nExchanged:\n\n");
    temp2 = exchangedHead;//print each word
    while (temp2 != NULL) {
        printf ( " %s", temp2->word);
        temp2 = temp2->next;
    }
    printf ("\n");

    temp = head;// free memory
    while(temp != NULL) {
        loop = temp->next;
        free ( temp->word);
        free ( temp);
        temp = loop;
    }

    tempC = headC;// free memory
    while (tempC != NULL) {
        loopC = tempC->next;
        free ( tempC->word1);
        free ( tempC->word2);
        free ( tempC);
        tempC = loopC;
    }
    return 0;
}

/*
* This function will go through and load the words from the text file and save it to
* the struct and link the current struct to the next one
*/
struct node *loadWords(char *filename) {
    FILE *stream = NULL;
    struct node *loop = NULL;
    struct node *temp = NULL;
    struct node *head = NULL;
    char *words = NULL;
    char *currentWord;
    size_t chrCount = 0;
    ssize_t nchr = 0;
    if ((stream = fopen(filename, "r")) == NULL) {
        printf ("could not open file\n");
        return NULL;
    }

    while((nchr = getline (&words, &chrCount, stream)) != -1) {//read a line from file

        char *wtemp = strdup (words);   /* copy words, strtok will modify   */
        char *sp = wtemp;               /* save wtemp address, pass sp      */
        currentWord = strtok(sp, " ");//get first token

        while (currentWord != NULL) {//loop through tokens
            if((temp = calloc(1, sizeof(struct node))) == NULL) {
                printf("ERROR - Could not allocate memory.\n");
                exit(0);
            }
            temp->word = strdup (currentWord);//allocate memory and copy token to word
            if ( head == NULL) {
                head = temp;//first structure
            }
            else {
                loop = head;
                while ( loop->next != NULL) {//loop to last structure
                    loop = loop->next;//add structure to end
                }
                loop->next = temp;
            }
            currentWord = strtok(NULL, " ");//next token
        }
        if (wtemp) free (wtemp);
        wtemp = NULL;
        // chrCount = 0; //so readline will allocate memory for next line (***NOT REQUIED***)
        // words = NULL; (***NOT REQUIED***)
    }
    if (words) free (words);//release memory
    if (stream) fclose (stream);

    return head;
}

/*
* This function will go through and load the words from the text file and save it to
* the struct and link the current struct to the next one
*/
struct codex *loadCodex(char *filename) {
    FILE *stream = NULL;
    struct codex *loop = NULL;
    struct codex *temp = NULL;
    struct codex *head = NULL;
    char *words = NULL;
    char *currentWord;
    char *currentWord2;
    size_t chrCount = 0;
    ssize_t nchr = 0;

    if (( stream = fopen(filename, "r")) == NULL) {
        printf ("could not open file\n");
        return NULL;
    }

    while(getline( &words, &chrCount, stream) > 0) {//read a line from file

        while (nchr > 0 && (words[nchr-1] == '\n' || words[nchr-1] == '\r'))
            words[--nchr] = 0;          /* strip newline or carriage rtn    */

        char *wtemp = strdup (words);   /* copy words, strtok will modify   */
        char *sp = wtemp;               /* save wtemp address, pass sp      */

        currentWord = strtok(sp, " ");//get first token
        currentWord2 = strtok(NULL, "\n");
        while (currentWord != NULL && currentWord2 != NULL) {//loop through tokens
            if((temp = calloc(1, sizeof(struct node))) == NULL) {
                printf("ERROR - Could not allocate memory.\n");
                exit(0);
            }
            temp->word1 = strdup ( currentWord);//allocate memory and copy token to word
            temp->word2 = strdup ( currentWord2);
            if (head == NULL) {
                head = temp;//first structure
            }
            else {
                loop = head;
                while ( loop->next != NULL) {//loop to last structure
                    loop = loop->next;//add structure to end
                }
                loop->next = temp;
            }
            currentWord = strtok(NULL, " ");//next token
        }
        if (wtemp) free (wtemp);
        wtemp = NULL;
        // chrCount = 0;//so readline will allocate memory for next line
        // words = NULL;
    }
    if (words) free (words);//release memory
    if (stream) fclose (stream);

    return head;
}

// struct node *exchange(struct node *head, struct codex *headC) {
//     struct node *temp;
//     temp = head;
//     while(head != NULL && headC != NULL) {
//         if(strcmp(head->word, headC->word1)) {
//             head->word = realloc(head->word, strlen(headC->word2));
//             head->word = headC->word2;
//             head->next = temp->next;
//             headC = headC->next;
//             temp = temp->next;
//         }
//     }
// }

struct node *exchange(struct node *head, struct codex *headC) 
{
    struct node *temp = head;

    while(temp != NULL) 
    {
        char *wtemp = NULL;
        struct codex *tempC = headC;

        while (tempC != NULL) 
        {
            if (strcmp(temp->word, tempC->word1) == 0) {

                size_t tclen = strlen(tempC->word2);
                wtemp = realloc(temp->word, tclen + 1); /* add 1 for null-term */

                if (!wtemp) {
                    fprintf (stderr, "%s() error: realloc failed.\n", __func__);
                    return head;
                }
                temp->word = wtemp;
                memcpy (temp->word, tempC->word2, tclen + 1); /* copies the null-term also */
            }
            tempC = tempC->next;
        }
        temp = temp->next;
    }
    return head;
}

输出

$ ./bin/ll_single_replace_w dat/ll_replace_poem.txt dat/ll_replace_codex.txt

Original:

 Eye have a spelling chequer,
 It came with my Pea Sea.
 It plane lee marks four my revue,
 Miss Steaks I can knot sea.
 Eye strike the quays and type a whirred,
 And weight four it two say,
 Weather eye am write oar wrong,
 It tells me straight aweigh.
 Eye ran this poem threw it,
 Your shore real glad two no.
 Its vary polished in its weigh.
 My chequer tolled me sew.
 A chequer is a bless thing,
 It freeze yew lodes of thyme.
 It helps me right all stiles of righting,
 And aides me when eye rime.
 Each frays come posed up on my screen,
 Eye trussed too bee a joule.
 The chequer pours over every word,
 Two cheque sum spelling rule.


Exchanged:

 I have a spelling chequer,
 It came with my P Sea.
 It plainly skip  marks for my revue,
 Mistakes skip I can not sea.
 I strike the keys and type a whirred,
 And weight for it two say,
 Weather I am write oar wrong,
 It tells me straight aweigh.
 I ran this poem threw it,
 Your shore real glad two no.
 Its vary polished in its weigh.
 My checker  tolled me sew.
 A checker  is a bless thing,
 It freeze yew lodes of thyme.
 It helps me right all stiles of righting,
 And aides me when I rime.
 Each frays come posed up on my screen,
 I trussed too bee a joule.
 The checker  pours over every word,
 Two cheque sum spelling rule.
于 2015-03-31T02:39:59.367 回答