Pointer NULL issues - c

void addWord(char *word, bucket **bkt, int size)
{
bucket *node, *auxNode;
if(findWord(word, bkt[hash(word, size)]) == 1)
{
return;
}
node = (bucket*) malloc (sizeof(bucket));
node->data = (char*) malloc (strlen(word) * sizeof(char));
memset(node->data, 0, strlen(word));
sprintf(node->data, "%s", word);
if(*bkt == NULL)
{
node->next = NULL;
*bkt = node;
}
else
{
auxNode = (bucket*) malloc (sizeof(bucket));
auxNode = *bkt;
while(auxNode->next != NULL)
{
auxNode = auxNode->next;
}
node->next = NULL;
auxNode->next = node;
}
}
int main(int argc, char **argv)
{
............
bkt = (bucket**) malloc (*sizeHash * sizeof(bucket*));
for(i = 0 ; i < (*sizeHash) ; i++)
{
printf("%d\n", i);
bkt[i] = NULL;
}
.........
if(bkt[hash(pch, *sizeHash)] == NULL)
{
printf("NULL: %s -> %d\n",pch, hash(pch, *sizeHash));
bkt[hash(pch, *sizeHash)] = NULL;
}
addWord(pch, &bkt[hash(pch, *sizeHash)], *sizeHash);
Every time enters in that if, that means that the node send is NULL; But after two inserts, the third although enters in that if, in addWord it arrives not NULL(i put a printf before findWord). I don't understand why this happens. This is a hash table, hash() is djb2 of Dan Bernstein. Could somebody tell my why the NULL pointer isn't send in addWord()?

Surely this:
if(findWord(word, bkt[hash(word, size)]) == 1)
is supposed to be this:
if(findWord(word, *bkt) == 1)
?
Remember that the bkt inside addWord is the &bkt[hash(pch, *sizeHash)] from main: it already points to the hash-entry for word.

Related

What is wrong with my replace string with another string or character using linked list

I have a linked list with many chars which I input from my input (what is the weather today?), to be replaced with another string (for example what replaced with how, so I get how is the weather today?).
But if the given words are right next to each other for example whatwhat, it will change to howwhat, disregarding the second part.
I think the problem is in the compare function, but I have no clue how to fix it, but the logic of replace should go like this:
If the words from my list and the needed word are the same, then proceed to iterate to the position where the next node of the word that should be changed (unwanted word) should be (pretty much the end of the word), then I create a new linked list with character with the wanted word, and connect temp to the start of the list and the next of the list to the position where the next character of the word that needs to be changed (unwanted word), which I found in the first loop.
Also don't roast my input() function, I know it is unsafe I just want to see what unsafe means with my own eyes, while I still have nothing to lose.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int value_c;
struct node *next_c;
struct node *prev_c;
};
typedef struct node string;
int compare(string *head, char *word) {
int counter = 0;
string *temp = head;
for (int i = 0; i < strlen(word); i++) {
if (temp->value_c == word[i]) {
temp = temp->next_c;
counter++;
}
}
if (counter == strlen(word))
return 1;
else
return 0;
}
void print_c(string *head) {
while (head != NULL) {
printf("%c", head->value_c);
head = head->next_c;
}
}
void append_c(string **head, char thing) {
string *newNode = (string *)malloc(sizeof(string));
newNode->value_c = thing;
newNode->next_c = NULL;
if (*head == NULL) {
*head = newNode;
newNode->prev_c = NULL;
return;
}
string *temp = *head;
while (temp->next_c != NULL)
temp = temp->next_c;
temp->next_c = newNode;
newNode->prev_c = temp;
}
string *replace_all1(string *head, char *what, char *with_what) {
string *temp = head;
while (temp != NULL) {
printf("%c ", temp->value_c);
if (compare(temp, what) == 1) {
printf("%i ", 1);
printf("%c ", temp->value_c);
string *new = temp;
for (int i = 0; i < strlen(what) - 1; i++) {
new = new->next_c;
}
string *word = NULL;
for (int i = 0; i < strlen(with_what); i++) {
append_c(&word, with_what[i]);
}
string *word_temp = word;
while (word_temp->next_c != NULL) {
word_temp = word_temp->next_c;
}
word_temp->next_c = new->next_c;
if (temp->prev_c != NULL) {
temp->prev_c->next_c = word;
} else {
head = word;
print_c(head);
temp = word;
print_c(temp);
word->prev_c = NULL;
}
}
temp = temp->next_c;
}
printf("\n");
return head;
}
string *String(char *str) {
string *st = NULL;
int i = 0;
while (str[i] != '\0') {
append_c(&st, str[i]);
i++;
}
return st;
}
string *input() {
char *a = (char *)malloc(sizeof(char));
scanf("%[^\n]", a); //maximum of 1408
string *stri = String(a);
return stri;
free(a);
}
int main() {
string *list = NULL;
string *big_boy_string = input();
//printf("%c", big_boy_string->value_c);
//print_c(big_boy_string);
//printf("\n");
//printf("%i", compare(big_boy_string, "what"));
//printf("%i ", len(big_boy_string));
//printf("\n");
//print_c(slice(big_boy_string, 1, 10));
//print_c(replace(big_boy_string, 'h', 'a'));
//printf("\n");
//print_c(reverse(big_boy_string));
print_c(replace_all1(big_boy_string, "a", "b"));
//getline();
}
char *a = (char*) malloc(sizeof(char));
scanf("%[^\n]",a); //maximum of 1408
The first statement allocates memory for just 1 byte. So the maximum is not 1408, but 1. It can store a single char, or the null-terminator if it's a string, but no more.
Next, scanf() will write to out of bounds memory, and invoke undefined behaviour. The subsequent functions all depend on this undefined behaviour, so I'm not going to look at them.
But then, you've a memory leak in the same function.
return stri;
free(a);
You return before freeing the allocated memory. The call to free() is never executed.
The return value of malloc() is also ignored. Code risks undefined behaviour if the subsequent dereferences are on a NULL pointer.
Aside: The cast is meaningless and may hide a bug. malloc() and family returns a void * that is implicitly converted to the right type.
Re: Also don't roast my input() function, I know its unsafe I just
want to see what unsafe means with my own eyes.
If you are already aware of this, then you shouldn't be asking why your code doesn't work. You are relying on undefined behaviour (playing with fire).
There is no need to look further than the input function: it has undefined behavior or the worst kind because you attempt to read the input string into a very small array, allocated for a single byte. You must fix this first. Since you know the maximum length of your input string, you can use this:
string *input(void) {
char a[1409];
if (scanf("%1408[^\n]", a) != 1) { //maximum of 1408
// invalid or missing input
return NULL;
}
scanf(%*[^\n]"); // consume any remaining characters on the input line
scanf(%*1[\n]"); // consume the newline if present
return String(a);
}
Here is an alternative using getchar() instead of scanf() which is quite tricky and error prone:
string *input(void) {
char a[1409];
int c;
size_t i = 0;
while ((c = getchar()) != EOF && c != '\n') {
if (i + 1 < sizeof(a))
a[i++] = (char)c;
}
if (c == EOF && i == 0) {
/* end of file without any input */
return NULL;
}
a[i] = '\0';
return String(a);
}
The compare function is incorrect: it should return false as soon as the comparison fails and it must test for the end of string (temp == NULL):
int compare(const string *head, const char *word) {
string *temp = head;
for (size_t i = 0; word[i] != '\0'; i++) {
if (temp == NULL || temp->value_c != word[i])
return 0;
temp = temp->next_c;
}
return 1;
}
The replace_all1() function has problems too:
for (int i = 0; i < strlen(what) - 1; i++) will cause undefined behavior if what is an empty string because strlen(what) - 1 is unsigned with the value SIZE_MAX in this case, causing the loop to proceed for a very long time, well beyond the end of the list pointed to by new.
while (word_temp->next_c != NULL) will cause a undefined behavior if the replaced word is empty as word_temp will be NULL.
once you replace the sublist, you do not update temp correctly to point to the node after the replaced one, which you could achieve by setting temp to word_temp.
the function does not free the replaced sublist.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
int value_c;
struct node *next_c;
struct node *prev_c;
};
typedef struct node string;
void string_append_char(string **head, int c) {
string *node = malloc(sizeof(*node));
if (node == NULL) {
fprintf(stderr, "out of memory\n");
exit(1);
}
node->value_c = c;
node->next_c = NULL;
if (*head == NULL) {
node->prev_c = NULL;
*head = node;
} else {
string *temp = *head;
while (temp->next_c != NULL)
temp = temp->next_c;
node->prev_c = temp;
temp->next_c = node;
}
}
string *string_new(const char *str) {
string *st = NULL;
for (int i = 0; str[i] != '\0'; i++) {
string_append_char(&st, str[i]);
}
return st;
}
string *string_input(const char *prompt) {
string *st = NULL;
int c;
if (prompt) {
printf("%s", prompt);
}
while ((c = getchar()) != EOF && c != '\n') {
string_append_char(&st, c);
}
return st;
}
void string_print(const char *before, const string *head, const char *after) {
printf("%s", before);
while (head != NULL) {
putchar(head->value_c);
head = head->next_c;
}
printf("%s", after);
}
void string_free(string *head) {
while (head != NULL) {
string *next = head->next_c;
free(head);
head = next;
}
}
int string_compare(const string *head, const char *word) {
const string *temp = head;
for (size_t i = 0; word[i] != '\0'; i++) {
if (temp == NULL || temp->value_c != word[i])
return 0;
temp = temp->next_c;
}
return 1;
}
int string_replace(string **head, const char *what, const char *with_what) {
int count = 0;
if (*what == '\0')
return 0;
string *temp = *head;
while (temp != NULL) {
if (string_compare(temp, what)) {
count++;
// locate the last node of the substring
string *temp_end = temp;
for (size_t i = 0; what[i + 1] != '\0'; i++) {
temp_end = temp_end->next_c;
}
string *next = temp_end->next_c;
if (*with_what == '\0') {
// just delete the substring
if (temp->prev_c != NULL) {
temp->prev_c->next_c = next;
} else {
*head = next;
}
if (next) {
next->prev_c = temp->prev_c;
}
} else {
// create a string from the replacement
string *word = string_new(with_what);
// locate the last node of the new substring
string *word_end = word;
while (word_end->next_c != NULL) {
word_end = word_end->next_c;
}
word->prev_c = temp->prev_c;
if (temp->prev_c != NULL) {
temp->prev_c->next_c = word;
} else {
*head = word;
}
word_end->next_c = next;
if (next) {
next->prev_c = word_end;
}
}
temp_end->next_c = NULL;
string_free(temp);
temp = next;
} else {
temp = temp->next_c;
}
}
return count;
}
int main() {
string *list = string_input("enter string: ");
string_print("input: ", list, "\n");
printf("replacing 'what' to 'how': %d matches\n", string_replace(&list, "what", "how"));
string_print("rep1: ", list, "\n");
printf("replacing 'a' to 'b': %d matches\n", string_replace(&list, "a", "b"));
string_print("rep2: ", list, "\n");
printf("deleting 'h': %d matches\n", string_replace(&list, "h", ""));
string_print("rep3: ", list, "\n");
string_free(list);
return 0;
}
Sample session:
enter string: what is the weather today?
input: what is the weather today?
replacing 'what' to 'how': 1 matches
rep1: how is the weather today?
replacing 'a' to 'b': 2 matches
rep2: how is the webther todby?
deleting 'h': 3 matches
rep3: ow is te webter todby?

Proper way of deallocation of double pointer to struct

I am trying to add memory deallocations to old C code.
I have a hash table of custom objects (HASHREC). After analysis of current code and reading other SO questions, I know that I need to provide three levels of deallocations. Fist - word member, next HASHREC*, and then HASHREC**.
My version of free_table() function frees mentioned objects. Unfortunately, Valgrind still complains that some bytes are lost.
I am not able to provide full code, it will be too long, but I am presenting how HASHREC **vocab_hash is filled inside inithashtable() and hashinsert().
Could you give me a suggestion how should I fix free_table()?
typedef struct hashrec {
char *word;
long long count;
struct hashrec *next;
} HASHREC;
HASHREC ** inithashtable() {
int i;
HASHREC **ht;
ht = (HASHREC **) malloc( sizeof(HASHREC *) * TSIZE );
for (i = 0; i < TSIZE; i++) ht[i] = (HASHREC *) NULL;
return ht;
}
void hashinsert(HASHREC **ht, char *w) {
HASHREC *htmp, *hprv;
unsigned int hval = HASHFN(w, TSIZE, SEED);
for (hprv = NULL, htmp = ht[hval]; htmp != NULL && scmp(htmp->word, w) != 0; hprv = htmp, htmp = htmp->next);
if (htmp == NULL) {
htmp = (HASHREC *) malloc( sizeof(HASHREC) ); //<-------- problematic allocation (Valgrind note)
htmp->word = (char *) malloc( strlen(w) + 1 );
strcpy(htmp->word, w);
htmp->next = NULL;
if ( hprv==NULL ) ht[hval] = htmp;
else hprv->next = htmp;
}
else {/* new records are not moved to front */
htmp->count++;
if (hprv != NULL) { /* move to front on access */
hprv->next = htmp->next;
htmp->next = ht[hval];
ht[hval] = htmp;
}
}
return;
}
void free_table(HASHREC **ht) {
int i;
HASHREC* current;
HASHREC* tmp;
for (i = 0; i < TSIZE; i++){
current = ht[i];
while(current != NULL) {
tmp = current;
current = current->next;
free(tmp->word);
}
free(ht[i]);
}
free(ht);
}
int main(int argc, char **argv) {
HASHREC **vocab_hash = inithashtable();
// ...
hashinsert(vocab_hash, w);
//....
free_table(vocab_hash);
return 0;
}
I assume the problem is here:
current = ht[i];
while(current != NULL) {
tmp = current;
current = current->next;
free(tmp->word);
}
free(ht[i]);
You release the word but you don’t release tmp. After you release the first item in the linked list but not the others which causes a leak.
Free tmp in there and don’t free ht[i] after since it’s already freed here.
current = ht[i];
while(current != NULL) {
tmp = current;
current = current->next;
free(tmp->word);
free(tmp);
}

read txt, count each alphabet using linked list

#pragma warning (disable:4996)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#include <ctype.h>
#define NUM_OF_ALPHABET 26
#define MAX_HEAP_SIZE 100
typedef struct _CharFrequency
{
char character;
int frequency;
struct _CharFrequency * next;
}CharFrequency;
typedef CharFrequency* pCharFrequency;
pCharFrequency pHead = NULL;
void initList();
void addNode(char ch);
void printAllNode(pCharFrequency pHead);
int main()
{
int i = 0, cnt = 0;
FILE *pFile;
char readLine[1024], *ptr;
char *token = " \t\n.";
pFile = fopen("C:\\Users\\Home\\Desktop\\dataset.txt", "r");
if (pFile == NULL)
{
printf("File open failed.\n");
return 0;
}
while (fgets(readLine, 1024, pFile) != NULL)
{
ptr = strtok(readLine, token);
while (ptr != NULL)
{
for (i = 0; i < strlen(ptr); i++)
{
addNode(ptr[i]);
}
ptr = strtok(NULL, token);
}
}
printAllNode(pHead);
return 0;
}
void initList()
{
pHead = (CharFrequency*)malloc(sizeof(CharFrequency));
if (!pHead)
{
printf("Fault\n");
return;
}
pHead->character = '\0';
pHead->frequency = 0;
pHead->next = NULL;
}
void addNode(char ch)
{
int i = 0;
pCharFrequency pNode = NULL;
pCharFrequency pCurrent= NULL;
if (isalpha(ch) == 0)
return;
if (ch >= 'A' && ch <= 'Z')
ch = ch + 32;
printf("%c ", ch);
for (pCurrent = pHead; pCurrent != NULL ; pCurrent = pCurrent->next)
{
if (pCurrent->character == ch)
{
pCurrent->frequency++;
}
else
{
pNode = (CharFrequency*)malloc(sizeof(CharFrequency));
pNode->frequency = 0;
pNode->next = NULL;
pNode->character = ch;
pNode->frequency++;
pCurrent->next = pNode;
}
}
pNode = (CharFrequency*)malloc(sizeof(CharFrequency));
pNode->frequency = 0;
pNode->next = NULL;
pNode->character = ch;
pNode->frequency++;
pCurrent->next = pNode;
}
void printAllNode(pCharFrequency pHead)
{
pCharFrequency pCurrent;
pCurrent = pHead;
pCurrent = pHead;
while (pCurrent->next != NULL) {
printf("%c %d", pCurrent->character, pCurrent->frequency);
pCurrent = pCurrent->next;
}
}
I want to build a program that reads txt file, count only alphabet, and count them using linked list. I make struct called CharFrequency to count alphabet.
addNode function gets the character, checks if it's in the list or not, and count them.
It makes error when doing for() in the addNode function.
You need to rethink about the logic inside your addNode method. It is adding a new node every time a character is not found in the list, and even if a match is found,the loop will continue until the last node adding a new node every time.
You could do something like this to get you started and experiment on it to make it more efficient.
pCharFrequency pNode = NULL;
pCharFrequency pCurrent= NULL;
pCharFrequency pTail= NULL;//this will keep track of the last node in the list
//so that we use it to insert a new node
....//your other code
pCurrent = pHead;//start from the head
while (pCurrent!=NULL)
{
if (pCurrent->character == ch)
{
pCurrent->frequency++;
return;//if a match was found, count and return
}
if(pCurrent->next == NULL)
pTail=pCurrent;//save the pointer to the last node in the list if we reach to it
pCurrent=pCurrent->next;//get the next node
}
//if we reach here, then we need to create a new node
pNode = (CharFrequency*)malloc(sizeof(CharFrequency));
if(pNode==NULL)
{
//show error message
return;
}
pNode->frequency = 1;
pNode->next = NULL;
pNode->character = ch;
if(pHead==NULL)
pHead=pNode;//for the very first node,we just assign to head
else
pTail->next = pNode;//otherwise set the last node's next to the node we just created

Trouble with strcmp function in C

I am writing a function called check that compares the alphabetical string of a dictionary that is loaded in through the command line with a text that is also loaded in through the command line. The function is part of a larger function called speller that acts as a spell checker.
I ran several printf debugging tests to check if the words being compared in the strcmp function. The problem comes here. The function finds that all words in the text are incorrectly spelled even when the printf test shows that the strings from the dictionary and the text are the same.
Don't know where to go from this point so any help would be greatly appreciated. Thanks so much
Below is the code for the particular function. Thanks again.
typedef struct node {
char word[LENGTH + 1];
struct node *next;
} node;
node *hashtable[27];
/* Returns true if word is in dictionary else false. */
int hash_fun (const char key);
bool check (const char *word)
{
//case-desensitizing
char caseless[strlen (word)];
int i, length;
for (int head = 0; head < 26; head++) {
hashtable[head] = NULL;
}
for (i = 0, length = strlen (word); i < length; i++) {
//("%c\n",word[i]);
if (isupper (word[i])) {
caseless[i] = tolower (word[i]);
} else {
caseless[i] = word[i];
}
}
caseless[i] = '\0';
//printf("-%s %s- \n*",word, caseless);
int word_index = hash_fun (caseless);
//printf("%i", word_index);
node *new_node = malloc (sizeof (node));
if (new_node == NULL) {
return 2;
}
if (word_index >= 0) {
if (hashtable[word_index] == NULL) {
hashtable[word_index] = new_node;
new_node->next = NULL;
}
node *cursor = malloc (sizeof (node));
cursor = hashtable[word_index];
while (cursor != NULL) {
//printf("Dictionary:%s and Text:%s \n", cursor->word, caseless);
int found;
found = strcmp (caseless, cursor->word);
if (found == 0) {
return true;
}
cursor = cursor->next;
}
}
return false;
}

C / linked list / How can fix the segmentation fault?

When I complie it, it has segmentation fault at
strcat(arr, cur->texts); which is in dumpTB function.
In main function, when the dumpTB function is called, it should print out like
hello\ngood bye\nworld\n same as what I have typed in newTB function..
Can anyone figure out what the problem is?
I have added the function called deleteTB(TB tb, int from, int to).
I'm not just asking like 'Can you do this for me?', i want to know and learn how to fix.
I tried from last night.. but still stuck..
Weirdly, I got a seg fault at the same line 'strcat(arr, cur->texts)'. I tried to modify different way and code differently.. but don't know.
Since my input is like, "hello\ngood bye\nworld\n"..
when the deleteTB(list , 0 , 1) is called like this, // (head node is 0)
printbuffer(list) should print like,
POS 0 : world
then, dumpTB(list) should print like,
world.
since i didn't know the rule in here, i have posted pretty much same thing last night which made people annoyed. Sorry for that. And i'm not just asking you guys to do it. I really want to learn.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "textbuffer.h"
#define MAX_TEXT 256
struct textbuffer {
char *texts;
int count;
TB next;
};
TB newTB (char text[]){
TB newText = malloc(sizeof(struct textbuffer));
char *cpy = (char *)malloc(MAX_TEXT * sizeof(char));
TB head = newText; // Store the first node to return
strcpy(cpy,text);
newText->count = 0;
newText->next = NULL;
int i = 0;
int j = 0;
while( cpy[i] != '\0') {
if( j == 0) {
head->texts = (char *)malloc(MAX_TEXT * sizeof(char));
}
if(cpy[i] == '\n') {
head->texts[j] = '\0';
newText->count++;
head->next = malloc(sizeof(struct textbuffer));
head = head->next;
j = 0;
i++;
} else {
head->texts[j++] = cpy[i++];
}
}
head->next = NULL;
return newText;
}
void releaseTB (TB tb) {
TB head = tb;
TB tmp;
while(head != NULL) {
tmp = head;
head = head->next;
free(tmp->texts);
free(tmp);
}
}
char *dumpTB (TB tb) {
if(tb == NULL) {
return NULL;
}
TB cur = tb;
char *arr = (char *)malloc(MAX_TEXT * sizeof(char));
while(cur != NULL) {
if(arr == NULL) {
strcpy(arr,"");
}
strcat(arr, cur->texts);
if(cur->next != NULL) {
strcat(arr, "\n");
}
cur = cur->next;
}
return (arr);
}
int linesTB(TB tb) {
return (tb->count);
}
void printBuffer(TB tb){
TB curr = tb;
int i=0;
while(curr->next != NULL){
printf("POS %d : %s\n", i++, curr->texts);
curr = curr->next;
}
}
void swapTB(TB tb, int pos1, int pos2) {
if((pos1 < 0) || (pos2 < 0) || (pos1 > linesTB(tb)-1) || (pos2 > linesTB(tb)-1)) {
printf("**GIVEN LINES ARE OUT OF RANGE**\n");
abort();
}
TB cur = tb;
TB head = tb;
int i = 0;
char *tmp = (char *)malloc(MAX_TEXT * sizeof(char));
tb->texts = cur->texts;
while( i < pos1) {
cur = cur->next;
i++;
}
strcpy(tmp, cur->texts);
cur->texts = NULL;
i=0;
while( i < pos2) {
head = head->next;
i++;
}
cur->texts = head->texts;
head->texts = tmp;
}
void deleteTB(TB tb, int from, int to) {
if((from < 0) || (to < 0) || (from > linesTB(tb)-1) || (to > linesTB(tb)-1)) {
printf("**GIVEN LINES ARE OUT OF RANGE**\n");
abort();
}
TB cur = tb;
int i = 0;
for(i = 0; i < from; i++) {
cur = cur->next;
}
while( i <= to ) {
cur->texts = '\0';
free(cur->texts);
//free(cur);
cur = cur->next;
i++;
}
}
int main(int argc, char * argv[]) {
TB list = NULL;
list = newTB("hello\ngood bye\nworld\n");
printf("**THERE ARE %d LINES IN TEXTBUFFER**\n", linesTB(list));
printBuffer(list);
printf("**Dumping test**\n");
printf("%s\n",dumpTB(list));
printf("**Swapping test**\n");
swapTB(list, 0, 1);
printBuffer(list);
printf("**Deleteing test**\n");
deleteTB(list, 1, 1);
printBuffer(list);
printf("%s\n",dumpTB(list));
releaseTB(list);
return 0;
}
you are using strcat function. and the first argument is arr which is not null terminated.
So use, below code before using strcat
arr[0]='\0';
Also, check for cur->next in the loop like this.
while(cur->next != NULL)
Also, your releaseTB will give you segfault for the above said reason.
change the loop condition to
while(head->next != NULL)
Edit
char *dumpTB (TB tb) {
if(tb == NULL) {
return NULL;
}
TB cur = tb;
char *arr = (char *)malloc(MAX_TEXT * sizeof(char)); //VS throws error if we wont cast
arr[0]='\0'; // Null Terminated
while(cur->next != NULL) { // changed to cur->next
if(arr == NULL) {
strcpy(arr,"");
}
strcat(arr, cur->texts);
if(cur->next != NULL) {
strcat(arr, "\n");
}
cur = cur->next;
}
return (arr);
}
void releaseTB (TB tb) {
TB head = tb;
TB tmp;
while(head->next != NULL) { // Changed to head->next
tmp = head;
head = head->next;
free(tmp->texts);
free(tmp);
}
}

Resources