Losing linked list after printing - c

I have the following code:
if (strcmp(method, "print") == 0){
for (i = 0; i < hashtable->M; i++){
fprintf(fout,"[%d] :", i);
if (hashtable->v[i] != NULL)
while(hashtable->v[i]){
fprintf(fout," ");
((Pair*)hashtable->v[i]->info)->fp(hashtable->v[i], fout);
hashtable->v[i] = hashtable->v[i]->urm;
}
fprintf(fout,"\n");
}
}
In my code, when I encounter a "print" from the file, I have to print out the values stored in my hashtable. M is the size of the hashtable, while v is a void* which points to a linked list. It's all good but if I have to add some values in the hashtable and then print them, after printing I lose all the previously stored values. I think this might have to do with the fact that I'm doing this: hashtable->v[i] = hashtable->v[i]->urm; but even so, I don't know how to recover the values. I was thinking about something as an auxiliary pointer to the hashtable, but that failed for me. Note, the structures are as follow
typedef struct celulag {
void *info;
struct celulag *urm;
} TCelulaG, *TLG, **ALG;
typedef unsigned int (*TFHash)(const void*, size_t M, size_t range);
/* structura tabela Hash */
typedef struct {
size_t M;
TFHash fh;
TLG *v;
} TH;
typedef void (*TPrint)(TLG l, FILE *g);
typedef struct {
void *key;
void *value;
TPrint fp;
int frequency;
} Pair;
Note that this is done in a while so the assignment would look as this:
Add 3 values, print, add another 4 values, print. After adding the first 3 values, if I prind, it's all good, after adding the next 4 values, if I print, only the last 4 values appear.
Can anyone help? Thank you very much.

Related

C : Binary tree infinite recursion problem

I can't seem to find where the problem is in my code, i'm essentially storing character patterns, if an existing pattern is already present I'll store it in the duplicate node, otherwise it will shift to the regular pattern one. The problem starts when i have a duplicate, it should move to the duplicate node, but instead loops infinitely.
The binary tree struct: :
struct arbre{
char id[10];
int length;
int token;
int count;
struct arbre *pattern;
struct arbre *doublon;
};
typedef struct arbre *Arbre;
The function to create and make new nodes
void ajouter(Arbre *a, char *tablettre, int length, int token){
if(*a==NULL){
*a=(Arbre)malloc(sizeof(struct arbre));
strcpy((*a)->id, tablettre);
//append((*a)->id,tablettre);
//printf("%s",(*a)->id);
(*a)->length = length;
(*a)->token = token;
(*a)->doublon=NULL;
(*a)->pattern=NULL;
}
if (strcmp((*a)->id, tablettre) == 0){ /// The problem is here
printf("%s",(*a)->doublon->id);
printf(" and %s",tablettre);
ajouter(&(*a)->doublon, tablettre, length, token);
}
if (strcmp((*a)->id, tablettre) != 0){
ajouter(&(*a)->pattern, tablettre, length, token);
}
}

Array of structures: printing all members of each structure

I'm trying to print out all the members of each structure from a list. I was provided the print functions below to print out an element from a generic list.
Here is the structure definition of my list, which is in a generic list ADT c file:
struct list_type {
void *data;
int size;
int capacity;
int elementSize;
int (*comparePtr) (void *d1, void *d2);
};
So in a generic list ADT c file, I have this print function:
// client needs to send a pointer to a function capable of printing an element
void printl(ListType listptr, void (*printItem) (void *d)) {
int i;
for(i = 0; i < listptr->size; i++) {
// since we cannot use data[i], we need to calculate the address
// of the element to be sent to the client's print function
// since data is of type void, the formula is:
// the beginning address of the array + (offset x element size)
printItem(listptr->data + i * (listptr->elementSize) );
printf(" ");
}
printf("\n");
}
I call my printl function like so:
printl(clientList, printItem);
In my driver file, there's a function to print out an element from the list:
void printItem (int* p) {
printf("%d", *p);
//`my attempt at printing the members of an individual structure from the list
// printf("%s", ((Client *)&p)[0]);
}
Here is my Client structure definition:
struct client_tag {
char id[5];
char name[30];
char email[30];
char phoneNum[15];
};
When I run the program, I get a bunch of weird characters. How do I fix this?
Assuming you left out the line
typedef struct client_tag Client;
and assuming the strings of Client are guaranteed to be null terminated, this is the idea:
void printItem (const Client* p) {
printf("%s\n", p->id);
}

How to write a linked list to a file

I'm a new programmer and I am having some troubles writing a linked list to a text file.
Here's my code:
typedef struct N {
int code;
char name[MAX1];
int items;
float price;
struct N *next;
} node_t;
typedef struct {
int code;
char name[MAX1];
int items;
float price;
} product;
product p;
product *ptr = &p;
node_t *iterator = head;
FILE *fp;
fp = fopen("newfile.txt", "w+");
while (iterator != NULL) {
p.code = iterator->code;
strcpy(p.name, iterator->name);
p.items = iterator->items;
p.price = iterator->price;
fwrite(ptr, 1, sizeof(product),fp);
iterator = iterator->next;
}
at this point, I read from stream and display what I should have written on "newfile.txt", but all it prints out is '0' where there should be an integer/float and nothing where there should be a string.
I've also tried writing to the file a simple integer with fputs() and other functions, but it printed out random numbers.
In case you are wondering, since I haven't copied the whole code here, the list is NOT empty and I can display correctly all of the items in it.
I'm sorry if I haven't been clear, but this is my first post here. Hope someone can help me, thank you!
I would suggest the following changes:
Divide the struct for each node into two structs - one for holding the data and one for capturing the next pointer.
typedef struct
{
int code;
char name[MAX1];
int items;
float price;
} NodeData;
typedef struct N {
NodeData data;
struct N *next;
} node_t;
Now the function to write the contents of a linked list can be:
fp = fopen("newfile.txt", "w+");
// Get the size of the linked list and write as the first piece of data.
size_t listSize = getLinkedListSize(head)
fwrite(&listSize, 1, sizeof(size_t), fp);
// Now write each node of the linked list.
while (iterator != NULL) {
fwrite(&(iterator->data), 1, sizeof(iterator->data), fp);
iterator = iterator->next;
}
fwrite just writes the binary representation of the data, rather than an ASCII representation as you might expect to see in a text file. An integer, for instance, will be represented by four NUL characters, which you won't be able to see. So your code might well be working.
If you want to write something out as text, use fprintf, e.g.:
fprintf(fp, "%d,%d,%lf,\"%s\"\n",
iterator->code, iterator->items, iterator->price, iterator->name);
would be a rough approximation of CSV (note it doesn't escape characters inside the name).
By the way, why not just make add a member variable of node_t which is a product? Then you can avoid all that copying about.

Array of structs - deleting/adding elements and printing

For the below code
struct orderSlip
{
char source[64];
char destination[64];
char item[64];
int position;
};
//global
struct orderSlip data[100];
Is there another way of printing out the data for each element other than these methods below:
printf("%s\n",data[0].source);
printf("%s\n",data[0].destination);
printf("%s\n",data[0].item);
printf("%i\n\n", data[0].position);
printf("%s\n",data[1].source);
printf("%s\n",data[1].destination);
printf("%s\n",data[1].item);
printf("%i\n", data[1].position);
etc
for(int n = 0; n< 3; n++)
{
printf("%s\n",data[n].source);
printf("%s\n",data[n].destination);
printf("%s\n",data[n].item);
printf("%i\n\n", data[n].position);
}
For deleting and adding, do I have to make a dynamic array of structs? If so, what would be the simplest syntax to do that?
Something like this c++ code
int * bobby;
bobby = new int [5];
delete bobby[5];
but in C? I'm guessing it has do with malloc and free
"For deleting and adding, do I have to make a dynamic array of structs? If so, what would be the simplest syntax to do that? Something like this c++ code"
Not if you know that you will never have more than x amount of items or at least check to make sure you aren't exceeding what you planned was the max. Then you can use your static array.
Adding only requires you to have a variable that keeps track of how many items are in the array:
void add_item(struct orderSlip *p,struct orderSlip a,int * num_items)
{
if ( *num_items < MAX_ITEMS )
{
p[*num_items] = a;
*num_items += 1;
}
}
Deleting from a static array would require a for loop that would move the items above it down one and decrementing the int keeping track of the number of items.
void delete_item(struct orderSlip *p,int *num_items, int item)
{
if (*num_items > 0 && item < *num_items && item > -1)
{
int last_index = *num_items - 1;
for (int i = item; i < last_index;i++)
{
p[i] = p[i + 1];
}
*num_items -= 1;
}
}
You could simplify printing the struct by passing it to a function that does the work.
void print(const struct orderSlip *p);
or
void print(const struct orderslip s);
optionally
void print(const struct orderslip s, FILE *fp);
or
void print(const struct orderslip *p, FILE *fp)
{
fprintf(fp,"%s\n",p->source);
...
}
and
void print_all(const struct orderSlip *p, int num_items)
//global
struct orderSlip data[MAX_ITEMS];
int num_items = 0;
int main(void)
{
...
print_all(data,num_items);
strcpy(a.source,"source 2");
strcpy(a.destination,"destination 20");
strcpy(a.item,"item xyz");
a.position = 99;
add_item(data,a,&num_items);
print_all(data,num_items);
delete_item(data,&num_items,0);
print_all(data,num_items);
One way is to allocate each element in your array and just keep an array of pointers
struct orderSlip **data;
data = calloc(100, sizeof(struct orderSlip*)); // 100 pointers to struct
(calloc will make sure memory is zero:ed from the start)
everytime you add a new struct:
data[i] = calloc(1, sizeof(struct orderSlip));
and when you don't need any longer
free(data[i]);
You can also change the size of data by using realloc, see
If you don't need to access the array using index, you could instead consider another type of data structure like a linked list to be truly dynamic.

C - struct problems - writing

I'm making a program in C, and I'mm having some troubles with memory, I think.
So my problem is: I have 2 functions that return a struct. When I run only one function at a time I have no problem whatsoever. But when I run one after the other I always get an error when writting to the second struct.
Function struct item* ReadFileBIN(char *name) -- reads a binary file.
struct tables* getMesasInfo(char* Filename) -- reads a text file.
My code is this:
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int numberOfTables=0;
int numberOfItems=0;
//struct tables* mesas;
//struct item* Menu;
typedef struct item{
char nome[100];
int id;
float preco;
};
typedef struct tables{
int id;
int capacity;
bool inUse;
};
struct tables* getMesasInfo(char* Filename){
struct tables* mesas;
char *c;
int counter,numberOflines=0,temp=0;
char *filename=Filename;
FILE * G;
G = fopen(filename,"r");
if (G==NULL){
printf("Cannot open file.\n");
}
else{
while (!feof(G)){
fscanf(G, "%s", &c);
numberOflines++;
}
fclose(G);
}
/* Memory allocate for input array */
mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables*));
counter=0;
G=fopen(filename,"r");
while (!feof(G)){
mesas[counter].id=counter;
fscanf(G, "%d", &mesas[counter].capacity);
mesas[counter].inUse= false;
counter++;
}
fclose(G);
numberOfTables = counter;
return mesas;
}
struct item* ReadFileBIN(char *name)
{
int total=0;
int counter;
FILE *ptr_myfile;
struct item my_record;
struct item* Menu;
ptr_myfile=fopen(name,"r");
if (!ptr_myfile)
{
printf("Unable to open file!");
}
while (!feof(ptr_myfile)){
fread(&my_record,sizeof(struct item),1,ptr_myfile);
total=total+1;
}
numberOfItems=total-1;
Menu = (struct item *)calloc(numberOfItems , sizeof(struct item));
fseek(ptr_myfile, sizeof(struct item), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter < total ; counter++)
{
fread(&my_record,sizeof(struct item),1,ptr_myfile);
Menu[counter] = my_record;
printf("Nome: %s\n",Menu[counter].nome);
printf("ID: %d\n",Menu[counter].id);
printf("Preco: %f\n",Menu[counter].preco);
}
fclose(ptr_myfile);
return Menu;
}
int _tmain(int argc, _TCHAR* argv[])
{
struct item* tt = ReadFileBIN("menu.dat");
struct tables* t = getMesasInfo("Capacity.txt");
getchar();
}**
the error that im getting is :
"Unhandled exception at 0x00411700 in test.exe: 0xC0000005: Access violation writing location 0x00000000."
in "Menu[counter] = my_record;"
Thanks in advance.
You seem to allocate a memory block of the wrong size in getMesasInfo(): sizeof(struct tables*) gives you the size of the pointer, not that of the struct it is pointing to:
mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables*));
So you can easily overwrite unallocated memory. The proper allocation should be
mesas = (struct tables *)malloc(numberOflines* sizeof(struct tables));
or, similar to how you allocate the other array in ReadFileBIN():
mesas = (struct tables *)calloc(numberOflines, sizeof(struct tables));
Moreover, I don't know whether it's intentional or not, but in ReadFileBIN() you are allocating (1) and reading (2) one less record than the total number of records:
numberOfItems=total-1; // 1
Menu = (struct item *)calloc(numberOfItems , sizeof(struct item)); // 1
fseek(ptr_myfile, sizeof(struct item), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter < total ; counter++) // 2
...
Since the loop counter is started from 1 (instead of 0 as is normal in C), you effectively execute the loop total-1 times. That is, you read into elements 1 to total-1 of the array. However, the real elements of the array are indexed from 0 to total-2 so the very first element in the array is left uninitialized, and in the end you commit a buffer overflow error.
You have a problem in these lines:
numberOfItems=total-1;
Menu = (struct item *)calloc(numberOfItems , sizeof(struct item));
fseek(ptr_myfile, sizeof(struct item), SEEK_END);
rewind(ptr_myfile);
for ( counter=1; counter < total ; counter++)
First, you're setting numberOfItems to one less than the total. This is incorrect. You don't even need numberOfItems; since total has the number of lines in the file, the next line should really be Menu = (struct item*) calloc(total, sizeof(struct item));
Second, you're trying to use Menu as a one-based array in the for loop. C arrays are zero-based. You should have the for loop use for (counter = 0; counter < total; counter++).
Finally, as Peter pointed out, in the first function you're allocating the wrong size of object. You need to malloc numberOfLines*(sizeof(struct tables) (not sizeof(struct tables*).
To further illustrate Peter's point:
struct tables {
int id;
int capacity;
int inUse; /* bool is not a C type */
};
int main()
{
printf("sizeof: %d\n",sizeof(struct tables*));
printf("sizeof: %d\n",sizeof(struct tables));
}
Will output:
sizeof: 4
sizeof: 12

Resources