2

I am trying to load a file into my program so I can work with the bytes on an individual basis, but when I am loading the file it stops loading prematurely; always by 1 character. If there is only one character in the file it does not load it. Is the problem with how I am reading the file or is it in a different location?

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

typedef struct node {//linked list structure, I use this because I am working with files of vastly varying length
    char val;
    struct node *next;
} data;

void printdata(data *head);
void freeData(data **head);
data* readFile(FILE *f);

void main(int argc, char *argv[]) {//set this up so it is easier to test
    if(argc == 2) {
        FILE *f = fopen(argv[1], "r");
        data *d = readFile(f);
        fclose(f);
        printdata(d);
        freeData(&d);
    }
}

data* readFile(FILE *f) {//This is the function containing the problem
    data *retVal = malloc(sizeof(data));
    data *cur = retVal;
    int c = fgetc(f);
    if(c != EOF) {
        retVal->val = (char) c;
        while((c = fgetc(f)) != EOF) {
            cur->next = malloc(sizeof(data));
            cur->next->val = (char) c;
            cur = cur->next;
        }
    } else return NULL;//EDIT: was in a rush and forgot to add this.
    cur->next = NULL;
    return retVal;
}

void freeData(data **head) {
    if((*head)->next != NULL) freeData(&((*head)->next));
    free(*head);
}

void printdata(data *head) {
    data *cur = head;
    do {
        printf("%c", cur->val);
        cur = cur->next;
    } while(cur->next != NULL);//EDIT: I changed this because there was a small "problem" that was not the real problem
    printf("\n");
}

2 Answers2

1

Let's look at the function printdata()

void printdata(data *head) {
    data *cur = head;
    while(cur->next != NULL) {
        printf("%c", cur->val);
        cur = cur->next;
    }
    printf("\n");
}

Notice that when

cur->next == NULL

The command inside the while will NOT be executed.

Also notice that this always happens at the last element. So your code won't print the last data.

Among other solutions, you could use a do-while loop:

do{
  printf("%c", cur->val)
  cur = cur->next;
} while (cur->next != NULL);

This will guarantee that the last element will printed, because the while will stop AFTER the inside of the loop is executed for the last element.

Hope this helps.

Luanf
  • 172
  • 1
  • 10
  • this is not the problem, I tried the change and the problem still exists in the same exact way. though thanks anyway – Egon Gilstrom Apr 16 '16 at 02:47
  • That's unfortunate. I do believe the "do while" is a improvement, but I understand if it is not the root of the problem. I'm burned out tonight, but if your problem stands by tomorrow I'll take another look! – Luanf Apr 16 '16 at 04:28
1

printdata() stops too soon. @Barmar

Do not stop when cur->next == NULL. Stop when cur == NULL

void printdata(data *head) {
  data *cur = head;
  while (cur) {
    printf(" <%hhx>", cur->val);  // Changed format for debugging
    fflush(stdout);               // Useful for debugging
    cur = cur->next;
  }
  printf("\n");
}

Also included is a simplified readFile().

data* readFile(FILE *f) { //This is the function containing the problem
  data head; // Only next field used
  data *cur = &head;
  int c;
  while ((c = fgetc(f)) != EOF) {
      cur->next = malloc(sizeof *(cur->next));
      cur = cur->next;
      assert(cur);
      cur->val = (char) c;
    }
  cur->next = NULL;
  return head.next;
}
Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256