struct practice

This commit is contained in:
2026-05-30 17:57:52 +02:00
parent 42c08d947f
commit c737f8ab0f
3 changed files with 169 additions and 3 deletions
+40
View File
@@ -0,0 +1,40 @@
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <time.h>
struct IntArray{
int *data;
size_t length;
};
void readintarray(struct IntArray *input) {
printf("inputlength:%zu\n", input->length);
for (int i = 0; i < input->length; i++) {
printf("digit:%d = %d\n", i, input->data[i]);
}
}
int main() {
srand(time(NULL));
printf("how many numbers?\n");
int length;
scanf("%d", &length);
struct IntArray *myintarray = malloc(sizeof(struct IntArray)); /* allocate memory for struct */
int *myarray = malloc(sizeof(int) * length); /* allocate memory for array that the struct points to */
myintarray->data = myarray; /* make sure the pointer in the struct points to the array */
myintarray->length = length; //forgot to actually assign a value to the struct
for (int i = 0; i < length; i++) {
myintarray->data[i] = rand() % 10;
printf("number:%d = %d\n",i,myintarray->data[i]);
}
readintarray(myintarray);
free(myintarray->data);
free(myintarray);
return 0;
}
+122
View File
@@ -0,0 +1,122 @@
Since you are currently navigating the transition from "fixed-size" allocation (calculating everything upfront) to "dynamic" allocation (growing as you go), the best way to learn is to build in stages.
The reason you didn't need a `count` or `capacity` in your `Darray` is that you did **Pre-Calculation**: you figured out exactly how many digits were in the number before you called `malloc`.
But for user input, you can't pre-calculate. You need **Dynamic Growth**.
Here is a learning path split into 4 sub-assignments.
---
### Assignment 1: The "Fixed" Dynamic Array
**Goal:** Master the basic Struct $\rightarrow$ Pointer relationship.
**Task:** Create a program that asks the user "How many numbers do you want to enter?".
1. Create a struct `IntArray` with `int *data` and `size_t length`.
2. `malloc` the struct.
3. `malloc` the `data` array based on the user's number.
4. Fill it, print it, and free it.
**Key Lesson:** Understanding that the struct is the "handle" and the pointer is the "payload."
---
### Assignment 2: The "Growing" Dynamic Array
**Goal:** Understand `capacity` vs `length` and `realloc`.
**Task:** Modify Assignment 1, but **don't** ask the user for the size upfront.
1. Add `size_t capacity` to your struct.
2. Start `capacity` at 2.
3. Use a `while` loop to take input until the user types `-1`.
4. Inside the loop: If `length == capacity`, use `realloc` to double the `capacity`.
**Key Lesson:** `length` is how many items are *actually there*; `capacity` is how many items *can fit* before you need more memory.
---
### Assignment 3: The "Pointer to Pointers" (The String Array)
**Goal:** Understand "Deep Allocation" (Double Indirection).
**Task:** Change your `IntArray` to a `StringArray`.
1. Your struct now has `char **words`.
2. When you `realloc` the `words` array, you are only making room for more **addresses** (pointers).
3. For every string the user enters, you must `malloc` a **new** piece of memory for that specific string and `strcpy` the input into it.
**Key Lesson:** A `char**` is just an array of pointers. The array itself is one allocation, but every string it points to is a *separate* allocation.
---
### Assignment 4: The "Deep Free"
**Goal:** Prevent memory leaks in complex structures.
**Task:** Write a dedicated `free_string_array(StringArray *sa)` function.
1. It must loop through the array and `free()` every individual string first.
2. Then it must `free()` the `words` pointer array.
3. Finally, it must `free()` the struct itself.
**Key Lesson:** You must free memory in the exact reverse order that you allocated it.
---
### The "Scaffold" (Start here for Assignment 3/4)
If you want to jump straight to the strings, here is a clean scaffold. I have left "TODOs" where the logic should go.
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char **words;
size_t length;
size_t capacity;
} StringArray;
// Initialize the "Manager" struct
StringArray* create_sa() {
StringArray *sa = malloc(sizeof(StringArray));
sa->length = 0;
sa->capacity = 4; // Start small to force realloc to happen
sa->words = malloc(sizeof(char*) * sa->capacity);
return sa;
}
void add_word(StringArray *sa, const char *input) {
// TODO 1: Check if length == capacity.
// If so, use realloc to double the capacity of sa->words.
// TODO 2: Allocate memory for the new string.
// Hint: strlen(input) + 1
// TODO 3: Copy the input into the newly allocated memory.
// TODO 4: Store that pointer in sa->words[sa->length] and increment length.
}
void free_sa(StringArray *sa) {
// TODO 5: Loop through sa->words and free each individual string.
// TODO 6: Free the sa->words array itself.
// TODO 7: Free the sa struct.
}
int main() {
StringArray *myList = create_sa();
char temp[100];
printf("Enter words (type 'exit' to stop):\n");
while (scanf("%99s", temp) == 1 && strcmp(temp, "exit") != 0) {
add_word(myList, temp);
}
printf("\nStored words:\n");
for (size_t i = 0; i < myList->length; i++) {
printf("%zu: %s\n", i, myList->words[i]);
}
free_sa(myList);
return 0;
}
```
### Final tip on your `Darray` logic:
In your `Darray` code, you did:
`DigDarr->digits = (int *)(DigDarr + 1);`
This is very "clever" code, but in professional C, it is often avoided unless you are writing a high-performance kernel or library. It makes the code harder to read and makes `realloc` almost impossible (because the data is physically glued to the struct).
**The standard way** is to have the struct hold a pointer to a separate block of memory. It's slightly slower (one extra pointer jump), but it's much safer and more flexible.
+7 -3
View File
@@ -22,7 +22,10 @@ okay dit werkt nu omzetten naar strings
/* return 1 if word1 < word 2*/
int compareword(char word1[], char word2[]) {
for (int i = 0; i < WORDLENGTH; i++) {
if (word1[i] < word2[i]) {
if (word1[i] == word2[i]) {
//it should continue
}
else if (word1[i] < word2[i]) {
printf("%s is larger than %s\n", word1, word2);
return 1;
}
@@ -33,7 +36,6 @@ int compareword(char word1[], char word2[]) {
return 0;
}
/* eerst gewone bubblesort weer doen */
int mybubblesort(char inputarr[WORDS][WORDLENGTH]) {
for (int i = 0; i < WORDS - 1; i++) { // voor elk woord
@@ -60,9 +62,11 @@ int mybubblesort(char inputarr[WORDS][WORDLENGTH]) {
int main() {
char mytest[16][64] = {"pear", "watermelon", "apple", "banana", "cantaloupe", "Elephant", "Zebra"};
char mytest[16][64] = {"pear", "watermelon", "aap", "apple", "banana", "cantaloupe", "Elephant", "Zebra"};
srand(time(NULL));
mybubblesort(mytest);
return 0;
}