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);
}
}
Related
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?
#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
My assignment is to make a program in C to remove null production from a CFG. Ans I can only use Linked List. Note that the Linked List value part points to an Array. I've given the output in the Code. My Null production removal is not working properly. Please run the code and tell me what you think and how can i improve it.
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdbool.h>
/*the CFG
S>ABAC
A>aA|$
B>bB|$
C>c
*/
/*List produced
SABAC
AaA
A$
BbB
B$
Cc*/
/*Desired Result
SABAC
SABC
SBAC
SBC
AaA
BbB
Bb
Cc*/
typedef struct node {
struct node * next;
//struct node * prev;
char arr[7];//the array to save CFG per line
}node_t;
char print_list(node_t * root);
//char first_set(node_t * root,char c);
char traversal(node_t * root);//To see which nodes have null productions
char rightTraversal(node_t * root,char);//Passing the nodes which have null production then removing them from list.
char c, temp, nonTerminal; int i=0; bool flag = true;
char null_list[7];
int null_counter = 0;
int main() {
node_t * head = malloc(sizeof(node_t));
node_t * current = malloc(sizeof(node_t));
node_t * root = malloc(sizeof(node_t));
head = current;
for(int j=0; j<7; j++){
null_list[j] = '#';
}
FILE *fp;
//char c, temp; int i=0; bool flag = true;
fp = fopen("cfg.txt", "r");
while((c = fgetc(fp)) != EOF) {
if(c == '\n') {
current->next = malloc(sizeof(node_t));
//current->next->next = NULL;
current = current->next;
current->next = NULL;
flag = true; i=0;
}else if(c == '>' || c == ' '){continue;}
else if(c == '|'){
current->next = malloc(sizeof(node_t));
current = current->next;
i = 0;
current->arr[i] = temp;
i++;
continue;
}
else {
current->arr[i] = c;
i++;
current->next = NULL;
//current->prev = NULL;
if(flag){
temp = c;
flag = false;
}
// continue;
}
}
fclose(fp);
root = head;
traversal(root);
/*for(int j=0; j<7; j++){
if(null_list[j] != '#'){
printf("%c\n",null_list[j]);
}
}*/
rightTraversal(root, null_list[0]);
rightTraversal(root, null_list[1]);
}
char print_list(node_t * root) {
while(root->next != NULL){
for(i=0; i<7; i++) {
printf("%c", root->arr[i]);
}
printf("\n");
root = root->next;
}
return 0;
}
char traversal(node_t * root) {
while(root->next != NULL){
for(i=0; i<7; i++) {
if(root->arr[i] == '$'){
null_list[null_counter] = root->arr[0];
null_counter++;
}
}
root = root->next;
}
return 0;
}
char rightTraversal(node_t * root, char c){
node_t * shoot = root;
while(shoot->next != NULL){
for(int i=1; i<7; i++){
if(shoot->arr[i] == c){
node_t * temp_node = malloc(sizeof(node_t));
/*printf("%c\n", shoot->arr[0]);*/
for(int i=0; i<7; i++){
temp_node->arr[i] = shoot->arr[i];
}
for(int k=1; k<7; k++){
if(temp_node->arr[k]==c){
temp_node->arr[k] = ' ';
break;
}
}
temp_node->next = shoot->next;
shoot->next = temp_node;
break;
//shoot->next = malloc(sizeof(node_t));
//shoot = shoot->next;
}
}
shoot = shoot->next;
}
print_list(root);
}
fgetc() returns an int. You assign the result to a char.
So this condition
(c = fgetc(fp)) != EOF)
will never detect EOF.
To fix this defined c to be an int or introduce an intermediate int like this:
int ci;
while (ci = fgetc(fp)) != EOF)
{
c = ci;
If you'd pushed up the compiler's warning level to the maximum (-Wall -Wextra -Wconversion -pedantic for GCC) it mostly like had warned you on this!
I am writing a library management program where the user can add books to a database which just means that the program will take the user's input and store it into a text document. Then, when the program starts up it will read through the text document where all the books are stored and build a linked list where each book would be a node. So, I have been able to get to a point where I can read the text file and store the values into nodes. However, when I try testing the bookList function to view the entire book list by title my program crashes. Here is the code:
void loadingMenu(){
FILE *fp = fopen(filename, "r");
int lines = 0;
char line[254];
char *ti = malloc(MAX_STR_LEN);
char *au = malloc(MAX_STR_LEN);
char *ca = malloc(MAX_STR_LEN);
char *id = malloc(MAX_STR_LEN);
char *ti_chopped;
char *au_chopped;
char *ca_chopped;
char *id_chopped;
int id_num;
struct node *tempNode;
while(fgets(line, sizeof(line), fp)){
if(line == 'EOF'){
break;
}
if(lines == 7){
lines = 0;
}
if(lines == 0){
line[strcspn(line, "\n")] = 0; // remove '\n' from string
strcpy(ti, line);
}
else if(lines == 1){
line[strcspn(line, "\n")] = 0;
strcpy(au, line);
}
else if(lines == 3){
line[strcspn(line, "\n")] = 0;
strcpy(ca, line);
}
else if(lines == 6){
line[strcspn(line, "\n")] = 0;
strcpy(id, line);
}
lines++;
if(lines == 6){
// removing the identifiers from each string
ti_chopped = ti + 6;
au_chopped = au + 7;
ca_chopped = ca + 9;
id_chopped = id + 3;
id_num = atoi(id_chopped);
// ------create book node------------
tempNode = malloc(sizeof *tempNode);
// ----------------------------------
tempNode->next = NULL;
tempNode->titleptr = malloc(strlen(ti_chopped) + 1);
strcpy(tempNode->titleptr, ti_chopped);
tempNode->authorptr = malloc(strlen(au_chopped) + 1);
strcpy(tempNode->authorptr, au_chopped);
tempNode->categoryptr = malloc(strlen(ca_chopped) + 1);
strcpy(tempNode->categoryptr, ca_chopped);
tempNode->id = id_num;
//printf("%d", tempNode->id);
head = addNode(head, tempNode);
}
}
fclose(fp);
}
int compareNode(struct node *n1, struct node *n2){
int compareValue = strcmp(n1->titleptr, n2->titleptr);
if(compareValue == 0){
return 0;
}
else if(compareValue < 0){
return -1;
}
else {
return 1;
}
}
struct node *addNode(struct node *list, struct node *node1){
struct node* tmp = list;
if(list == NULL){
return node1;
}
if(compareNode(node1,list) == -1){
node1->next = list;
list = node1;
return list;
}
else
{
struct node* prev = list;
while(tmp != NULL && compareNode(node1, tmp) >= 0){
prev = tmp;
tmp = tmp->next;
}
prev->next = node1;
node1->next = tmp;
return list;
}
}
void bookList(){
system("cls");
struct node *tmp;
tmp = head;
printf("List of all Books: ");
while(tmp != NULL)
{
printf("%s\n", tmp->titleptr);
tmp = tmp->next;
}
printf("\n\nEnd of list.");
}
First off I would like to apologize for the bad code, also I trimmed away some of the fat of the program and just left the functions involved behind.
So, please if you could help me out on this or at least point me in the right direction I would be very grateful. Also, if you have any coding tips or comments go ahead and tell me, I am always hungry to learn!
EDIT: The code now runs and the list will print, however, the strings will not be in alphabetical order. Currently trying to figure that out.
In the first addNode() function, you need to set the previous pointer. That should fix the problem.
if(compareNode(node1,list) == -1)
{
node1->next = list;
list->prev = node1;
list = node1;
return list;
}
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.