Debugging: Problem with linked list linkage - c

I have a linked list implementation as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CAPACITY 128
typedef struct blob blob;
struct blob {
char text[CAPACITY];
struct blob* prev;
struct blob* next;
};
static blob* create_blob() {
blob* newBlob = malloc(sizeof(blob));
if (!newBlob) {
fprintf(stderr, "%s\n", "Malloc failed");
return 0;
}
newBlob->prev = 0;
newBlob->next = 0;
memset(newBlob->text, 0, CAPACITY);
return newBlob;
}
int insertAtTail(blob* list[static 1]) {
blob* newBlob = create_blob();
if (!newBlob) {
fprintf(stderr, "%s\n", "Malloc failed");
return 0;
}
if (!*list) {
*list = newBlob;
return 1;
}
blob* lastElement = *list;
while (lastElement->next) {
// Check if linkage until last element is okay
if (lastElement != (lastElement->next)->prev) {
fprintf(stderr, "%s\n", "The next_element->prev does not point to the current element");
} else {
fprintf(stderr, "%s\n", "Okay");
}
lastElement = lastElement->next; // Find last Blob
}
lastElement->next = newBlob;
newBlob->prev = lastElement;
return 1;
}
int reversePrintBlobs(blob const list[static 1]) {
if (!list) {
fprintf(stderr, "%s\n", "list is empty");
return 1;
}
const blob* tmp = list;
size_t blobCounter = 1;
while (tmp->next) {
blobCounter++;
tmp = tmp->next;
}
while (tmp && tmp != list) {
if ((tmp->prev)->next != tmp) {
fprintf(stderr, "%s\n", "error with the linkage");
exit(1);
}
printf("#number = %zu: %s\n", blobCounter--, tmp->text);
tmp = tmp->prev;
}
return 0;
}
When I add some blobs with the following main() function, it seems like the prev member of my struct doesn't point to the previous element. That is, there is a problem with the linkage. Can anyone point out why?
int main() {
FILE* pFile = fopen("example.txt", "r");
if (!pFile) {
perror("fopen failed\n");
return EXIT_FAILURE ;
}
fseek(pFile, 0, SEEK_SET);
blob* list = create_blob();
blob* tmp = list;
while (!feof(pFile)) {
size_t noBytesRead = fread(tmp->text, sizeof(char), CAPACITY,
pFile);
if (noBytesRead != CAPACITY && !feof(pFile)) {
fprintf(stderr, "%s\n", "File read failed");
exit(EXIT_FAILURE);
}
// Append a null terminating character in the end
tmp->text[noBytesRead] = '\0';
if (!feof(pFile) && insertAtTail(&list)) {
tmp = tmp->next;
}
}
}
On the other hand, If I use the following main() everything works fine.
int main() {
blob* list = create_blob();
insertAtTail(&list);
insertAtTail(&list);
insertAtTail(&list);
insertAtTail(&list);
insertAtTail(&list);
/* code */
return 0;
}

The bug has been fixed, the new main function is the following:
int main() {
FILE* pFile = fopen("example.txt", "r");
if (!pFile) {
perror("fopen failed\n");
return EXIT_FAILURE ;
}
fseek(pFile, 0, SEEK_SET);
blob* list = create_blob();
blob* tmp = list;
int blobCounter = 1;
while (!feof(pFile)) {
size_t noBytesRead = fread(tmp->text, sizeof(char), CAPACITY,
pFile);
if (noBytesRead != CAPACITY && !feof(pFile)) {
fprintf(stderr, "%s\n", "File read failed");
exit(EXIT_FAILURE);
}
// Append a null terminating character in the end
tmp->text[noBytesRead - 1] = '\0';
if (!feof(pFile) && insertAtTail(&list)) {
blobCounter++;
tmp = tmp->next;
}
}

Related

rename() function differs in levels of indirection from int

I'm trying to write a code that uses linked lists and files, to maintain actions (functions) that are given on a text file, instead of receiving them from the user.
For some reason i'm encountering an error which says:
"Severity Code Description Project File Line Suppression State
Error C2040 'rename': 'hw_component *(char *,char *,hw_component *)' differs in levels of indirection from 'int (const char *,const char *)' EX5_313410961 c:\users\edave\source\repos\ex5_313410961\ex5_313410961\shahar_connection.c 172"
I'm having trouble understanding if the problem is the actual function rename() or because of the actions() function.
The code is very long so ill post the relevant section only.
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define NAME_LENGTH 200
typedef struct hw_component
{
char name[NAME_LENGTH];
int copies;
struct hw_component *next;
}hw_component;
hw_component *create_component(char* name,int copies)
{
if (name != NULL && strlen(name) > NAME_LENGTH)
return NULL;
hw_component *comp = (hw_component*)malloc(sizeof(hw_component));
if (comp == NULL)
{
printf("Error: memory allocation failed\n");
return NULL;
}
strcpy(comp->name, name);
comp->copies = copies;
comp->next = NULL;
return comp;
}
hw_component *add_sort(hw_component* head, int copies, char *name)
{
hw_component *iter, *prev = NULL;
hw_component *new_comp = create_component(name, copies);
if (head == NULL)
return new_comp;
if (strcmp(new_comp->name, head->name) < 0)
{
new_comp->next = head;
return new_comp;
}
iter = head;
while (iter != NULL && strcmp(iter->name, new_comp->name) < 0)
{
prev = iter;
iter = iter->next;
}
prev->next = new_comp;
new_comp->next = iter;
return head;
}
hw_component *initialize(char *argv[])
{
hw_component *list_of_comp = NULL;
FILE *fp = NULL;
char dolar[2] = "$";
fp = fopen(argv[1],"r");
if (fp == NULL)
{
printf("Error: opening %s failed\n", argv[1]);
exit(1);
}
while (!feof(fp))
{
char str[400], *token, *str_num;
fgets(str, 400, fp);
int numb;
token = strtok(str,dolar);
str_num = strtok(NULL, dolar);
numb = atoi(str_num);
list_of_comp=add_sort(list_of_comp, numb, token);
}
fclose(fp);
return list_of_comp;
}
void finalize(hw_component *head, char *argv[])
{
hw_component *temp;
FILE *fp = NULL;
int temp_num;
char *str,*num_str;
fp = fopen(argv[3], "w");
if (fp==NULL)
{
printf("Error: opening %s failed\n", argv[3]);
while (head!=NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
while (head!=NULL)
{
temp = head;
fprintf(fp,"%s $$$ %d\n",temp->name,temp->copies);
head = temp->next;
free(temp);
}
fclose(fp);
}
hw_component *remove_comp_by_name(hw_component *head_comp, char comp_name[NAME_LENGTH + 1])
{
hw_component *temp_ptr = head_comp;
hw_component *prev_ptr;
hw_component *zero_copies_check = head_comp;
if (head_comp == NULL)
{
return head_comp;
}
if (strcmp(temp_ptr->name, comp_name) == 0)
{
head_comp = head_comp->next;
free(temp_ptr);
return head_comp;
}
while (temp_ptr != NULL && strcmp(temp_ptr->name, comp_name) != 0)
{
prev_ptr = temp_ptr;
temp_ptr = temp_ptr->next;
}
if (temp_ptr != NULL)
{
prev_ptr->next = temp_ptr->next;
free(temp_ptr);
}
while (zero_copies_check != NULL)
{
if (zero_copies_check->copies == 0)
{
free(zero_copies_check);
}
zero_copies_check = zero_copies_check->next;
}
return head_comp;
}
hw_component *rename(char old_name[NAME_LENGTH], char new_name[NAME_LENGTH], hw_component *head_comp)
{
hw_component *temp_comp = head_comp;
int num_of_copies = 0;
if (head_comp == NULL)
{
return head_comp;
}
while (temp_comp != NULL && strcmp(temp_comp->name, old_name) != 0)
{
temp_comp = temp_comp->next;
}
num_of_copies = temp_comp->copies;
head_comp=remove_comp_by_name(head_comp, old_name);
head_comp=add_sort(head_comp, num_of_copies, new_name);
return head_comp;
}
hw_component *return_comp(hw_component *head, char name_of_comp[], int copies)
{
hw_component *temp_comp = head;
if (head == NULL)
{
return head;
}
while (temp_comp != NULL && strcmp(temp_comp->name, name_of_comp) != 0)
{
temp_comp = temp_comp->next;
}
if (temp_comp != NULL)
{
temp_comp->copies += copies;
}
else
{
add_sort(head, name_of_comp, copies);
}
return head;
}
int choose_act(char *str)
{
char init[12] = "Initialize ", rename[8]="Rename ",fire[6]="Fire ";
char retu[24] = "Returned_from_customer ", prod[12]="Production " ,fatal[19]="Fatal_malfunction ";
char finalize[] = "Finalize";
if (strcmp(str,init)==0)
return 1;
if (strcmp(str, rename)==0)
return 2;
if (strcmp(str, retu)==0 || strcmp(str, prod)==0)
return 3;
if (strcmp(str, fire)==0 || strcmp(str, fatal)==0)
return 4;
if (strcmp(str, finalize)==0)
return 5;
}
void actions(char *argv[])
{
char dolar[2] = "$";
hw_component *head;
FILE *fp = NULL;
char str[400], *token, *name, *old_name;
int choise = 0, numb;
fp = fopen(argv[2], "r");
if (fp == NULL)
{
printf("Error: opening %s failed\n", argv[2]);
exit(1);
}
while (!feof(fp))
{
fgets(str, 400, fp);
token = strtok(str,dolar);
choise = choose_act(token);
head = initialize(argv);
switch (choise)
{
case 1:
break;
case 2:
old_name = strtok(str, dolar);
name = strtok(str, dolar);
printf("%s %s", old_name, name);
head=rename(old_name,name,head);
break;
case 3:
name = strtok(str, dolar);
numb = atoi(strtok(str, dolar));
head=return_comp(head, name, numb);
break;
case 4:
name = strtok(str, dolar);
numb = atoi(strtok(str, dolar));
head=fatal_maf(head, name, numb);
break;
case 5:
finalize(head,argv);
break;
default:
break;
}
}
}
int check_argc(int argc)
{
int numb = argc;
if (argc != 3)
{
printf("Error: invalid number of arguments (<%d> instead of 3)\n", numb);
return 0;
}
return 1;
}
int main(int argc, char *argv[])
{
int res = 0;
res=check_argc(argc);
if (res == 1)
actions(argv);
return 0;
}
You library already defines a function called rename(), which is prototyped in and included by adding stdio.h, which is creating the conflict with your user-defined function.
As per the lined manual, the signature of the library-defined rename() is int rename (const char *, const char*), whereas as er your function definition, you have a signature as hw_component *rename(char *, char *, hw_component *) - which does not match and your compiler is showing you correct warning (and error) message.
Solution: Use a different name for your function.
You cannot name your custom function rename while including stdio.h, because the name collides with the standard library function rename. Name your own function something different.
The standard function is
int rename(const char *old, const char *new);
So it has type int (const char *, const char *), the same type that the compiler is complaining about a conflict with.

malloc in a loop using valgrind

I am having troubles with memory leaks (error detected by valgrind).
So here is my first function:
message *creationCellule() {
message *cellule;
cellule = (message *)malloc(sizeof(message));
if (cellule != NULL) {
cellule->dateDeb = 0;
cellule->dateFin = 0;
cellule->suivant = NULL;
memset(cellule->text, '\0', TAILLE_MAX);
}
return cellule;
}
It returns cellule which is allocated by malloc.
Now I have this:
void lectureFichier(const char *nomFichier, message **tete) {
FILE *fp = fopen(nomFichier, "r");
message *test;
test = creationCellule();
int k = 0;
if (fp != NULL) {
k = fscanf(fp, "%d %d ", &(test->dateDeb), &(test->dateFin));
while (k != EOF) {
fgets(test->text, 100, fp);
insertion(tete, test);
test = creationCellule();
k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
}
}
}
In which I call creationCellule() in a loop.
My problem is that, if I put free(test) inside a loop I lose all the context of my code and valgrind shows me ERROR SUMMARY:213 errors from 19 contexts.
What should I do ?
This is the complete code and the valgrind output:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "tp1.h"
message *creationCellule() {
message *cellule;
cellule = (message *)malloc(sizeof(message));
if (cellule != NULL) {
cellule->dateDeb = 0;
cellule->dateFin = 0;
cellule->suivant = NULL;
memset(cellule->text, '\0', TAILLE_MAX);
}
return cellule;
}
message **recherche(message *tete, int date) {
message **prec = tete;
message *cour = *tete;
while (cour != NULL && cour->dateDeb < date) {
prec = &(cour->suivant);
cour = cour->suivant;
}
return prec;
}
void insertion(message **tete, message *cellule) {
message **prec;
if (cellule != NULL) {
prec = recherche(tete, cellule->dateDeb);
cellule->suivant = *prec;
*prec = cellule;
}
}
void lectureFichier(const char *nomFichier, message **tete) {
FILE *fp = fopen(nomFichier, "r");
message *test;
test = creationCellule();
int k = 0;
if (fp != NULL) {
k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
while (k != EOF) {
fgets(test->text, 100, fp);
insertion(tete, test);
test = creationCellule();
k = fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin));
}
}
}
void affichageListe(message **tete) {
if (tete != NULL) {
message *tmp = *tete;
while (tmp != NULL) {
//printf("jam ktu\n");
printf("DateDeb = %d \n", tmp->dateDeb);
printf("DateFin = %d \n", tmp->dateFin);
printf("Text = %s \n", tmp->text);
tmp = tmp->suivant;
}
}
}
void suppression(message **tete, int valeur, int dateDeb) {
message **prec;
prec = recherche(tete, dateDeb);
//printf("Prec text: %s , prec dateFin: %d\n", (*prec)->text, (*prec)->dateFin);
if ((*prec) != NULL && (*prec)->dateFin == valeur) {
(*prec) = (*prec)->suivant;
}
}
void supprimeObsoletes(message **tete) {
message *pt = *tete;
time_t temps;
struct tm *date;
int intNum;
temps = time(NULL);
date = localtime(&temps);
char buffer[9];
if ((date->tm_mon) < 10) {
sprintf(buffer, "%d0%d%d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
} else {
sprintf(buffer, "%d%d%d", date->tm_year + 1900, date->tm_mon + 1, date->tm_mday);
}
intNum = atoi(buffer);
while (pt != NULL) {
if ((pt->dateFin) < intNum) {
printf("KTU HYB %s\n", pt->text);
suppression(tete, pt->dateFin, pt->dateDeb);
}
pt = pt->suivant;
}
}
void changeDate(int dateChange, int dateInit, message **tete) {
message *point = *tete;
//printf("Kjo eshte tete %p:\n", (*point));
while (point != NULL) {
if ((point->dateDeb) == dateInit) {
printf("%d\n", point->dateDeb);
printf("%s\n", point->text);
point->dateDeb = dateChange;
}
point = point->suivant;
}
}
int main(int argc, char *argv[]) {
const char *name = argv[1];
message *pointeur = NULL;
message **tete = &pointeur;
int dateInit = 19973012;
int dateChange = 20003008;
FILE *fp = fopen(name, "r");
lectureFichier(name, tete);
//changeDate(dateChange, dateInit, tete);
supprimeObsoletes(tete);
affichageListe(tete);
return 0;
}
The header: tp1.h
#ifndef TP1_TEST_H
#define TP1_TEST_H
#define TAILLE_MAX 100
typedef struct cell {
int dateDeb;
int dateFin;
char text[TAILLE_MAX];
struct cell *suivant;
} message;
message *creationCellule();
message **recherche(message **tete, int date);
void affichageListe(message **tete);
void insertion(message **tete, message *cellule);
void lectureFichier(const char * nomFichier, message **tete);
The .txt file (added in execution)
19973012 20220512 TEXT 1
19980511 19001203 THIS
20011102 20301123 HOUSE
20020809 20301025 HELP
Valgrind output:
Function lectureFichier does not free unused nodes properly.
Here is a corrected version:
void lectureFichier(const char *nomFichier, message **tete) {
FILE *fp = fopen(nomFichier, "r");
if (fp != NULL) {
for (;;) {
message *node = creationCellule();
if (fscanf(fp, "%d%d %99s", &node->dateDeb, &node->dateFin, node->text) == 3) {
insertion(tete, node);
} else {
free(node);
break;
}
}
}
}
the following proposed code:
cleanly compiles
properly handles errors
removed unused code
does NOT cleanup the linked list when an error occurs -- you will need to add that
and now, the proposed code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifndef TP1_TEST_H
#define TP1_TEST_H
#define TAILLE_MAX 100
struct cell
{
int dateDeb;
int dateFin;
char text[TAILLE_MAX];
struct cell * suivant;
};
typedef struct cell message;
message * creationCellule( void );
message ** recherche( message ** tete, int date );
void affichageListe( message ** tete );
FILE * ecrireFichier( message ** tete );
void dateNonExpires( message ** tete );
#endif // TPI_TEST_H
message * creationCellule()
{
message * cellule = malloc(sizeof(message));
if( !cellule )
{
perror( "malloc failed" );
exit( EXIT_FAILURE );
}
cellule->dateDeb = 0;
cellule->dateFin = 0;
cellule->suivant = NULL;
return cellule;
}
message ** recherche( message ** tete, int date )
{
message ** prec = tete;
message * cour = *tete;
while( cour != NULL && cour->dateDeb < date )
{
prec = &(cour->suivant);
cour = cour->suivant;
}
return prec;
}
void insertion(message ** tete, message * cellule)
{
(void)tete;
(void)cellule;
// insert code that does something reasonable
}
void lectureFichier(const char * nomFichier, message ** tete)
{
FILE * fp = fopen(nomFichier, "r");
if( !fp )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
test = creationCellule();
while( fscanf(fp,"%d %d ", &(test->dateDeb), &(test->dateFin)) == 2 )
{
fgets(test->text, 100, fp);
insertion(tete, test);
test = creationCellule();
}
}
void affichageListe( message ** tete )
{
if( tete )
{
message * tmp = *tete;
while( tmp )
{
//printf("jam ktu\n");
printf( "DateDeb = %d \n", tmp->dateDeb );
printf( "DateFin = %d \n", tmp->dateFin );
printf( "Text = %s \n", tmp->text );
tmp = tmp->suivant;
}
}
}
void suppression( message**tete, int valeur, int dateDeb )
{
message **prec;
prec = recherche( tete, dateDeb );
//printf("Prec text: %s , prec dateFin: %d\n",(*prec)->text,(*prec)->dateFin);
if( (*prec) != NULL && (*prec)->dateFin == valeur )
{
(*prec)=(*prec)->suivant;
}
}
void supprimeObsoletes(message **tete)
{
message *pt = *tete;
time_t temps;
struct tm *date;
temps=time(NULL);
date=localtime(&temps);
char buffer[9];
if((date->tm_mon)<10)
{
sprintf(buffer,"%d0%d%d",date->tm_year + 1900,date->tm_mon +1,date->tm_mday);
}
else
{
sprintf(buffer,"%d%d%d",date->tm_year + 1900,date->tm_mon +1,date->tm_mday);
}
int intNum=atoi(buffer);
while( pt )
{
if( (pt->dateFin) < intNum )
{
printf( "KTU HYB %s\n", pt->text );
suppression( tete, pt->dateFin, pt->dateDeb );
}
pt=pt->suivant;
}
}
int main(int argc, char * argv[])
{
if( argc != 2 )
{
fprintf( stderr, "USAGE: %s filename\n", argv[0] );
exit( EXIT_FAILURE );
}
const char * name = argv[1];
message * pointeur = NULL;
lectureFichier( name, &pointeur );
supprimeObsoletes( &pointeur );
affichageListe( &pointeur );
while( pointeur )
{
message *current = pointeur;
pointeur = pointeur->suivant;
free( current );
}
return 0;
}

How to sort lines of a file alphabetically in C? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
Ok so what I have right now, checks the counts of the words. But I am having trouble trying to sort the words alphabetically.
I'd rather do that then just count the number of which they are.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node *node_ptr;
typedef struct node {
int count;
char *word;
node_ptr next;
} node_t;
char *words[] = { "hello", "goodbye", "sometimes", "others", "hello", "others", NULL };
node_ptr new_node() {
node_ptr aNode;
aNode = (node_ptr)(malloc(sizeof(node_t)));
if (aNode) {
aNode->next = (node_ptr)NULL;
aNode->word = (char *)NULL;
aNode->count = 0;
}
return aNode;
}
node_ptr add_word(char *word, node_ptr theList) {
node_ptr currPtr, lastPtr, newPtr;
int result;
int found = 0;
currPtr = theList;
lastPtr = NULL;
printf("Checking word:%s\n", word);
if (!currPtr) {
newPtr = new_node();
if (!newPtr) {
fprintf(stderr, "Fatal Error. Memory alloc error\n");
exit(1);
}
newPtr->word = word;
newPtr->next = currPtr;
newPtr->count = 1;
found = 1;
theList = newPtr;
}
while (currPtr && !found) {
result = strcmp(currPtr->word, word);
if (result == 0) {
currPtr->count += 1;
found = 1;
} else
if (result>0) {
newPtr = new_node();
if (!newPtr) {
fprintf(stderr, "Fatal Error. Memory alloc error\n");
exit(1);
}
newPtr->word = word;
newPtr->next = currPtr;
newPtr->count = 1;
if (lastPtr) {
lastPtr->next = newPtr;
} else {
theList = newPtr;
}
found = 1;
} else {
lastPtr = currPtr;
currPtr = currPtr->next;
}
}
if ((!found) && lastPtr) {
newPtr = new_node();
if (!newPtr) {
fprintf(stderr, "Fatal Error. Memory alloc error\n");
exit(1);
}
newPtr->word = word;
newPtr->next = (node_ptr)NULL;
newPtr->count = 1;
lastPtr->next = newPtr;
found = 1;
}
return theList;
}
void printList(node_ptr theList) {
node_ptr currPtr = theList;
while (currPtr) {
printf("word: %s\n", currPtr->word);
printf("count: %d\n", currPtr->count);
printf("---\n");
currPtr = currPtr->next;
}
}
int main() {
char **w = words;
node_ptr theList = (node_ptr)NULL;
printf("Start\n");
while (*w) {
theList = add_word(*w, theList);
w++;
}
printList(theList);
printf("OK!\n");
return 0;
}
I'd also like to instead of reading from an array of words, I'd rather read from a file.
FILE *fp;
fp = fopen("some.txt", "w");
How do I read from a file using my structure I've created and then sort them?
You can read the words from a file with fscanf():
int main(int argc, char *argv[]) {
node_t *theList = NULL;
for (int i = 1; i < argc; i++) {
FILE *fp = fopen(argv[i], "r");
if (fp != NULL) {
char word[100];
while (fscanf(fp, "%99s", word) == 1) {
theList = add_word(word, theList);
}
fclose(fp);
}
}
printList(theList);
printf("OK!\n");
return 0;
}

glibc detected outfile: free(): invalid pointer:

My code is giving glibc error.Can someone please point out my mistake.
This code is used to tokenize words. How do i solve these problems using GDB or any other tool that can be helpful. The code is given below
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>
struct token
{
char *token;
int length;
};
void freeing(gpointer item)
{
free(((struct token*)item)->token);
}
int main(int argc, char* argv[])
{
int start1 = 0, start2 = 0, i =0;
struct token *tk = NULL;
char line[256], *temp = NULL;
FILE *fp1 = NULL;
FILE *fp2 = NULL;
GSList *list = NULL, *iterator = NULL;
fp1 = fopen(argv[1], "r");
fp2 = fopen(argv[2], "w+");
if (NULL == fp1)
{
fprintf(stderr,"cant open %s",argv[1]);
return 1;
}
if (NULL == fp2)
{
fprintf(stderr,"cant open %s",argv[2]);
return 1;
}
while (1)
{
if (NULL == fgets(line, 255, fp1))
break;
tk = (struct token *)malloc(sizeof(struct token));
start1 = -1; start2 = -1;
for(temp = line,i = 0; temp[i] != '\n'; i++)
{
if ((temp[i] == ',') || (temp[i] == ' ') || (temp[i] == ';') || (temp[i] == '.'))
start2 = i;
if (start1 == start2)
continue;
tk->token = strndup(line + (start1+1), start2 - (start1+1));
tk->length = strlen(tk->token);
list = g_slist_append(list, tk);
start1 = start2;
}
tk->token = strndup(line + (start1+1), strlen(line));
tk->length = strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );
}
for (iterator = list; iterator; iterator = iterator->next)
{
printf("%s -> ",((struct token *)(iterator->data))->token);
printf("%d\n",((struct token*)iterator->data)->length);
}
g_slist_foreach(list, (GFunc)freeing, NULL);
fclose(fp1);
fclose(fp2);
return 0;
}
the following code has the major problems fixed, but not the logic errors in the loop :
for(int i=0, temp = line; temp[i] != '\n'; i++)
{
...
}
tk->token = strndup(line + (start1+1), strlen(line));
tk->length = strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );
the suggested fixes for the majority of the problems in the posted code are corrected in the following:
added final call to g_slist_free(list); so all the instances of the struct token are returned to the heap.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>
#define MAX_LINE_LEN (256)
struct token
{
char *token;
int length;
};
void freeing(gpointer item)
{
free(((struct token*)item)->token);
}
int main(int argc, char* argv[])
{
if( 3 != argc )
{ // then incorrect number of command line arguments
fprintf( stderr, "USAGE: %s <inputfile> <outputfile>\n", argv[0]);
exit( EXIT_FAILURE );
}
// implied else, correct number of command line arguments
FILE *fp1 = NULL;
FILE *fp2 = NULL;
if( NULL == (fp1 = fopen(argv[1], "r") ) )
{ // then fopen failed
fprintf( stderr, "fopen for %s for read failed\n", argv[1]);
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (fp2 = fopen(argv[2], "w+") ) )
{ // then fopen failed
fprintf( stderr, "fopen for %s for write failed\n", argv[2]);
fclose( fp1 ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fopen successful
GSList *list = NULL;
GSList *iterator = NULL;
char line[ MAX_LINE_LEN ];
struct token *tk = NULL;
char *temp = NULL;
while ( fgets(line, sizeof(line), fp1) )
{
if( NULL == (tk = malloc(sizeof(struct token)) ) )
{ // then malloc failed
perror( "malloc for struct token failed");
fclose( fp1 );
fclose( fp2 );
exit( EXIT_FAILURE );
}
// implied else, malloc successful
size_t start1 = 0;
size_t start2 = 0;
temp = line;
for(size_t i=0; temp[i] != '\n'; i++)
{
if ((temp[i] == ',') || (temp[i] == ' ') || (temp[i] == ';') || (temp[i] == '.'))
start2 = i;
if (start1 == start2)
continue;
tk->token = strndup(line + (start1+1), start2 - (start1+1));
tk->length = (int)strlen(tk->token);
list = g_slist_append(list, tk);
start1 = start2;
} // end for
tk->token = strndup(line + (start1+1), strlen(line));
tk->length = (int)strlen(tk->token);
printf("\ntk->length : %d\n",tk->length);
list = g_slist_append(list, tk );
} // end while
for (iterator = list; iterator; iterator = iterator->next)
{
printf("%s -> ",((struct token *)(iterator->data))->token);
printf("%d\n",((struct token*)iterator->data)->length);
}
g_slist_foreach(list, (GFunc)freeing, NULL);
g_slist_free(list);
fclose(fp1);
fclose(fp2);
return 0;
}

C — Directory exploration

I want to dynamically populate an array of strings with file name and directory name that are inside the specified directory path.
According to you, is this the fastest implementation for this purpose?
If not, can you suggest an alternative implementation?
int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
DIR *dirstream = NULL;
struct dirent *direntp = NULL;
size_t listSize = 5;
errno = 0;
if (!(dirstream = opendir(dirpath)))
return errno;
if (!((*list) = malloc(sizeof(char *) * listSize))) {
fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
*numItems = 0;
while(1) {
errno = 0;
if (!(direntp = readdir(dirstream)))
break;
if (*numItems + 1 == listSize) {
listSize *= 2;
if (!((*list) = realloc((*list), sizeof(char *) * listSize))) {
fprintf(stderr, "Error in list reallocation for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
}
*numItems += 1;
(*list)[*numItems - 1] = stringDuplication(direntp->d_name);
}
if (errno != 0) {
fprintf(stderr, "Error in readdir for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
if (closedir(dirstream) == -1) {
fprintf(stderr, "Error in closedir for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
free(direntp);
return 0;
}
This is the implementation based on scandir!
int exploreDirectory(const char *dirpath, char ***list, int *numItems) {
struct dirent **direntList;
int i;
errno = 0;
if ((*numItems = scandir(dirpath, &direntList, NULL, alphasort)) == -1)
return errno;
if (!((*list) = malloc(sizeof(char *) * (*numItems)))) {
fprintf(stderr, "Error in list allocation for file list: dirpath=%s.\n", dirpath);
exit(EXIT_FAILURE);
}
for (i = 0; i < *numItems; i++) {
(*list)[i] = stringDuplication(direntList[i]->d_name);
}
for (i = 0; i < *numItems; i++) {
free(direntList[i]);
}
free(direntList);
return 0;
}

Resources