无法从文件打印字符串

Having trouble printing string from a file

我的任务是从文件中读取单词并分别打印每个单词。 到目前为止我得到了这个:

#define MAX 100000
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node *ptr;
typedef struct node {
    char *data;
    ptr next;
} node;

ptr head = NULL;

void add(char *data) {
        node *new_node = malloc(sizeof(node));
        new_node->data = data;
        new_node->next = head;
        head = new_node;
    printf("Adding new word:%s\n",data);
}

void print_list() {
    node *current = head;
        while (current != NULL) {
            printf("%s\n", current->data);
            current = current->next;
        }
}

void free_list(ptr *hnode)
{
    ptr p;
    while(*hnode){
        p = *hnode;
        *hnode = (*hnode)->next;
        free(p);
    }
}

int main(int argc, char *argv[]) {
    FILE *file;
    char buffer[MAX];
    char ch;
    int i = 0;

    if (argc != 2) {
        printf("Usage: %s <file>\n", argv[0]);
            exit(EXIT_FAILURE);
        }

        file = fopen(argv[1], "r");
        if (file == NULL) {
            printf("Error opening file\n");
            exit(EXIT_FAILURE);
        }

    while(i < MAX-1 && !feof(file))
    {
        if((ch = fgetc(file)) == ' '|| ch == '\n')
        {
            buffer[i] = '[=10=]';
            add(buffer);
            i = 0;
        }
        else{
            if(ch == EOF)
                  break;
            buffer[i++] = ch;
        }
    }

        print_list();
        free_list(&head);
        exit(EXIT_SUCCESS);
}

当我尝试 运行 代码时,没有编译或 运行 时间错误,但我只得到最后一个词和一个奇怪的符号,例如:

Adding new word:Hello
Adding new word:World!
Adding new word:Does
Adding new word:my
Adding new word:code
Adding new word:work?
work?
work?
work?
work?
work?
work?

当它说添加新词的部分正确并且正确读取文件时,我的问题是打印部分。 编辑:现在我有一个正确的 EOF 检查,仍然没有按预期工作。

当您调用 add(buffer) 时,您每次都传递完全相同的指针(从技术上讲,数组不是指针,但对于本次讨论而言它足够接近)。该指针被分配给节点的 data 字段。这意味着每个节点都包含对完全相同字符串的引用。这就是为什么每个节点都打印出相同的值。此外,随着您的代码变得越来越复杂,如果 buffer 的生命周期到期,您 运行 将面临这些引用变得无效的风险。

您要做的是使用 malloc 为每个节点提供自己的字符串副本。

void add(char *data) {
    size_t len = strlen(data);
    node *new_node = malloc(sizeof(node)); // Note: You should check this return value.
    new_node->data = malloc(len+1); // Note: Ditto.
    memcpy(new_node->data, data, len+1);
    new_node->next = head;
    head = new_node;
    printf("Adding new word:%s\n",data);
}

void free_list(ptr *hnode)
{
    ptr p;
    while(*hnode){
        p = *hnode;
        *hnode = (*hnode)->next;
        free(p->data);
        free(p);
    }
}

在函数中添加所有节点的数据成员数据指向main中声明的同一个数组缓冲区

void add(char *data) {
        node *new_node = malloc(sizeof(node));
        new_node->data = data;
        new_node->next = head;
        head = new_node;
    printf("Adding new word:%s\n",data);
}

所以函数print_list将输出缓冲区中最后存储的内容。

您需要动态复制传递的字符串。

还有这个while循环

while(i < MAX-1 && !feof(file))
{
    if((ch = fgetc(file)) == ' '|| ch == '\n')
    {
        buffer[i] = '[=11=]';
        add(buffer);
        i = 0;
    }
    else{
        buffer[i++] = ch;
    }
}

没有多大意义。首先,变量 ch 应声明为类型 int。循环中的条件

while(i < MAX-1 && !feof(file))

可能导致在缓冲区中存储值 EOF。输出证明了这一点。

(编辑:您问题中的此更新

       if(ch == EOF)
              break;

你是在我的回答之后做出来的。)

按一个字符读取字符串也是低效的。您应该使用函数 fscanf 而不是 fgetc.

注意不要定义全局变量head

ptr head = NULL;

并且当某些函数依赖于全局变量时。

此外,在程序的某些部分中,您使用的是 typedef 名称 ptr,而在程序的其他部分中,您使用的是类型 node *。这只会让代码的读者感到困惑。