1

A uni project I have involves sorting a very large set of data into two different lists, one which has a bunch of data on a city or country, and another which has that same data (on a city, this time), but also with some coordinates, like so:

//used for cities and countries in the textual mode
typedef struct node{
  int year;
  int month;
  float temp;
  char* name;

  struct node* next;
  struct node* prev;
} node_t;

//used for cities in the graphical mode
typedef struct City{
  node_t data;
  float latitude;
  float longitude;
} City;

That is the way I set this up, but it doesn't allow me to use the same functions, because the pointers I have are to 'node', not 'City'. I could make them both like the second one, but putting half a million entries in memory, each with two empty floats would be kind of unnecessary and problematic.

I'm looking to use the same functions for both of them. The functions are your usual linked list ones, like sorted insertion and such. I was trying to use void pointers before, casting them as needed, but that means my functions must have two parts to them.

I'm looking to change the uhh... structure of my structs, so that they allow me to use the same functions simply, without the need for casts, or with a minimal one at least.

They are quite similar as you can see, but nothing comes to mind. Any ideas would be greatly appreciated. Cheers!

Alex
  • 133
  • 3
  • There are only a few more than 200 countries in the world, so wasting a couple floats in the country list isn't a big deal. The country's latitude and longitude could be the lat/long of the capital city. Then they aren't wasted. – user3386109 May 13 '18 at 21:00
  • Well, it depends, but yes, it is possible and legal to cast a `City *` to `node *`. – Antti Haapala -- Слава Україні May 13 '18 at 21:01
  • See also: https://stackoverflow.com/questions/8416417/nested-structs-and-strict-aliasing-in-c – Antti Haapala -- Слава Україні May 13 '18 at 21:03
  • The list has half a million entries... It has the temperature of a country or city in an arbitrary year and month – Alex May 13 '18 at 21:03
  • Still not worth the trouble. On a 64-bit system, each struct will be 40 bytes, or 48 bytes with lat/long. So 20MB versus 24MB for a list with half a million entries. On a 32-bit system, the struct will be 24 bytes, or 32 bytes with lat/long. So 12MB versus 16MB. I don't think there are any systems where that difference in size makes any difference in the viability of your program. And more to the point, if you were to implement EyIM's answer, you would find that you're using *more* memory than just wasting a couple floats. – user3386109 May 13 '18 at 21:24
  • In fact, on a 64-bit system, if you combine `year` and `month` into a single `int`, and then add `latitude` and `longitude` to the struct, the struct size will remain unchanged at 40 bytes. – user3386109 May 13 '18 at 21:31
  • 1
    Thank you for doing the math user3386109, I guess it is not as problematic as I thought. I'll either try that, or using different functions for each list type, as it turns out I only need to repeat like 4 of them. – Alex May 13 '18 at 21:45

1 Answers1

0

You could modify your linked list implementation to use void* as a data pointer.

struct Node
{
  void *data;
  struct Node *next;
}

The insert function should look something like:

Node * insert (struct Node *h, void *data, size_t data_size)
{
  Node *node = malloc(sizeof(Node));
  node->data = malloc(data_size);
  memcpy(node->data, data, data_size);
  node->next = h;
  h = node;
  return h;
}

When inserting City or any other type:

City* city = malloc(sizeof(City));
insert(head, city, sizeof(City));
EylM
  • 5,967
  • 2
  • 16
  • 28