首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用codex C在struct中交换单词

使用codex C在struct中交换单词
EN

Stack Overflow用户
提问于 2015-03-31 09:43:00
回答 1查看 62关注 0票数 0

我正在编写一个程序,它将读取两个文件(hw8.data和codex.data)。hw8.data包含一首诗,而codex.data包含要替换的词。我已经获得了要加载的文件并将其保存在链表中。我在查找匹配的单词和替换它们时遇到了困难。此外,例如,我在将标点符号从hw8转移到新替换的单词时遇到了麻烦。hw8: Hello World。,codex: World sup,所以诗歌中的新词应该是Hello sup。下面是hw8.data

代码语言:javascript
复制
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 (不是全部)

代码语言:javascript
复制
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
.
.
.

下面是我的代码:

代码语言:javascript
复制
#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;
        }
    }
}
EN

回答 1

Stack Overflow用户

发布于 2015-03-31 10:39:59

您在exchange中遇到的问题( realloc拼写错误和返回值失败除外)是无法为realloc上的null-terminating字符分配空间。(注意,我还没有检查列表操作的正确性)

代码语言:javascript
复制
head->word = realloc(head->word, strlen(headC->word2));

应该是

代码语言:javascript
复制
head->word = realloc(head->word, strlen(headC->word2) + 1);

这就解释了为什么每行末尾的1-char标点符号都丢失了。

您还应该realloctmp指针,并且仅在重新分配成功时才分配head->word = tmp;。(否则将丢失head->word的原始内容)此外,如果不打算从exchange返回值,只需将函数设置为void (否则将返回head)。如果这不能解决问题,请告诉我,我会更深入地挖掘。

更多问题

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

但是,当您向strtok发送行words时,您犯了一个错误--没有事先进行复制。为什么?getline分配了空间,并且需要管理/释放它分配的内存块。当您将words发送到strtok时,它会修改内存,插入null-terminating字符,这可能会在getline尝试free/realloc块时导致杂散错误。Always在将线路发送到strtok之前,始终对getline分配的线路进行复制。此外,由于你的必须释放拷贝,创建一个pointer到你的拷贝,以便你保留你的内存块的起始地址,以便在你完成时传递给free

不需要将未打开的FILE*指针传递给读取函数。可以在函数中声明的。您需要传递的是一个filename,以便您的read函数知道要打开的内容。我更改了main以包含其参数,因此您现在可以将单词/codex文件名作为参数传递。

注意:我只是在测试中使用了您的示例codex值。

查看代码的修改和注释:

代码语言:javascript
复制
#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;
}

输出

代码语言:javascript
复制
$ ./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.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29359214

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档