I am currently trying to make function create() for singly linked list, where I am supposed to pass unlimited amount of parameters and it will pass the parameters as nodes' values. The code looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
//define sllnode struct
typedef struct sllist
{
int val;
struct sllist *next;
}
sllnode;
sllnode* create(int count, ...);
int main(void)
{
//here i try to print out values of this list
sllnode* new_sllist = create(34,2,5,18);
//print out values that I have assign using create() to test
for(int i = 0; i < 4; i++)
{
printf("%i\n",new_sllist[i].val);
}
}
//create function
sllnode* create(int count, ...)
{
va_list list;
int i;
int arr[count];
va_start(list, count);
//create array arr that have all the values passed as parameters
for(i = 0; i < count; i++)
{
arr[i] = va_arg(list,int);
}
//allocate memory for new singly linked list
sllnode *sllist = malloc(count * sizeof(sllnode));
//check if memory has been successfully allocated
if(sllist == NULL)
{
printf("Unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
// loop through array arr and assign values to val and *next of each sllnode in new sllist
for (int j = 0; j < count; j++)
{
sllist[j].val = arr[j];
sllist[j].next = &sllist[j+1];
if(j == count - 1)
{
sllist[j].val = arr[j];
sllist[j].next = NULL;
}
}
return sllist;
free(sllist);
}
But when I print out I only receive the last 3 values (2,5,18) and a number -23791193490 which differs each time (I suppose this has seeped into another part of memory). How do I do this correctly?
You are passing 34 for the count parameter. Correct usage would be:
sllnode* new_sllist = create(4,34,2,5,18);
Related
I'm dealing with implementing a hash table. My understanding of a hashtable is that is that to have an array like table where you're able to access the elements quickly by getting the hash value and modding it by the table size. So my initial thought was declaring
Node *hTable [100];
where
typedef struct node {
char *s;
int value;
} Node;
and going to the index of the array and malloc a new element that belongs there. But, the problem is that I need to grow my table.
So, my question is, how would I make a dynamic table, but access it like an array? (e.g table[i]).
I know that you need to call something like
Node *table = (Node*)malloc(sizeof(Node)*size);
which lets you access it like a table table[i] =... but if I did that, I can't declare a new Node in the index of the table
table[i]=(Node*)malloc(sizeof(Node));
Here's a code that I've been testing with (getting seg fault) to better give a view of the problem:
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 typedef struct node {
5 int data;
6 struct node *next;
7 } Node;
8
9
10 void main() {
11 Node **list;
12 *list = (Node*)malloc(sizeof(Node)*10);
13 for (int i = 0; i < 10; i++) {
14 list[i] = (Node*)malloc(sizeof(Node)); //problem here?
15 list[i]->data = i;
16 list[i]->next = NULL;
17 }
18 printf("printing...\n");
19 for (int i = 0; i < 10; i++) {
20 printf("%d ", list[i]->data);
21 }
22 }
Your problem is how you allocate space for list. list is uninitialized and does not point to valid memory, you must allocate space for it first, and then allocate space for each element:
#include <stdio.h>
#include <stdlib.h>
typedef struct node
{
int data;
struct node *next;
} Node;
int main() //return type of main is int
{
Node **list;
list = malloc(10 * sizeof *list); //allocate memory for list not *list, also no need to cast return value of malloc.
for (int i = 0; i < 10; i++)
{
list[i] = malloc(sizeof *list[i]); //allocate space for each element.
list[i]->data = i;
list[i]->next = NULL;
}
printf("printing...\n");
for (int i = 0; i < 10; i++)
{
printf("%d ", list[i]->data);
}
return 0;
}
It doesn't need to be an array of pointers, you can simply make an array of nodes, with:
Node *list = malloc(sizeof *list * count);
Then you can access list[i].s and list[i].value.
When you want to grow the table, you use realloc():
new_list = realloc(list, sizeof *list * new_count);
if (new_list) {
list = new_list;
} else {
// report allocation failure
}
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
int main() {
// just initialize it this way ( previous was undefined behavior, dereferencing an initialize pointer)
Node **list= malloc(sizeof(Node*)*10);
for (int i = 0; i < 10; i++) {
list[i] = malloc(sizeof(Node*)); //problem here?
list[i]->data = i;
list[i]->next = NULL;
}
printf("printing...\n");
for (int i = 0; i < 10; i++) {
printf("%d ", list[i]->data);
}
}
I'm trying to build an arraylist in C with the following code
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// Declaration of ArrayList structure
typedef struct ArrayList {
int length, capacity;
int *items;
} ArrayList;
// Create a new ArrayList
ArrayList *newList() {
int *items = malloc(4 * sizeof(int));
ArrayList *list = malloc(sizeof(ArrayList));
list->length = 0;
list->capacity = 4;
list->items = items;
return list;
}
// Check and expand list if neccessary
void check(ArrayList *list) {
printf("Check called (%d, %d)\n", list->length, list->capacity);
if (list->length >= list->capacity) {
printf("Expanding\n");
list->capacity = list->capacity * 2;
printf("Reallocating\n");
list->items = realloc(list->items, list->capacity);
if (list->items == NULL) {
printf("realloc failed\n");
exit(1);
}
}
}
// Add a value to the ArrayList
void add(ArrayList *list, int n) {
check(list);
list->items[list->length] = n;
list->length++;
}
// Print the list
void printList(ArrayList *list) {
for (int i=0; i<list->length; i++) {
if (i > 0) printf(", ");
printf("%d", list->items[i]);
}
printf("\n");
}
int main () {
ArrayList *list = newList();
for (int i = 0; i < 20; i++) {
add(list, i);
}
printList(list);
}
When the array is full, the check function is called as it should be. However, the second time the check function is called, the program failes on the call to realloc giving the following error:
*** Error in `./test': realloc(): invalid next size: 0x0000000001d3c010 ***
Aborted (core dumped)
where the size varies every time the program is run.
I have read that this error is caused by a corrupt heap, which is normally caused by pointers going wrong somewhere. However, I cannot see where the problem lies in this example. Any help would be appreciated.
you are reallocating the list->items. realloc() function has 2 parameter
first one is void pointer ,this point to the memory block that previously allocated,and second parameter works for how many bytes have to reallocate.
in your code you added only the capacity...bt it is not .u have to add size of the int with capacity ...cause it only takes (size ) int byte ...
then it works fine
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
// Declaration of ArrayList structure
typedef struct ArrayList {
int length, capacity;
int *items;
} ArrayList;
int i;
// Create a new ArrayList
ArrayList *newList() {
int *items = malloc(4 * sizeof(int));
ArrayList *list = malloc(sizeof(ArrayList));
list->length = 0;
list->capacity = 4;
list->items = items;
return list;
}
// Check and expand list if neccessary
void check(ArrayList *list) {
printf("Check called (%d, %d)\n", list->length, list->capacity);
if (list->length >= list->capacity) {
printf("Expanding\n");
list->capacity = list->capacity * 2;
printf("Reallocating\n");
list->items = realloc(list->items, list->capacity * sizeof(int));
if (list->items == NULL) {
printf("realloc failed\n");
exit(1);
}
}
}
// Add a value to the ArrayList
void add(ArrayList *list, int n) {
check(list);
list->items[list->length] = n;
list->length++;
}
// Print the list
void printList(ArrayList *list) {
for (i=0; i<list->length; i++) {
if (i > 0) printf(", ");
printf("%d", list->items[i]);
}
printf("\n");
}
int main () {
ArrayList *list = newList();
for ( i = 0; i < 20; i++) {
add(list, i);
}
printList(list);
}
I am trying to take input from console and add it to hash table.
But I'm getting Segmentation fault 11.
So, I debugged the program using gdb-apple.
It is showing that I'm trying access memory I cannot, using the pointer variable.
I think it is something obvious, but I'm missing it
This is what the gdb is displaying
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000986 in CreateHashTable (size=200) at hashing.c:29
29 h->Table[i]->next = NULL;
Here is the code
Header File:
#define LOAD_FACTOR 20
#define INITIAL_SIZE 200
struct HashTable *CreateHashTable(int size);
int HashSearch(struct HashTable *h,int data);
int HashInsert(struct HashTable *h,int data);
int HashDelete(struct HashTable *h, int data);
void Rehash(struct HashTable *h);
int Hash(int data, int size);
struct ListNode
{
int key;
int data;
struct ListNode *next;
};
struct HashTableNode
{
int bcount;
struct ListNode *next;
};
struct HashTable
{
int tsize;
int count;
struct HashTableNode **Table;
};
Implementation file:
#include "hashing.h"
#include<stdio.h>
#include<stdlib.h>
struct HashTable *CreateHashTable(int size)
{
struct HashTable *h;
h = (struct HashTable *) malloc ( sizeof(struct HashTable) );
if(h == NULL)
{
printf("Memory Error");
return NULL;
}
h->tsize = (int) size/LOAD_FACTOR;
printf("h->tsize = %d",h->tsize);
h->count = 0;
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
if( h->Table == NULL )
{
printf("Memory Error");
return NULL;
}
int i;
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
return h;
}
I would paste the rest of file, or Driver file, but I don't see it relevant.
Please tell me why I'm getting the segmentation fault 11
You allocated memory for array of pointers but you didn't allocate memory for members of this array.
for( i=0 ; i < (h->tsize) ; i++)
{
h->Table[i] = malloc(...); //put correct arguments here and check allocation
h->Table[i]->next = NULL;
h->Table[i]->bcount = 0;
}
Your problem is here:
struct HashTableNode **Table;
You want an array of nodes (not a 2d array), change to:
struct HashTableNode *Table;
also change
h->Table = malloc ( ( sizeof(struct HashTableNode **) ) * (h->tsize) );
to
h->Table = malloc(sizeof(struct HashTableNode) * h->tsize);
I think I want an array of pointers to nodes, don't I?
As pointed out by #WhozCraig, there is no reason for the additional level of indirection.
Example A (Pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a; /* pointer */
int i, n = 10;
a = malloc(n * sizeof(int)); /* space for 10 ints */
for (i = 0; i < n; i++) {
a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", a[i]);
}
free(a);
return 0;
}
Example B (Pointer to pointer):
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int **a; /* pointer to pointer*/
int i, n = 10;
a = malloc(n * sizeof(int *)); /* space for 10 pointer to ints */
for (i = 0; i < n; i++) {
a[i] = malloc(sizeof(int)); /* space for 1 int */
*a[i] = i;
}
for (i = 0; i < n; i++) {
printf("%d\n", *a[i]);
free(a[i]);
}
free(a);
return 0;
}
As you can see both do the same thing, but the first one requires less memory and the code is cleaner.
One way to make it easy to remember is:
int * can hold an array
int ** can hold a table (NROWS * NCOLS)
int *** can hold an array of tables
I wrote a piece of code to handle dynamic arrays. Idea was to use array of struct pointers, where the last member of array is NULL. Slight variation of code I wrote is below (using integers and not structures).
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int **list, int* value) {
for(int i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
}
void list_init(int **list) {
int* x;
for(int i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(list, x);
}
}
int main() {
int** l = malloc(sizeof(int*));
l[0] = NULL;
list_init(l);
}
While debugging, I discovered that only first 3 integers are added to the list. I can't seem to figure out why is this happening. Any ideas?
The problem is that the call to realloc() in list_add() potentially frees the memory block *list and allocates another. list_add updates its list pointer, but it does not return the updated pointer to the caller, list_init(); list_init()'s list pointer is potentially a pointer to the recently-freed memory block.
To fix this code, list_add() and list_init() need to be able to "return" the updated list pointer:
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
void list_add(int ***p_list, int *value) {
int **list = *p_list;
int i;
for(i = 0; true; i++) {
if(list[i] == NULL) {
list = realloc(list, (i+2) * sizeof(int*));
list[i] = value;
list[i+1] = NULL;
break;
}
}
*p_list = list;
}
void list_init(int ***p_list) {
int **list = *p_list;
int *x;
int i;
for(i = 0; i < 100; i++) {
x = malloc(sizeof(int));
*x = i;
list_add(&list, x);
}
*p_list = list;
}
int main() {
int **list = malloc(sizeof(int*));
list[0] = NULL;
list_init(&list);
int **l = list;
for (; *l != NULL; ++l) {
printf("%d\n", **l);
}
}
http://codepad.org/iGcSaJOR
EDIT
In this case of dynamic arrays the way you have told will not make anything better, the code will complicate only. For each addition of integer you have used realloc trying aggressively to save memory, but this will take more time while execution. Why not allocate a block of memory reserved for the array and to reflect the dynamic character put the array inside a struct with the last index, and when you add something add it on the last location and increment the counter. When this block is filled, you can chain another block to point to another one.
typedef struct _dyna_arr
{
my_type data_arr[MAX_LEN];
int n;
struct _dyna_arr *next block;
};
Therefore you maintain a linked list of multiple arrays. The size of MAX_LEN can be fixed which is appropriate for an application which will help decrease internal fragmentation.
*old answer removed *
I am goofing around with pointers and structures. I want to achieve the following:
(1) define a linked list with a structure (numberRecord)
(2) write a function that fills a linked list with some sample records by going thourgh a loop (fillList)
(3) count the number of elements in the linked list
(4) print the number of elements
I am now so far that the fillList function works well, but I do not succeed in handing over the filled linked list to a pointer in the main(). In the code below, the printList function only displays the single record that was added in main() instead of displaying the list that was created in the function fillList.
#include <stdio.h>
#include <stdlib.h>
typedef struct numberRecord numberRecord;
//linked list
struct numberRecord {
int number;
struct numberRecord *next;
};
//count #records in linked list
int countList(struct numberRecord *record) {
struct numberRecord *index = record;
int i = 0;
if (record == NULL)
return i;
while (index->next != NULL) {
++i;
index = index->next;
}
return i + 1;
}
//print linked list
void printList (struct numberRecord *record) {
struct numberRecord *index = record;
if (index == NULL)
printf("List is empty \n");
while (index != NULL) {
printf("%i \n", index->number);
index = index->next;
}
}
//fill the linked list with some sample records
void fillList(numberRecord *record) {
numberRecord *first, *prev, *new, *buffer;
//as soon as you add more records you get an memory error, static construction
new = (numberRecord *)malloc(100 * sizeof(numberRecord));
new->number = 0;
new->next = NULL;
first = new;
prev = new;
buffer = new;
int i;
for (i = 1; i < 11; i++) {
new++;
new->number = i;
new->next = NULL;
prev->next = new;
prev = prev->next;
}
record = first;
}
int main(void) {
numberRecord *list;
list = malloc(sizeof(numberRecord));
list->number = 1;
list->next = NULL;
fillList(list);
printf("ListCount: %i \n", countList(list));
printList(list);
return 0;
}
SOLUTION
Do read the posts below, they indicated this solution and contain some very insightful remarks about pointers. Below the adapted code that works:
#include <stdio.h>
#include <stdlib.h>
typedef struct numberRecord numberRecord;
//linked list
struct numberRecord {
int number;
struct numberRecord *next;
};
//count #records in linked list
int countList(struct numberRecord *record) {
struct numberRecord *index = record;
int i = 0;
if (record == NULL)
return i;
while (index->next != NULL) {
++i;
index = index->next;
}
return i + 1;
}
//print linked list
void printList (struct numberRecord *record) {
struct numberRecord *index = record;
if (index == NULL)
printf("List is empty \n");
while (index != NULL) {
printf("%i \n", index->number);
index = index->next;
}
}
//fill the linked list with some sample records
numberRecord *fillList() {
numberRecord *firstRec, *prevRec, *newRec;
int i;
for (i = 1; i < 11; i++) {
newRec = malloc(sizeof(numberRecord));
newRec->number = i;
newRec->next = NULL;
//initialize firstRec and prevRec with newRec, firstRec remains head
if (i == 1) {
firstRec = newRec;
prevRec = newRec;
}
prevRec->next = newRec;
prevRec = prevRec->next;
}
return firstRec;
}
int main(void) {
numberRecord *list;
list = fillList();
printf("ListCount: %i \n", countList(list));
printList(list);
return 0;
}
This statement in fillList
record = first;
has no effect on the list variable in main. Pointers are passed by value (like everything else) in C. If you want to update the list variable in main, you'll either have to pass a pointer to it (&list) and modify fillList accordingly, or return a numberRecord* from fillList. (I'd actually go with that second option.)
Here's a (bad) illustration:
When main calls fillList, at the starting point of that function, the pointers are like this:
main memory fillList
list ----> 0x01234 <---- record
A bit later in fillList, you allocate some storage for new (that's actually a bad name, it conflicts with an operator in C++, will get people confused)
main memory fillList
list ----> 0x01234 <---- record
0x03123 <---- new
At the last line of fillList you're left with:
main memory fillList
list ----> 0x01234 ,-- record
0x03123 <---- new
record and list are not the same variable. They start out with the same value, but changing record will not change list. The fact that they are both pointers doesn't make them any different from say ints in this respect.
You can change the thing pointed to by list in fillList, but you can't change what list points to (with your version of the code).
The easiest way for you to get around that is to change fillList like this:
numberRecord *fillList() {
....
return new;
}
And in main, don't allocate list directly, just call fillList() to initialize it.