TL/DR: Are linked lists the best solution for an Entity list in C or is there a better solution?
I'm currently in the process of refactoring a small tutorial roguelike I made in C in order to make the code conform to best practices. In my game I have a list of Items and a list of Monsters which I can iterate through in order to make monsters take turns or see if the player is able to pick up an Item. Until recently, I had these lists implemented simply as arrays of pointers with a respective int counter to keep count of how many Items or Monsters there were at any given time:
Item* items[15] = { NULL };
int n_items = 0;The arrays were bounded with a hard-coded limit (15 in this example). This limit could easily be observed when creating a new level and keep the number of items below the max, but once the player was given the option to 'drop' items, this limit became a problem, as any item carried over from other levels and dropped in a newly created dungeon level would now be added back into the item array and could easily overflow it.
In order to solve this issue I've implemented a singly linked list struct as:
typedef struct List
{
union {
Actor* actor;
Item* item;
};
struct List* next;
} List;This List struct uses the following function to add new Items to the list:
void appendItem(List* head, Item* item)
{
List* temp = head;
while (temp->next)
{
temp = temp->next;
}
temp->next = malloc(sizeof(List));
temp = temp->next;
temp->item = item;
temp->next = NULL;
}The list can now be initiated as:
List* items = malloc(sizeof(List)); items->item = NULL; items->next = NULL;
And I can iterate through the list with:
List* temp = items;
while (temp = temp->next)
{
checkSomething(temp->item);
}This setup now allows me to forget about a limit on items or actors and just add them as needed. However, before I continue with this structure and refactor all other arrays to use this, I wanted to ask if anyone knows whether this would be the best solution for the problem of the item and monster lists in a C roguelike. I've delved into the original Rogue source code and saw that the THING union has a prev and next pointers so I believe that it uses a similar setup, but I don't know if that is a good modern C solution. If any C developers would share any best-practices that they know of regarding this issue, it would be much appreciated. Thanks for taking the time to read through this and for any reply!
TL/DR: Are linked lists the best solution for an Entity list in C or is there a better solution?
C Program Length of Array
List input in C and length argument - Code Golf Meta Stack Exchange
How do I determine the size of my array in C? - Stack Overflow
(C#) find length of a List<String>?
How do you find the length of an array in C?
Why is `sizeof` used to determine the length of an array in C?
What is the length of an empty array in C?
Videos
The following code prints 40, but I expect the output to be 10. Any ideas why?
Not for all languages
I estimate 15% of my Python golfs with list input could be shortened by taking in its length, if that were allowed. Hundreds of golfs in mainstream languages could be improved by mechanically replacing "len(l)" or similar with an input parameter.
These submissions strongly suggest that golfers wouldn't guess this to be allowed without knowing the rule specifically. This is a hidden rule of the worst kind -- broadly useful, unexpected, and likely to make golfs more boring on average.
I'm sympathetic to the problems languages like C have with cumbersome input processing, especially as they already have many disadvantages. Golfing languages can be designed around such issues, but C is stuck with them.
But, I want to avoid the trend of giving all languages an easy extra workaround because one language really wants it. The result is a laundry list of liberties with input that go beyond taking it conveniently and naturally for the language, to doing parts of the golfing task in the input format, justified by citing obscure meta threads about other languages.
I'd rather say that this is a property of C that golfers need to deal with, or that a C-specific rule be made. Either one would be better than changing the rules for all languages.
This is an interesting indication of the way PPCG has changed since the early days. I remember when a lot of questions included the length as a separate input and people commented with requests to make it optional because their high-level languages didn't need it.
In most high-level languages an array is effectively a struct with a pointer and a length. I don't see that there's any point to creating a standard struct template. However, it does seem perfectly reasonable to interpret "array" in a question as meaning "pointer and length, as encapsulated in your language". In the case of C the simplest "encapsulation"* is as two variables.
* Yes, I get the point that it's not really encapsulation if you can split them up, hence the scare quotes. But such pedanticism is not the point here.
Executive summary:
int a[17];
size_t n = sizeof(a)/sizeof(a[0]);
Full answer:
To determine the size of your array in bytes, you can use the sizeof
operator:
int a[17];
size_t n = sizeof(a);
On my computer, ints are 4 bytes long, so n is 68.
To determine the number of elements in the array, we can divide the total size of the array by the size of the array element. You could do this with the type, like this:
int a[17];
size_t n = sizeof(a) / sizeof(int);
and get the proper answer (68 / 4 = 17), but if the type of
a changed you would have a nasty bug if you forgot to change
the sizeof(int) as well.
So the preferred divisor is sizeof(a[0]) or the equivalent sizeof(*a), the size of the first element of the array.
int a[17];
size_t n = sizeof(a) / sizeof(a[0]);
Another advantage is that you can now easily parameterize the array name in a macro and get:
#define NELEMS(x) (sizeof(x) / sizeof((x)[0]))
int a[17];
size_t n = NELEMS(a);
The sizeof way is the right way iff you are dealing with arrays not received as parameters. An array sent as a parameter to a function is treated as a pointer, so sizeof will return the pointer's size, instead of the array's.
Thus, inside functions this method does not work. Instead, always pass an additional parameter size_t size indicating the number of elements in the array.
Test:
#include <stdio.h>
#include <stdlib.h>
void printSizeOf(int intArray[]);
void printLength(int intArray[]);
int main(int argc, char* argv[])
{
int array[] = { 0, 1, 2, 3, 4, 5, 6 };
printf("sizeof of array: %d\n", (int) sizeof(array));
printSizeOf(array);
printf("Length of array: %d\n", (int)( sizeof(array) / sizeof(array[0]) ));
printLength(array);
}
void printSizeOf(int intArray[])
{
printf("sizeof of parameter: %d\n", (int) sizeof(intArray));
}
void printLength(int intArray[])
{
printf("Length of parameter: %d\n", (int)( sizeof(intArray) / sizeof(intArray[0]) ));
}
Output (in a 64-bit Linux OS):
sizeof of array: 28
sizeof of parameter: 8
Length of array: 7
Length of parameter: 2
Output (in a 32-bit windows OS):
sizeof of array: 28
sizeof of parameter: 4
Length of array: 7
Length of parameter: 1
I am attempting to grab a List<String> and iterate through each string in the list then Iterate through each Character in each string.
I can get the length of the list, but I am having a hard time getiing the length of the String.
List<String> myList;
for (int y = 0; y <= myList.Count(); y++)
{
for (int x = 0; x <= myList[y].Length ; x++)
{And I keep getting an index out of bounds error. I know I am probably going about this all wrong. So I will ask here for advice and come back tomorrow with a fresh head and see if it makes any more sense.
Thanks!