-2

I have a file.txt file

|i|Correo|Apellido|Nombre|
|-+------+--------+------|
|0|-a@.mx|----a---|--a---|
|1|-b@.mx|----b---|--b---|
|2|-c@.mx|----c---|--c---|

which I read with the following function

void readFILE()
{
    ifstream file;
    string line;
    file.open(path, ios::in);

    if(file.fail()) printf("Error reading\n");
    while(!file.eof())
    {
        getline(file, line);
        cout << line << endl;
    }
    file.close();
}

I have the problem that I can't think of a way to take each string I read as if the entire row were a string and store it in a doubly linked list.

example.

line[0] = "|i|Correo|Apellido|Nombre|";
line[2] = "|0|a@.mx |a       |a     |";

take each string and store it in:

struct node {
    string *data;
    struct node *next;
    struct node *prev;
    int size;
};

struct node* MakeNode(string *data)
{
    struct node* newnode = (struct node*) malloc(sizeof(struct node));
    newnode->prev = newnode;
    newnode->data = data;
    newnode->next = newnode;
    newnode->size = 1;
    return newnode;
}

struct node* addEnd(struct node* tail, string *data)
{
    struct node* newnode = MakeNode(data);
    if(tail == NULL) return newnode;
    else
    {
        struct node* temp = tail->next;
        newnode->next = temp;
        newnode->prev = tail;
        tail->next = newnode;
        temp->prev = newnode;
        tail = newnode;
        return tail;
    }
}

I imagine it as extracting the entire line of the file in a string, then storing that string in the data of the node and then doing operations with the nodes such as ordering.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 1
    see [Why !.eof() inside a loop condition is always wrong.](https://stackoverflow.com/q/5605125/9254539) Instead `while (getline(file, line)) { ... }` Also `file.close();` while proper is unnecessary, the stream with be automatically closed when `file` goes out of scope on program end. Other than using `iostream`, you list operations appear to be pure C. Are you sure you shouldn't be using `new` and `delete` for allocation and free in C++? (`malloc` and `free` are fine, just don't mix with `new` and `delete`) – David C. Rankin Mar 21 '22 at 03:21
  • Since you are using a number of C functions, reading `line` and then using `sscanf()` with `line.c_str()` provides an easy way to separate the values in each line. `strtok()` is another option, or manually parse with alternating `.find_first_of()` and `.find_first_not_of()` to pick out the strings between each `'|'`. – David C. Rankin Mar 21 '22 at 03:28

1 Answers1

1

Don't store a string pointer in your struct, store a string

struct node {
    string data;  <<<<<<<<<===========
    struct node *next;
    struct node *prev;
    int size;
};

and in make_node

node* MakeNode(const string &data)
{
   // struct node* newnode = (struct node*) malloc(sizeof(struct node));
    node *newnode = new node(); // see below
    newnode->prev = newnode;
    newnode->data = data;
    newnode->next = newnode;
    newnode->size = 1;
    return newnode;
}

in addEnd

 node* addEnd(struct node* tail,const string &data)
 {
    node* newnode = MakeNode(data);

I cannot see the caller of addEnd but you need to change that too.

This is the normal way to use strings in c++


EDIT, also do not use malloc in c++ programs, you must use new., also note that structs are full types in c++ no need for 'struct node' you can just say 'node'

So do

node* MakeNode(string *data)
{
    node* newnode = new node(); <<<<<======
    newnode->prev = newnode;
    newnode->data = data;
    newnode->next = newnode;
    newnode->size = 1;
    return newnode;
}

also see Why is "using namespace std;" considered bad practice?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
pm100
  • 48,078
  • 23
  • 82
  • 145
  • Switching to storing the string by value in `struct node` exposes a problem, because you're still advocating C-style allocation with `malloc`. This is "okay" for POD, but `std::string` is a non-trivial type and so its constructor is not invoked. Additionally, the new memory is not initialized so when you assign, you'll invoke the string's destructor on this uninitialized memory. You _could_ construct it correctly with placement-new and placement-delete, but that's just so nasty for this kind of usage. Use `node* newnode = new node;` and save the pain. – paddy Mar 21 '22 at 03:34
  • @paddy I did not notice a malloc, i will edit my answer - ty – pm100 Mar 21 '22 at 03:35