0

I've been trying to write some code for an assignment, which takes the contents of a list and saves them into a file. Afterwards, it has to load the contents from said file to a list. The header file was given by my professor. What I need to write is the actual code.

list.h:

#ifndef LIST_H_
#define LIST_H_

#define TRUE 1
#define FALSE 0
typedef struct nodeR* node;
struct nodeR{
    char payload[20];
    node next;
    node previous;
};    
typedef struct listR* list;
struct listR{
    node head;
    node tail;
    int length;
};
list initList(); //creates a new list and returns it. Returns NULL if it fails
int destroyList(list l); //frees memory from the list. Returns TRUE upon success or FALSE upon failure
int getNodeIndex(list l, node targetNode); //returns the position of the targetNode in the list. Returns a negative number if it fails
int getListLength(list l); //returns the length of the list. Returns a negative number if it fails
int addNode(list l, node newNode); //adds newNode at the end of the list. Returns TRUE upon success or FALSE upon failure
int insertNodeBefore(list l, node targetNode, node newNode); //injects newNode in the list right before the targetNode. Returns TRUE upon success or FALSE upon failure
int deleteNode(list l, node targetNode); //deletes targetNode from list. Returns TRUE upon success or FALSE upon failure
list reverseList(list l); //returns a list which is created by reversing the order of the elements of l. Returns NULL if it fails

#endif

file.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "file.h"
#include "list.h"

void saveListToFile(FILE* file, list l){
    char name[100];     
    int i;          
    node curNode;   
    printf("Give the name of the file you would like to save the contents of the list to.\n");
    fgets(name, 100, stdin);    
    file = fopen(name, "wb+");  
    if (file == NULL){      
        printf("Error: File could not be opened.\n");
        return;
    }
    strcpy(temp, curNode->payload);
    curNode = l->head;
    while (curNode != NULL){
        char temp[20];
        strncpy(temp, curNode->payload, sizeof(temp));
        fwrite(temp, 1, sizeof(temp), file);    
        curNode = curNode->next;    
    }
    fclose(file);                   
}

int getNodesInFile(FILE* file){
    char name[100];         
    int nodes;          
    fseek(file, 0, SEEK_END);   
    nodes = ftell(file) / 20;   
    fseek(file, 0, SEEK_SET);   
    return nodes;           
}

void loadListFromFile(FILE* file, list l){
    char name[100]; 
    value[20];
    int nodes, i;           
    node temp;          
    printf("Give the name of the file you would like to load the contents of on a list.\n");
    fgets(name, 100, stdin);
    strtok(name, "\n");
    file = fopen(name, "r");    
    if (file == NULL){      
        printf("Error: File could not be opened.\n");
        return;
    }
    nodes = getNodesInFile(file);   
    printf("%d\n", nodes);
    for (i = 0; i<nodes; i++){  
        fread(value, sizeof(value), 1, file);   
        strcpy(temp->payload, value);
        addNode(l, temp);           
    }
    fclose(file);                   
}

main.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "file.h"
#include "list.h"

int main(){
    int i;
    list l;
    l = initList();
    node r1, r2, r3, r4, curNode, current;

    FILE* file;
    //  loadListFromFile(file, l);
    //  printf("a\n");
    //  current = l->head;
    //  printf("b\n");
    //  while (current != NULL){
    //      printf("%sh\n", current->payload);
    //      current = current->next;
    //  }
    r1 = malloc(sizeof(struct nodeR));
    r2 = malloc(sizeof(struct nodeR));
    r3 = malloc(sizeof(struct nodeR));
    r4 = malloc(sizeof(struct nodeR));

    strcpy(r1->payload, "test1");
    strcpy(r2->payload, "test2");
    strcpy(r3->payload, "test3");
    strcpy(r4->payload, "test4");
    addNode(l, r1);
    addNode(l, r2);
    addNode(l, r3);
    addNode(l, r4);
    curNode = l->head;
    for (i = 0; i < l->length; i++){
        printf("%s\n", curNode->payload);
        curNode = curNode->next;
    }
    reverseList(l);
    current = l->head;
    while (current != NULL){
        printf("%s\n", current->payload);
        current = current->next;
    }
    saveListToFile(file, l);
    current = l->head;
    while (current != NULL){
        printf("%s\n", current->payload);
        current = current->next;
    }
    destroyList(l);
}

I tried testing the code with a main program that creates a list of 4 nodes, gives each node a "test1-4" payload value, and then calls saveListTofile() to try and save the contents of the list to a file. When I open the file afterwards, all there is in it is 1 line saying [object Object]. I am fairly new to files, so I have no idea what might have caused this, and whatever I have tried so far has failed. Any help is greatly appreciated.

Luke Sykpe
  • 311
  • 1
  • 11
  • 2
    emmm...am I the only one missing the `main()`? – Sourav Ghosh Jun 18 '15 at 14:53
  • No, I did not post it. Should I? I don't feel like it is really relevant to the problem, which, I think, lies with my use of fwrite(). – Luke Sykpe Jun 18 '15 at 14:59
  • Always try to provide a ___[MCVE](http://stackoverflow.com/help/mcve)___. It's of immense help. – Sourav Ghosh Jun 18 '15 at 15:02
  • what is `list`? a typedef? – Sourav Ghosh Jun 18 '15 at 15:04
  • @SouravGhosh I would, if I knew how to, per say. I am a beginner in C, and programming in general, so I have next to no idea what information people do and do not need in order to understand my problem. – Luke Sykpe Jun 18 '15 at 15:05
  • Don't get me wrong, I'm not blaming you, i'm just informing you regarding the best way to get help here. :-) – Sourav Ghosh Jun 18 '15 at 15:06
  • Yes, list is a typedef in list.h. I just checked my post above, and the line has been erased. Probably a mistake I made while formatting the code before posting, since on my Visual Studio 2013 project, where I copied from, the line is there. I corrected it. – Luke Sykpe Jun 18 '15 at 15:07
  • I know the professor gave it to you, but see [Is it a good idea to `typedef` pointers](http://stackoverflow.com/questions/750178/is-it-a-good-idea-to-typedef-pointers) for why you shouldn't do what the code given to you does do. – Jonathan Leffler Jun 18 '15 at 15:43
  • Note that `fgets()` keeps the newline; your file name has a newline at the end of it. Not a good idea. – Jonathan Leffler Jun 18 '15 at 15:44
  • I did that, as somebody already suggested in the comments of the answer, and it solved the problem. Now, the issue is, I found another problem in loadListFromFile(), in that, I apparently can't copy the contents of a string to a node->payload. Here's my example: `strcpy(temp->payload, value);` where value is this: `char value[20]`, and the payload of a `node temp` is a string of 20 characters, as seen in the structs above. I did `fread(value, sizeof(value),1, file);` before the strcpy, and when the program reaches strcpy() it crashes with Segmentation Fault (core dumped) – Luke Sykpe Jun 18 '15 at 15:50
  • You've not shown the definition of `temp` — it seems to be a global variable defined in `file.h` (given that we can see most everything else). You should be using `sizeof()` or a defined constant instead of writing 20 more than once. – Jonathan Leffler Jun 18 '15 at 15:52
  • I'm sorry, I forgot to edit the code on the post. It is done now, and you can see loadListFromFile() as it is in my file.c. Note that the crash happens on the line `strcpy(temp->payload, value);` – Luke Sykpe Jun 18 '15 at 16:06
  • I tried doing that, and it didn't help. The problem seems to be with temp->payload, since the program crashes wherever I use that. – Luke Sykpe Jun 18 '15 at 16:41

1 Answers1

1

In the function that saves, you need to compute temp for each node.

Something like:

strcpy(temp, curNode->payload);
for(; curNode != NULL; curNode = curNode->next) {
    char temp[20];
    strncpy(temp, curNode->payLoad, sizeof temp);
    fwrite(temp, 1, sizeof temp, file);
    curNode = curNode->next;    
}

You must also open your file in binary mode ("wb+") for this.

Note: the above is probably the first time I actually recommend strncpy() on this site. So rare is this need for a fixed-width record. Amazing! :)

unwind
  • 391,730
  • 64
  • 469
  • 606
  • Does that hinder my ability to use the file as a random access one though? The assignment specifies the file has to be a random access one, and after some google searching, I came upon the use of fwrite(). – Luke Sykpe Jun 18 '15 at 15:04
  • @LukeSykpe Does that mean you want fixed length per row? You can do that with pure text as well, although line endings introduce some ambiguity. – unwind Jun 18 '15 at 15:07
  • I think, yes. The assignment specifies the program will be tested with a "student information saving/sorting" algorithm, and the user (via my professor's main function) should be able to navigate to, say, the 20th student in the file without having to save the 19 prior to him to the list, using fseek(). – Luke Sykpe Jun 18 '15 at 15:09
  • So, I changed it, but it didn't change anything. When the program asks me for the name of the file, I use "test" or "test.txt", and, in both cases, when I open the file, it only says [object Object] in it. – Luke Sykpe Jun 18 '15 at 15:20
  • @user3121023 Thanks a bunch. That actually solved the problem. When I open the file test.txt, now, it reads "test4test3test2test1", like (I think) it should. Even so, I have another issue with loadListFromFile, which I described in the comments of the original question above. – Luke Sykpe Jun 18 '15 at 15:52