c - 使用 fgets 和 strtok 并尝试打印创建的节点时出现 NULL 节点或空格

标签 c linked-list fgets strtok

当尝试打印句子时,获取空格或 NULL 节点时遇到问题。

输入文件是txt文件,内容为“这是我们闪耀的时刻”,不带引号

还存在两个空输出文件,用于与当前问题无关的后续输出。

代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 200
typedef struct data{
    char *word;
    struct data *next;
}node;
node *head=NULL;
node *copy=NULL;
node *prev=NULL;
int _log=-1;
void read_content(char *filename);//prototype
node* create_word(char *string);//prototype
void add_word(node *word);//prototype
void delete_word(char *string);//prototype
void print_words();//prototype
void log_it(node *curr, node *next, int op);//prototype
void undo();//prototype


int main(int argc, char *argv[]){
    if(argc!=4){
        printf("\nInvalid parameters");
        return 0;
    }//end if
    head=malloc(sizeof(node));
    copy=malloc(sizeof(node));
    prev=malloc(sizeof(node));
    read_content(argv[1]);
    int option=4;
    int stringLength;
    char *del_word=malloc(sizeof(char) * MAX);
    char *word=malloc(sizeof(char) * MAX);
    node *addit;
    while(option!=0){
        printf("\nSentence: ");
        print_words();
        printf("\nMenu: \n(1) Add new word\n(2) Delete word\n(3) Undo last action\n(0) Exit\nOption: ");
        scanf("%d", &option);
        if(option==1){//add new word
            printf("\nPlease enter new word: ");
            scanf("%s", word);
            addit=create_word(word);
            printf("\n%s", word);
            add_word(addit);
        }//end if
        else if(option==2){//delete option
            printf("\nPlease enter word to delete: ");
            scanf("%s", del_word);
            delete_word(del_word);
        }//end if
        else if(option==3){
            undo();
        }//end if
        else if(option==0){
            printf("\nTerminating program");
            return 0;
        }//end if
        else{
            printf("\nUnrecognized option");
        }//end else
    }//end while
    return 0;
}//end main

//this is course cs2050
void read_content(char *filename){
    FILE *input=fopen(filename, "r");
    if(input==NULL){
        head=NULL;
        printf("\nEmpty list started");
    }
    char s[MAX];
    char* token;
    while(fgets(s, sizeof(s), input) != NULL)
    {
      int length = strlen(s)-1;
      if(s[length] == '\n') 
         s[length] = '\0';
    }//end while

    token = strtok(s, " ");
    //head = NULL;
    node *newnode;
    while (token)
    {
            char *s = malloc(sizeof(char) * strlen(token));
            strcpy(s, token);
            newnode=create_word(s);//create new node 
            printf("\n%s", newnode->word);//error checking
            add_word(newnode);//add to linked list 
            token = strtok(NULL, " ");
    }//end while

    fclose(input);
}//end read content

//creates node from char string
node* create_word(char *string){
    node *newNode=malloc(sizeof(node));
    newNode->word=string;
    newNode->next=NULL;
    return newNode;
}//end create word

//adds node to link list
void add_word(node *word){
    node *current=head;
    if(current==NULL){
        current=word;
    }//end if
    else{
        while(current->next!=NULL){
            current=current->next;

        }//end while;

        current->next=word;
    }//end else
    //printf("\n%s", current->next->word);
    _log=1;
}//end add word


void delete_word(char *string){
    node *current=head;
    node *previous=NULL;
    while(string!=current->word){
        previous=current;
        current=current->next;
    }//end while
    if(string==current->word){
        previous->next=current->next;
        copy->word=current->word;
        copy->next=current->next;
        prev=current;
    }//end while
    _log=-1;
}//end delete word

//function to print linked list as sentence
void print_words(){
    node *printhead=head;
    //printf("\n");
    //printhead=printhead->next;
    while(printhead!=NULL){
        printf("%s ", printhead->word);
        printhead=printhead->next;  
    }//end while
}//end print words


void log_it(node *curr, node *next, int op){

}//end log it


void undo(){
    node *current=head;
    node *prev=malloc(sizeof(node));
    if(_log==-1)//last action was delete word
    {

    }//end if
    else if(_log==1)//last action was insert word
    {

    }//end else if
    else{

    }//end else
}//end undo

输出如下:

print_words() 打印此内容: (null) 这是我们闪耀的时刻

一开始似乎有一个空节点在起作用,但似乎找不到原因。

最佳答案

这是工作代码;它比您提供的更接近于 SSCCE。空指针(打印为 (null))的问题是由于您处理空列表的方式而产生的。

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

#define MAX 200

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

node *head = NULL;

static void  read_content(char *filename);
static node *create_word(char *string);
static void  add_word(node *word);
static void  print_words(void);

int main(int argc, char *argv[])
{
    if (argc!=2)
    {
        fprintf(stderr, "Usage: %s file\n", argv[0]);
        return 1;
    }

    read_content(argv[1]);
    print_words();

    return 0;
}

void read_content(char *filename)
{
    FILE *input = fopen(filename, "r");
    if (input==NULL)
    {
        fprintf(stderr, "Failed to open file %s for reading\n", filename);
        exit(1);
    }
    char s[MAX];

    while (fgets(s, sizeof(s), input) != NULL)
    {
        int length = strlen(s)-1;
        if (s[length] == '\n')
            s[length] = '\0';

        char* token = strtok(s, " ");

        while (token)
        {
            char *s = malloc(sizeof(char) * (strlen(token) + 1));
            strcpy(s, token);
            node *newnode = create_word(s);
            printf("Word: %s\n", newnode->word);
            add_word(newnode);
            token = strtok(NULL, " ");
        }
    }

    fclose(input);
}

node *create_word(char *string)
{
    node *newNode = malloc(sizeof(node));
    newNode->word = string;
    newNode->next = NULL;
    return newNode;
}

void add_word(node *word)
{
    if (head == NULL)
        head = word;
    else
    {
        node *current = head;
        while (current->next != NULL)
            current=current->next;
        current->next = word;
    }
}

void print_words(void)
{
    for (node *pw = head; pw != NULL; pw = pw->next)
        printf("%s ", pw->word);
    putchar('\n');
}

read_content() 的结构已被修改,因此它读取文件中所有行中的所有单词,而不仅仅是文件的最后一行。 main()head 的内存分配导致输出中出现虚假 (null)。该代码也在 add_word() 中修复。函数 print_words() 已被重写。大部分多余的 Material 都被无情地淘汰了;剩下的或多或少是必要的,以表明问题已得到解决。仍有改进的空间。 read_content() 中的字符串分配和复制可能会在 create_word() 中得到更好的处理;您可能想也可能不想考虑使用 strdup() 来复制字符串。

关于c - 使用 fgets 和 strtok 并尝试打印创建的节点时出现 NULL 节点或空格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17634720/

相关文章:

java - 递归方法到底如何返回最终值并分配其结果?

c - 将 c 控制台输入拆分为整数

c - 在 C 中使用 fgets() 作为非阻塞调用是否安全?

c - 选择选项时菜单中出现段错误?

c - 有关 .so 文件的信息

java - 按 LIFO 顺序从列表中获取对象? (后进先出)(初学者)

java - java中如何链接两个链表的元素?

C:打印的字符不正确,怀疑是内存。问题

cat/Xargs/command VS for/bash/command

c - 最简单程序反汇编说明(x86)