c - 我的链接列表正在打印文本文件中所有元素的最后一个单词

标签 c linked-list singly-linked-list

这段代码正在读取一个文本文件并将每个单词插入到链接列表中。 我是链表新手,现在已经为此工作了四个小时,但我一生都无法弄清楚这一点。

那么这是怎么回事呢?我已经检查了我知道的所有方法,但我一生都无法正确打印链接列表。我相信它与 push/append 函数有关。不知何故,它覆盖了链接列表中以前的所有内容。也许 printlist 函数会覆盖所有内容,但我不明白它是如何做到这一点的。

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

// A complete working C program to demonstrate all insertion methods
// on Linked List  
// A linked list node
struct Node;
void push(struct Node **head_ref, char *new_data);
void insertAfter(struct Node *prev_node, char *new_data);
void append(struct Node **head_ref, char *new_data);
void printList(struct Node *node);
int LINECOUNT(FILE *(*stream), char *filename);

struct Node {
    char *data;
    struct Node *next;
};

/* Given a reference (pointer to pointer) to the head of a list and 
   an int, inserts a new node on the front of the list. */
void push(struct Node **head_ref, char *new_data) {
    /* 1. allocate node */
    struct Node* new_node = (struct Node *)malloc(sizeof(struct Node));

    /* 2. put in the data  */
    new_node->data  = new_data;
    printf("push data:%s ", new_data);

    /* 3. Make next of new node as head */
    new_node->next = (*head_ref);

    /* 4. move the head to point to the new node */
    (*head_ref) = new_node;
}

/* Given a reference (pointer to pointer) to the head
   of a list and an int, appends a new node at the end  */
void append(struct Node **head_ref, char *new_data) {
    /* 1. allocate node */
    struct Node* new_node = (struct Node *)malloc(sizeof(struct Node));
    struct Node *last = *head_ref;  /* used in step 5*/

    /* 2. put in the data  */
    new_node->data  = new_data;
    printf("push data:%s ", new_data);

    /* 3. This new node is going to be the last node, so make next of
          it as NULL*/
    new_node->next = NULL;

    /* 4. If the Linked List is empty, then make the new node as head */
    if (*head_ref == NULL) {
       *head_ref = new_node;
       return;
    }

    /* 5. Else traverse till the last node */
    while (last->next != NULL)
        last = last->next;

    /* 6. Change the next of last node */
    last->next = new_node;
    return;
}

// This function prints contents of linked list starting from head
void printList(struct Node *node) {
    while (node != NULL) {
        printf(" %s ", node->data);
        node = node->next;
    }
}

int LINECOUNT(FILE *(*stream), char *filename) {            
    int size = 0;
    size_t chrCount;
    char *text;

    if ((*stream = fopen(filename, "r")) == NULL) {
        printf("LC Could not open hw8 data file.\n");
        exit(0);
    }
    while (1) {
        text = NULL;
        getline(&text, &chrCount, *stream); 
        free(text); /*free text*/
        if (feof(*stream))
            break;
        size++;
    }
    rewind(*stream);
    return size;
}

/*int wordCount(FILE *(*stream), char *filename, int lineCount) {
    char ch;
    int wordcount = 0;
    int charcount = 0; 
    *stream = fopen(filename, "r");
    int x = 0;
    int lineArr[lineCount];
    for (int i = 0; i < lineCount; i++) {
        lineArr[i] = 0;
    }
    if (*stream) {
        while ((ch = getc(*stream)) != EOF) {
            if (ch != ' ' && ch != '\n') {
                charcount++;
            }
            if (ch == ' ' || ch == '\n') { 
                wordcount++;
                lineArr[x] = lineArr[x] + 1;
            }
            if (ch == '\n') {
                x++;
            }
        }
        if (charcount > 0) {
            wordcount++;
            charcount++;
        }
    } else {
        printf("Failed to open the file\n");
    }

    // rewind(*stream);
    return lineArr;
}*/

int main(void) {
    char *fn = "hw8data.txt";
    int lineCount;
    FILE *stream;

    lineCount = LINECOUNT(&stream, fn);
    //int lineArr[lineCount];
    //int lineArr[];//lineArr[0] = 4 would say the first line has 4 words. using this data for strtok

    //lineArr = wordCount(&stream, fn, lineCount);

    //-------------------------------------
    char ch;
    int wordcount = 0;
    int charcount = 0; 
    stream = fopen("./hw8data.txt", "r");
    int x = 0;
    int lineArr[lineCount];
    for (int i = 0; i < lineCount; i++) {
        lineArr[i] = 0;
    }
    if (stream) {
        while ((ch = getc(stream)) != EOF) {
            if (ch != ' ' && ch != '\n') {
                charcount++;
            }
            if (ch == ' ' || ch == '\n') {
                wordcount++;
                lineArr[x] = lineArr[x] + 1;
            }
            if (ch == '\n') {
                x++;
            }
        }
        //if (charcount > 0) { wordcount++; charcount++; }
    } else {
        printf("Failed to open the file\n");
    }
    /* Start with the empty list */
    struct Node *head = NULL;
    rewind(stream);
    char *sArr = malloc(42 * sizeof(char));

    fscanf(stream, "%s ", sArr);
    printf("%s ", sArr);
    push(&head, sArr);
    fscanf(stream, "%s ", sArr);
    printf("%s ",sArr);
    append(&head, sArr);
    printList(head);
    return 0;
}

最佳答案

  char* sArr=malloc(42*sizeof(char));

  fscanf(stream,"%s ",sArr);
  printf("%s ",sArr);
  push(&head,sArr);
  fscanf(stream,"%s ",sArr);
  printf("%s ",sArr);
  append(&head,sArr);

您将相同的值添加到列表中两次,这是您从一次返回的值,并且仅调用malloc。如果您希望两个节点保存不同的值,请不要将相同的值添加两次。一个丑陋的修复是,如果在 push(&head,sArr) 之后添加另一个 sArr = malloc(42*sizeof(char));。这样,您对 append 的调用就会向列表添加不同的值。

如果您没有看到此内容,请添加代码以在打印列表时输出 node->data 的值。您将看到两个节点都有指向同一 block 内存的指针,即您从调用 malloc 中返回的值。

但是如果您的列表条目拥有其内容,那就更优雅了。这需要像 pushappend 这样的函数来分配自己的指针,将字符串复制到其中,然后使用这些新指针。销毁列表的代码可以对指向的数据以及节点调用free

关于c - 我的链接列表正在打印文本文件中所有元素的最后一个单词,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52911257/

相关文章:

c - IP_ADD_MEMBERSHIP/IP_DROP_MEMBERSHIP 和 IP_ADD_SOURCE_MEMBERSHIP/IP_DROP_SOURCE_MEMBERSHIP 有什么区别?

c - 打印链表时出现问题

c - 如何从命令行使用创建的 Linux 内核字符驱动程序

c - scanf/getchar 只有第一次通过循环才能正常工作吗?

java - 打印在java中产生错误的输出

C - 嵌套链表

c - C 中删除列表节点的这一段是什么意思

c - 如何修改链表中的插入函数以适合所需的输出?

c - Tizen 屏幕键盘(输入组件)文本截断

java - 协助仅使用节点创建 java 链表