【问题标题】:Reading words from file into dynamic char with linked lists使用链表将文件中的单词读入动态字符
【发布时间】:2015-06-04 00:21:30
【问题描述】:

我正在尝试从文件中读取数据并将数据保存到链接列表中。我们无法将 char 字变成静态字符。我们必须使用 char *word 使其动态地接受任意长度的单词。我无法从文件中读取单词并将其保存到动态字符中。我以前用静态字符做过这件事,这很容易。这是代码。

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

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

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

struct node *loadWords(FILE *stream);

int main() {
    struct node *head;
    FILE *stream;
    head = loadWords(stream);
    return 0;
}

struct node *loadWords(FILE *stream) {
    struct node *poem;
    struct node *temp;
    char *words, *currentWord;
    size_t chrCount;
    stream = fopen("hw8.data", "r");

    rewind(stream);

    while(!feof(stream)) {
        if(temp = (struct node*)calloc(1, sizeof(struct node)) == NULL) {
            printf("ERROR - Could not allocate memory.\n");
            exit(0);
        }
        getline(&words, &chrCount, stream);
        currentWord = strtok(words, " ");
        strcpy(temp->word, words);
        head->next = temp;
        head = head->next;
    }

    return poem;
}

我如何动态地做到这一点?

【问题讨论】:

    标签: c dynamic linked-list char


    【解决方案1】:

    这使用 getline 从文件中读取每一行。如果 words 设置为 NULL 并且 chrCount 设置为零,getline 将分配存储文件中的行所需的内存。
    随着行被标记化,结构被调用。 strdup 将分配内存来存储令牌并将令牌复制到结构中。
    新结构被添加到链表的末尾。为 word 分配的内存被释放,并为下一行重置 words 和 chrCount。
    只要 getline 返回大于 0 的值,循环就会继续。
    在 main 中,遍历列表打印每个单词,然后再次遍历,释放分配的内存。

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    struct node {
        char * word;
        struct node* next;
    };
    
    struct node *loadWords(FILE *stream);
    
    int main()
    {
        FILE *stream = NULL;
        struct node *head;
        struct node *temp;
        struct node *loop;
        head = loadWords(stream);
        if ( head == NULL) {
            return 1;
        }
        temp = head;//print each word
        while ( temp != NULL) {
            printf ( "%s\n", temp->word);
            temp = temp->next;
        }
    
        temp = head;// free memory
        while ( temp != NULL) {
            loop = temp->next;
            free ( temp->word);
            free ( temp);
            temp = loop;
        }
        return 0;
    }
    
    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;
        }
        fclose ( stream);
        return head;
    }
    

    【讨论】:

      【解决方案2】:

      由于您似乎知道如何分配内存,我假设问题是您不知道为每个单词分配多少。 (类似的想法也适用于逐行阅读)。

      如果您对每个单词可能有多大有所了解,您可以静态分配它,然后在读入每个单词后,动态分配您需要的正确大小。

      否则,您可以一次读入一个字符,直到读完一个单词,这样您就可以根据需要增加缓冲区。

      【讨论】:

        【解决方案3】:
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        struct node {
            char *word;
            struct node *next;
        };
        
        //struct codex unused
        
        struct node *loadWords(FILE *stream);
        
        int main(void) {
            struct node *head;
            FILE *stream = fopen("hw8.data", "r");//No sense to pass arguments If you do not open at caller side
            head = loadWords(stream);
            fclose(stream);
            {//test print and release
                struct node *p = head;
                while(p){
                    struct node *temp = p->next;
                    puts(p->word);
                    free(p->word);
                    free(p);
                    p = temp;
                }
            }
            return 0;
        }
        
        struct node *loadWords(FILE *stream) {
            struct node *head = NULL, *curr, *temp;
            char *words = NULL, *currentWord;
            size_t chrCount = 0;
        
            rewind(stream);
        
            while(getline(&words, &chrCount, stream) != -1){
                currentWord = strtok(words, " \t\n");
                while(currentWord != NULL){
                    if((temp = calloc(1, sizeof(struct node))) == NULL) {
                        fprintf(stderr, "ERROR - Could not allocate memory.\n");
                        exit(EXIT_FAILURE);
                    }
                    temp->word = strdup(currentWord);//malloc and strcpy
                    if(head == NULL){
                        curr = head = temp;
                    } else {
                        curr = curr->next = temp;
                    }
                    currentWord = strtok(NULL, " \t\n");
                }
            }
            free(words);
        
            return head;
        }
        

        【讨论】:

          【解决方案4】:

          解释这个想法:

          我的想法是将每个单词的字符链接到一个名为 Word 的链表中。然后,我将每个单词放入另一个名为Node 的链表中。 (当然一切都会动态分配)。

          文本示例:

          你好,世界,这里。

          我们的算法会做这样的事情:

          H-&gt;e-&gt;l-&gt;l-&gt;o -> W-&gt;o-&gt;r-&gt;l-&gt;d -> h-&gt;e-&gt;r-&gt;e

          注意:单词用空格或标准标点分隔,所以我使用isspaceispunct函数。

          这是我的代码:

          #include<stdio.h>
          #include<conio.h>
          #include<stdlib.h>
          #include <ctype.h>
          struct Node {
              char * word;
              struct Node* next;
          };
          
          struct Word {
              char chr;
              struct Word* next;
          };
          
          
          int main (void)
          {
             static const char filename[] = "C:\\a.txt";
             FILE *file = fopen(filename, "r");
             Node *list = 0;
             Node **last = &list;
             Word *word = 0;
             int list_size = 0;
             int word_size = 0;
             if ( file != NULL )
             {
                int ch, inword = 0;
                while ( 1 )
                {
                   ch = fgetc(file);
                   if ( isspace(ch) || ispunct(ch) || ch == EOF )
                   {
                      if ( inword )
                      {
                         inword = 0;
                         char * string = (char *) malloc(word_size+1);
                         for(int i=word_size-1; i>=0; i--) {
                             string[i]= word->chr;
                             Word * aux = word;
                             word = word->next;
                             free(aux);
                         }
                         string[word_size] = '\0';
                         Node * aux = (Node *) malloc(sizeof(Node));
                         aux->word = string;
                         aux->next = 0;
                         *last = aux;
                         last = & aux->next;
                         word_size = 0;
                      }
                      if(ch == EOF)
                          break;
                   }
                   else
                   {
                      inword = 1;
                      Word * aux = word;
                      word = (Word *) malloc(sizeof(Word));
                      word->chr = ch;
                      word->next = aux;
                      word_size++;
                   }
                }
                fclose(file);
                for(Node * aux = list ; aux; aux=aux->next) {
                    puts(aux->word);
                }
                getchar();
             }
             return 0;
          }
          

          希望我能帮上忙。

          快乐编码:D

          【讨论】:

          • 我在 Visual c++ 中处理过这段代码,所以可能是我不小心包含了 c++ 的一些特性。大声笑,我在代码中使用了true ,我将其编辑为1。 @BLUEPIXY 请告诉我我的代码中是否使用了另一个功能,它在 c++ 中退出,而不是在 c 中。
          • 可以切换编译器选项的设置。
          猜你喜欢
          • 2012-06-25
          • 1970-01-01
          • 2021-10-26
          • 1970-01-01
          • 2021-12-16
          • 2020-03-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多