Reputation: 85
I am using a struct to store a string and an integer like so:
struct movement {
char *direction;
int steps;
};
I can add items into the struct by doing this
struct movement m1= { "right",20 };
struct movement m2= { "left" ,10 };
The end result I am trying to achieve is to collect user inputs (e.g. "right 20"), and store it in the struct. How can I store an unknown number of user inputs into the struct without the use of variables (m1, m2 etc) since I will not know how many items there will be at the end.
Upvotes: 1
Views: 788
Reputation: 26315
Use a linked list. It is a recursive data structure which would be great for what you want.
Here is some example code I wrote a while ago that might help:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* basic linked list structure */
typedef struct node node_t;
struct node {
char *direction;
int steps;
node_t *next;
};
/* pointers to the head and tail of the list */
typedef struct {
node_t *head;
node_t *foot;
} list_t;
list_t *initialize_list(void);
list_t *insert_nodes(list_t *list, char *direction, int steps);
void free_list(list_t *list);
node_t *generate_node(void);
void print_list(list_t *list);
void exit_if_null(void *ptr, const char *msg);
int
main(int argc, char const *argv[]) {
list_t *list;
/* empty list created */
list = initialize_list();
/* inserting information one a time */
list = insert_nodes(list, "right", 20);
list = insert_nodes(list, "left", 10);
print_list(list);
/* freeing list at the end */
free_list(list);
list = NULL;
return 0;
}
/* function to insert information into a node */
list_t
*insert_nodes(list_t *list, char *direction, int steps) {
/* called generate_node() to create a new node */
node_t *new;
new = generate_node();
/* puts steps information into node */
new->steps = steps;
/* allocates space for direction string */
/* this is needed because *direction is a pointer */
new->direction = malloc(strlen(direction)+1);
/* copies direction info into node */
strcpy(new->direction, direction);
/* inserting information at the tail of the list */
new->next = NULL;
if (list->foot == NULL) {
/* first insertion into list */
list->head = list->foot = new;
} else {
list->foot->next = new;
list->foot = new;
}
/* returns modified list */
return list;
}
.* function which generates new nodes */
node_t
*generate_node(void) {
node_t *newnode;
/* create space for new node */
newnode = malloc(sizeof(*newnode));
exit_if_null(newnode, "Allocation");
/* initialize node info to nothing */
newnode->direction = NULL;
newnode->steps = 0;
return newnode;
}
/* creates the empty linked list */
list_t
*initialize_list(void) {
list_t *list;
create space for list */
list = malloc(sizeof(*list));
exit_if_null(list, "Allocation");
/* set pointers to NULL */
/* We don't want them pointing at anything yet */
list->head = list->foot = NULL;
return list;
}
/* function which prints entire list */
void
print_list(list_t *list) {
/* start at the head of the list */
node_t *curr = list->head;
while (curr) {
printf("%s %d\n", curr->direction, curr->steps);
/* steps through the list */
curr = curr->next;
}
}
/* function which frees nodes */
void
free_list(list_t *list) {
node_t *curr, *prev;
/* start at beginning of list */
curr = list->head;
/* frees nodes one at a time */
while(curr) {
prev = curr;
curr = curr->next;
free(prev);
}
/* frees entire list */
free(list);
}
/* function which checks malloc(), and whether enough space was allocated */
void
exit_if_null(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}
Upvotes: 2
Reputation: 399949
It doesn't sound as if you really want to "store values into the struct", instead you want to store a sequence of independent struct instances; one for each user input.
The three most basic ways of doing this are:
Which one to prefer depends on which you think is simplest. If at all possible, a static appeoach is always simplest. You can easily have something like
struct movement movements[10000];
at the global level, this will only cost perhaps 120 KB on a 64-bit system. Note though that this doesn't include memory for the direction
strings; if those are always chosen from "right" and "left" (and perhaps "up"/"down" too) you could represent it as an enum instead:
enum direction { DIRECTION_LEFT = 0, DIRECTION_RIGHT, DIRECTION_UP, DIRECTION_DOWN };
This will make the structure "self-contained" and (on 64-bit systems) smaller since the enumeration will be smaller than a pointer.
Dynamically growing an array using realloc()
isn't too hard, you could look that up easily as its often used.
Upvotes: 4
Reputation: 2221
Use a LinkedList to store an indefinite number of movements. For each movement, create a node in the linked list and update the next pointer.
struct node {
struct movement m;
node* next;
}
Upvotes: -1