0

I have a program coded in Windows 10, and it works perfectly. In this case (I'm going to simplify this overly because this is where the program fails), it takes a simple linked list of 200 elements (struct) and copies the data of the first 100 elements into an array of 100 elements (array[100]). The program works perfectly on Windows, but it doesn't copy a single struct on Ubuntu. Is there any difference between the GCC compiler from both systems that can cause this?

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 100

typedef struct{
  int id;
  char title[100];
  char director[100];
  char genre[100];
  int likes;
  int number_of_voters;
  float average_rating;
  int year;
  int cost;
  char color[100];
  float ratingW;
}Movie;

struct Node{
  Movie movie;
  struct Node *next;
};

//Simply linked list
typedef struct{
  struct Node *head;
}List;

//Array
typedef struct{
  Movie movies[SIZE];
  int num;  //number of elements
}Array;

void Initialize(List *l);
void PrintList(List l);
void InsertNode(List *l, Movie reg);
void PrintMovie(Movie mov);
void PrintArray(Array arr);
void FromListToArray(List l, Array *arr);

int main(){
  List sls;
  Array a;
  Initialize(&sls);
  PrintList(sls);  //Prints 200 movies, and shows the message "Movies loaded in the list ::: 200"
  FromListToArray(sls, &a);
  PrintArray(a);  //Doesn't print any movie, and shows the message "Movies loaded in the array ::: 0"
  return 0;
}

//Initializes the list
void Initialize(List *l){
  l->head = NULL;
}

void PrintList(List l){
  struct Node *p;
  p = l.head;
  while(p != NULL)
  {
    PrintMovie(p->movie);
    p = p->next;
  }
}

//Inserts a node at the beginning of the list
void InsertNode(List *l, Movie reg){
  struct Node *r;
  r = (struct Node *) malloc (sizeof(struct Node));;
  if (r == NULL){
    printf("No memory!\n");
  }
  else{
    r->movie.id = reg.id;
    strcpy(r->movie.title, reg.title);
    strcpy(r->movie.director, reg.director);
    strcpy(r->movie.genre, reg.genre);
    r->movie.likes = reg.likes;
    r->movie.number_of_voters = reg.number_of_voters;
    r->movie.average_rating = reg.average_rating;
    r->movie.year = reg.year;
    r->movie.cost = reg.cost;
    strcpy(r->movie.color, reg.color);
    r->movie.ratingW = reg.ratingW;
    r->next = l->head;
    l->head = r;
  }
}

/*Copies the data from a txt file into a simply linked list. 
Line 1 is the id of the first movie, line 2 the title... line 10 is the color. 
Line 11 is the id of the second movie, and so on... This repeated 200 times (200 movies = 2000 lines)*/
void FromTxtToList(List *l, FILE *f){
  int j = 0;
  char cad[100];
  Movie reg;
  f = fopen("movies.txt", "r");
  if (f == NULL){
    printf("Error, could not open the file\n");
  }
  else{
    while(!feof(f)){
      fgets(cad, 100, f);
      reg.id = atoi(cad);
      fgets(cad, 100, f);
      strcpy(reg.title, cad);
      fgets(cad, 100, f);
      strcpy(reg.director, cad);
      fgets(cad, 100, f);
      strcpy(reg.genre, cad);
      fgets(cad, 100, f);
      reg.likes = atoi(cad);
      fgets(cad, 100, f);
      reg.number_of_voters = atoi(cad);
      fgets(cad, 100, f);
      reg.average_rating = atof(cad);
      fgets(cad, 100, f);
      reg.year = atoi(cad);
      fgets(cad, 100, f);
      reg.cost = atoi(cad);
      fgets(cad, 100, f);
      strcpy(reg.color, cad);
      reg.ratingW = 0;
      InsertNode(l, reg);
      j++;
    }
  }
  fclose(f);
  printf("Movies loaded in the list ::: %d\n", j);
}

void PrintMovie(Movie mov){
  printf("///////////////////////////////////\n");
  printf("Id: %d\n", mov.id);
  printf("Title: %s", mov.title);
  printf("Director: %s", mov.director);
  printf("Genre: %s", mov.genre);
  printf("Likes: %d\n", mov.likes);
  printf("Number of voters: %d\n", mov.number_of_voters);
  printf("Average rating: %.2f\n", mov.average_rating);
  printf("Year: %d\n", mov.year);
  printf("Cost: $%d\n", mov.cost);
  printf("Color or BW: %s", mov.color);
  printf("Rating: %.2f\n", mov.ratingW);
  printf("///////////////////////////////////\n");
}

void PrintArray(Array arr){
  int i;
  printf("\nArray: \n");
  for(i=0; i < arr.num; i++){
    PrintMovie(arr.movies[i])
  }
}

void FromListToArray(List l, Array *arr){
  int i = 0;
  arr->num = 0;
  struct Node *p;
  p = l.head;
  while ((p != NULL) && (arr->num < SIZE)){
    if (strcmp(p->movie.color, "Color\n")==0){  
    //If I find a "colored" movie (color = "Color")
      //Copy the data into the array
      arr->movies[i].id = p->movie.id;
      strcpy(arr->movies[i].title, p->movie.title);
      strcpy(arr->movies[i].director, p->movie.director);
      strcpy(arr->movies[i].genre, p->movie.genre);
      arr->movies[i].likes = p->movie.likes;
      arr->movies[i].number_of_voters = p->movie.number_of_voters;
      arr->movies[i].average_rating = p->movie.average_rating;
      arr->movies[i].year = p->movie.year;
      arr->movies[i].cost = p->movie.cost;
      strcpy(arr->movies[i].color, p->movie.color);
      arr->movies[i].ratingW = p->movie.ratingW;
      arr->num++;
      i++;
    }
    p = p->next;
  }
  printf("Movies loaded in the array ::: %d\n", arr->num);
}
digest
  • 19
  • 5
  • 2
    Maybe, but it's overwhelmingly more likely that you have a UB bug:( – Martin James Nov 26 '19 at 20:12
  • Also, it's that 'doesn't compile' != 'doesn't work correctly when run' – Martin James Nov 26 '19 at 20:14
  • @Martin James UB? – digest Nov 26 '19 at 20:16
  • We'd definitely need to see the snippet of code in question. Also, how do you know the data isn't being copied? – Mike Robinson Nov 26 '19 at 20:18
  • 1
    For us to help you, we need a [mcve] that illustrates the problem. – Code-Apprentice Nov 26 '19 at 20:18
  • UB: **Undefined Behaviour**, see [wikipedia article](https://en.wikipedia.org/wiki/Undefined_behavior) or [c2 wiki](http://wiki.c2.com/?UndefinedBehavior) – pmg Nov 26 '19 at 20:19
  • 1
    UB means that you are doing something that is undefined and the nice windows guys made an assumption about what you wanted it to do – Hogan Nov 26 '19 at 20:20
  • One might be a debugging version. The undefined behaviour does not have to give the same result on both systems (or even be consistent on one system). – Weather Vane Nov 26 '19 at 20:24
  • Added some code. – digest Nov 26 '19 at 20:51
  • Yeah.... 'while ((p != NULL)' ... you really sure that sls is correctly initialized/loaded? Check with your debugger. – Martin James Nov 26 '19 at 21:04
  • @Martin James Yeah. I have a function to print the list (it prints the 200 movies correctly), and I looked what happens if I print p->movie (in the FromListToArrayt function, after p = l.head) and it prints the first movie correctly. So I'm sure the list is loaded correctly. – digest Nov 26 '19 at 21:09
  • I wouldn't be so sure. There may be something to `//sls already with the content I want, 200 structs Movie` that we're not seeing. A [mcve] would confirm this. – dbush Nov 26 '19 at 21:16
  • `FromListToArray(sls, &a);` causes undefined behaviour (`sls` is uninitialized and you pass it by value) – M.M Nov 26 '19 at 21:25
  • @M.M It is initialized, because it has contents, I just didn't include the function here. – digest Nov 26 '19 at 22:13
  • Ok I added some more functions, I think that should cover all the code with the problem I'm having. – digest Nov 26 '19 at 22:51
  • Would you mind to provide a (small) example of the input file? And I don't think that `Initialize(&sls); PrintList(sls);` will print any movie. – the busybee Nov 27 '19 at 07:58
  • @thebusybee [this](https://i.imgur.com/u8jUFiX.png) is what the file looks like. Although keep in mind that since `InsertNode` inserts at the beginning, the last movie of the file will be the first node. Inverse order. – digest Nov 27 '19 at 10:31
  • Well, please [edit] your question with an excerp of the input file. I'm afraid no-one would like to type all that lines by hand. And where in your [example] is the `List sls` filled before the call of `PrintList(sls)`? – the busybee Nov 27 '19 at 10:55

1 Answers1

0

First, in function PrintArray

there is a miising ";" in the line PrintMovie(arr.movies[i]).

Second, there is an issue with while(!feof(f)) in the function FromTxtToList.

Apparently feof() is TRUE only after the end of file (EOF) is read, not when EOF is reached. See here and here.

A possible fix could be if(fgets(cad, 100, f)==NULL) break;

instead of fgets(cad, 100, f);

in function FromTxtToList.

Also the movies.txt file should end with only one empty line (otherwise you will get "Color" instead of "Color\n" for the last movie).

Chan Tzish
  • 1,108
  • 9
  • 7