Home > OS >  how to take input from a text scanf and put it in linkedlist in C
how to take input from a text scanf and put it in linkedlist in C

Time:12-29

i'm trying to take input from a text file and put the value in a linked list variables, my file(text.txt) in in the following format: the first value is my burst time, the second arrival and the last value is the priority

the first value is my burst time, the second arrival and the last value is the priority, i want to make operations on all of these value from the same line like burst time prioriy and so on, and when the operation for the first line ends up, the program should pass to the next line until the time the prom will fin the EOF. now the big issue is when i'm trying to read each character and store each in a variable of a linked list for manipulation. find down my code:

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

typedef struct Node{
    int x;
    struct Node* next;
}Node;

void insert_end(Node** root, int value)
{
    Node* new_node = malloc(sizeof(Node));
    if(new_node == NULL)
    {
        exit(1);
    }
    new_node->next = NULL;
    new_node->x = value;


    if(*root == NULL)
    {
        *root = new_node;
        return;
    }

    Node* curr = *root;
    while(curr->next != NULL)
    {
        curr = curr->next;
    }
    curr->next = new_node;


}
//the part i'm reading the file
void deserialize(Node** root)
{
    FILE* file = fopen("text.txt","r");
    if(file == NULL)
    {
        exit(2);
    }
    int val;
    int val2;
    while(fscanf(file, "%d", &val)>0)
    {
        insert_end(root, val);
    }
    fclose(file);
}
int main(int argc, char* argv[])
{
    Node* root = NULL;
    if(root == NULL)
    {
        exit(2);
    }
    root->x = 15;
    root->next = NULL;

    deserialize(&root);


    for(Node* curr = root; curr != NULL; curr = curr->next)
    {
        printf("%d\n",curr->x);
    }

    deallocate(&root);
   
    return 0;
}

i really need your help, thank you

CodePudding user response:

The format string %d does not match the input :101 ,since : cannot be part of an integer. So scanf("%d") consumes nothing and the : is left in the input stream. You could use: while(fscanf(file, "M:", &val) == 1). If you are reading the last value on a line, the : will not match, but in this case you don't care. You might want to use fscanf(file, "M:M:M", ...) == 3 if you want to check the format of the input (ie, always exactly 3 inputs per line, so you can reject lines like 1:2:3:4:5:6:7). YMMV

CodePudding user response:

May be you could write this in 2 steps. First try to consume the data on file, then put the code to insert this into a linked list..

About the struct

typedef struct Node
{
    int          x;
    struct Node* next;
} Node;

maybe not the best way to describe a linked list. This is just a node and not a list. You will be better served with a bit of encapsulation. A list has metadata and pointers to nodes. Nodes points to or contain data. A list is NOT a node. A node is NOT a list. Program a linked list with just a node is problematic at best. Many loose pointers and your case even more problematic Node** pointers.

Compare with something like


typedef struct
{
    unsigned burst;
    unsigned arrival;
    unsigned priority;
}   Info;

typedef struct st_node
{
    Info* info;
    st_node* next;
    st_node* prev;
}   Node;

typedef struct
{
    Node* head;
    Node* tail;
    unsigned size;
}   List;

List* create();
List* destroy(List* list);
int insert(Info* one_item, List* list);

And see that a list is a list of nodes. Nodes points to info and info is the unit of data. Any data.

insert() inserts an item into a list, create() and destroy() manages lists and the encapsulation makes everything far more easier than just using pointers and pointers to pointers.

Consuming the file

Using this file as input.txt

2:101:34
20:10:3
5:1:4

and this data unit


typedef struct
{
    unsigned burst;
    unsigned arrival;
    unsigned priority;
}   Info;

See that the input is a CSV --- from Comma Separated Values --- file, a format from de '70s. The separator is a ':'.

scanf() and family was written for this: Scan Formatted Files, hence the name. It is a scanner. So it is easier to just use it in this way.

See this example

List* deserialize(const char* file)
{
    FILE* in = fopen(file, "r");
    if (in == NULL) return NULL;

    Info info = {};
    List* new_l = create(); // new list here
    while (3 == fscanf(
                    in, "%d:%d:%d", &info.arrival,
                    &info.burst, &info.priority))
    {
        fprintf(
            stderr, "%d:%d:%d\n", info.arrival, info.burst,
            info.priority);
        insert(&info, new_l); // insert data into list
    };
    fclose(in);
    return new_l; // returns a list with the data on file
}

and the output

2:101:34
20:10:3
5:1:4

when called as

    List* new_list = deserialize("input.txt");

as expected. And a List is returned with the data on file...

The complete code

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

typedef struct
{
    unsigned burst;
    unsigned arrival;
    unsigned priority;
} Info;

typedef struct st_node
{
    Info*    info;
    st_node* next;
    st_node* prev;
} Node;

typedef struct
{
    Node*    head;
    Node*    tail;
    unsigned size;
} List;

int   insert(Info* one_item, List* list);
List* create();
List* destroy(List*);

List* deserialize(const char* file)
{
    FILE* in = fopen(file, "r");
    if (in == NULL) return NULL;

    Info info = {};
    List* new_l = create(); // new list here
    while (3 == fscanf(
                    in, "%d:%d:%d", &info.arrival,
                    &info.burst, &info.priority))
    {
        fprintf(
            stderr, "%d:%d:%d\n", info.arrival, info.burst,
            info.priority);
        insert(&info, new_l); // insert data into list
    };
    fclose(in);
    return new_l; // returns a list with the data on file
}

int main(void)
{
    List* new_list = deserialize("input.txt");
    new_list       = destroy(new_list);
    return 0;
}

int insert(Info* one_item, List* list) { return 0; }

List* create()
{
    List* L = (List*)malloc(sizeof(List));
    if (L == NULL) return NULL;
    L->size = 0;
    L->head = NULL;
    L->tail = NULL;
    return L;
}

List* destroy(List* list) { return NULL; }
  • Related