I'm trying to build a binary search tree , that store word/definition pairs.
so my struct is like this :
struct BinarySearchTree_t
{
char *word,*def;
struct BinarySearchTree_t *left;
struct BinarySearchTree_t *right;
};
typedef struct BinarySearchTree_t BinarySearchTree;
So I've been blocked in insertWord function that inserts a word/definition pair in a binary search tree. Neither the word nor the definition may be NULL. NULL is considered as a special value. If the word already exists then this function replaces the current definition by the new one and returns the old one.
This is the function:
char* insertWord(BinarySearchTree *tree, char *word, char *definition)
{
int r;
char* a;
if((tree==NULL))
{
BinarySearchTree* tmp;
tmp = malloc( sizeof( BinarySearchTree ) );
tmp->word= malloc((strlen(word)+1)*sizeof(char));
tmp->def = malloc((strlen(definition)+1)*sizeof(char));
strcpy(tmp->word, word);
strcpy(tmp->def , definition);
tmp->left = NULL;
tmp->right = NULL;
*tree = *tmp;
return NULL;
}
else
{
a= tree->word;
r= strcmp(a,word);
if(r = 0)
{
char* ret= tree->def;
strcpy(tree->word, word);
strcpy(tree->def , definition);
return ret;
}
else if(r<0)
return insertWord((tree->right),word,definition);
else
return insertWord((tree->left),word,definition);
}
}
What is the problem?
Edited : the correct function:
char* insertWord(BinarySearchTree **tree, char *word, char *definition)
{
int r;
char* a;
if(((*tree)==NULL) || ((*tree)!=NULL && (*tree)->mot==NULL))
{
BinarySearchTree* tmp;
tmp = malloc( sizeof( BinarySearchTree ) );
tmp->left = NULL;
tmp->right = NULL;
tmp->mot = malloc((strlen(word)+1)*sizeof(char));
tmp->def = malloc((strlen(definition)+1)*sizeof(char));
strcpy(tmp->mot , word);
strcpy(tmp->def , definition);
*tree = tmp;
return NULL;
}
else
{
a= (*tree)->mot;
r= strcmp(a,word);
if(r == 0)
{
char* ret= (*tree)->def;
strcpy((*tree)->mot , word);
strcpy((*tree)->def , definition);
return ret;
}
else if(r<0)
return insertWord(&((*tree)->right),word,definition);
else
return insertWord(&((*tree)->left),word,definition);
}
}
So, you are trying to initialize the pointer to root of your SearchTree, the first time it's accessed, right? The problem is that you are modifying a local copy of the pointer *tree and not the actual pointer that's present in the parent (calling) function. If you plan to modify the pointer to your SearchTree inside the called function, you should pass a pointer to the *tree in call to insertWord (i.e. a pointer to pointer).
You should change the definition to:
char* insertWord(BinarySearchTree **tree, char *word, char *definition)
Accordingly you should modify all accesses of tree inside your insertWord function.
Alternative working code — given a clean bill of health by valgrind:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct BinarySearchTree_t
{
char *word, *def;
struct BinarySearchTree_t *left;
struct BinarySearchTree_t *right;
};
typedef struct BinarySearchTree_t BinarySearchTree;
static void freeTree(BinarySearchTree *root);
static void dump_tree(BinarySearchTree *root);
extern char *insertWord(BinarySearchTree **ptree, char *word, char *definition);
char *insertWord(BinarySearchTree **ptree, char *word, char *definition)
{
if (*ptree == NULL)
{
BinarySearchTree *tmp = malloc(sizeof(*tmp));
tmp->word = strdup(word);
tmp->def = strdup(definition);
tmp->left = NULL;
tmp->right = NULL;
*ptree = tmp;
return tmp->def;
}
else
{
BinarySearchTree *tree = *ptree;
int r = strcmp(tree->word, word);
if (r == 0)
{
free(tree->def);
tree->def = strdup(definition);
return tree->def;
}
else if (r < 0)
return insertWord(&tree->right, word, definition);
else
return insertWord(&tree->left, word, definition);
}
}
int main(void)
{
char *word_defs[][2] =
{
{ "cat", "feline" },
{ "dog", "canine" },
{ "box", "carton" },
{ "cat", "purring critter" },
};
BinarySearchTree *root = 0;
for (size_t i = 0; i < sizeof(word_defs) / sizeof(word_defs[0]); i++)
{
printf("%zu: Add %s => %s\n", i, word_defs[i][0], word_defs[i][1]);
char *def = insertWord(&root, word_defs[i][0], word_defs[i][1]);
dump_tree(root);
printf("New definition: %s\n", def);
}
freeTree(root);
return 0;
}
static void freeTree(BinarySearchTree *root)
{
if (root != 0)
{
freeTree(root->left);
freeTree(root->right);
free(root->word);
free(root->def);
free(root);
}
}
static void dump_tree(BinarySearchTree *root)
{
if (root->left != 0)
dump_tree(root->left);
printf("%p: %s => %s\n", (void *)root, root->word, root->def);
if (root->right != 0)
dump_tree(root->right);
}
This version reports the new definition of the word. The original code may have been reporting the old definition; it is not hard to fix this code so that it reports the old definition (but it requires a modicum of care to ensure that the old definition is actually released, and null pointers aren't printed).
Related
How can I return a tree node when I found it?
So, I have a binary tree and, when I search in the tree what I searched for was found I want to return the pointer to that node, so I can usa that node in other function. There is my search function:
Tnode *Tsearch(Tnode *r, char *word) {
if(r == NULL) {
printf("%s NOT FOUND\n", word);
return NULL;
}
int comp = strcasecmp(r->word, word);
if( comp == 0) {
printf("%s FOUND\n", r->word);
return r;
}
else if( comp > 0) {
Tsearch(r->left, word);
}
else if( comp < 0) {
Tsearch(r->right, word);
}
return 0;
}
My problem is that when I try to use the return of the function Tsearch it doesn't work and I really can't understand why and how to solve it.
The function where I want to use that returned node from the search function is the following:
int Tsearch_ref(Tnode *r, char (*words)[30]) {
if(r == NULL) {
return 0;
}
printf("%s, %d", words[0], (int)strlen(words[0]));
Tsearch(r,words[0]);
auxT = Tsearch(r,words[0]);
Lnode *aux = auxT->head;
printf("Title: %s\n", ((Book *)aux->ref)->title);
while(aux != NULL) {
aux_arr[i].ref=aux->ref;
printf("Title: %s\n", ((Book *)aux_arr[i].ref)->title);
printf("%p\n", &(aux_arr[i].ref));
aux = aux->next;
i++;
}
}
This function is not complete because I was trying to solve the return problem, but basically I want to take that tree node that have a list inside and put that list into a temporary array.
The structures are the following:
typedef struct {
char *title;
char isbn13[ISBN13_SIZE];
char *authors;
char *publisher;
int year;
} Book;
typedef struct lnode {
struct lnode *next;
void *ref;
} Lnode;
typedef struct tnode {
struct tnode *left;
struct tnode *right;
char *word;
Lnode *head;
} Tnode;
It's my first question here in StackOverflow, so if you need any more info about anything I will obviously provide it.
Thanks in advance!
You need to change the recursive calls to Tsearch to actually return the found node. So, instead of this code:
else if( comp > 0) {
Tsearch(r->left, word);
}
else if( comp < 0) {
Tsearch(r->right, word);
}
do this:
else if( comp > 0) {
return Tsearch(r->left, word);
}
else if( comp < 0) {
return Tsearch(r->right, word);
}
Note that if your tree is very deep, you may use up the entire call stack and throw an exception.
Why not use while loop?
Tnode *Tsearch(Tnode *r, char *word) {
Tnode *cur = r;
int comp;
while (cur != NULL)
{
if ((comp = strcasecmp(cur->word, word)) == 0)
{
printf("%s FOUND\n", cur->word);
return cur;
}
else if (comp > 0)
{
/* Move to the left child */
cur = cur->left;
}
else
{
/* Move to the right child */
cur = cur->right;
}
}
printf("NOT FOUND\n");
return NULL;
}
This function update() should suppose to the this, it scans information from file stream upd, number of the PC and its new IP address. It should scan the tree looking for PC's that have same red_br and s_red_br, and when it finds that PC, should update its IP address with the new IP address (s_ip_adress).
red_br and s_red_br are numbers of a PC; ip_adresa is PC's current IP address; s_ip_adresa is a new IP address.
RACUNAR is from:
typedef struct racunar_st {
int red_br;
char naziv[MAX_NAZIV];
char ip_adresa[MAX_IP];
int brzina;
struct racunar_st *left;
struct racunar_st *right;
} RACUNAR;
void update(FILE *upd, FILE *out, RACUNAR *root){
int s_red_br;
char s_ip_adresa[MAX_IP];
while(fscanf(upd, "%d %s", &s_red_br, s_ip_adresa) == 2){
int temp = root->red_br;
char temp1 = *root->ip_adresa;
if (temp == s_red_br){
temp1 = *s_ip_adresa;
}
}
}
I know that I am not going through the whole tree; I just wanted to test it and I can't even change the root.
Here you go the full program:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#define MAX_NAZIV 20
#define MAX_VEL 10
#define MAX_IP 14+1
typedef struct racunar_st {
int red_br;
char naziv[MAX_NAZIV];
char ip_adresa[MAX_IP];
int brzina;
struct racunar_st *left;
struct racunar_st *right;
} RACUNAR;
void init_tree(RACUNAR **root){
*root = NULL;
}
void add_to_tree(RACUNAR *new, RACUNAR **root){
if(*root == NULL){
*root = new;
} else if(new->brzina <= (*root)->brzina){
add_to_tree(new, &((*root)->left));
} else if(new->brzina > (*root)->brzina) {
add_to_tree(new, &((*root)->right));
}
}
RACUNAR *create_new_item(int red_br, char naziv[], char ip_adresa[], int brzina){
RACUNAR *new = (RACUNAR *)malloc(sizeof(RACUNAR));
if(new == NULL){
printf("Nema dovoljno RAM-a!!!\n");
exit(21);
}
new->red_br = red_br;
strcpy(new->naziv, naziv);
strcpy(new->ip_adresa, ip_adresa);
new->brzina = brzina;
new->left = NULL;
new->right = NULL;
return new;
}
void read_tree_from(FILE *in, RACUNAR **root){
int tmp_red_br;
char tmp_naziv[MAX_NAZIV];
char tmp_ip_adresa[MAX_IP];
int tmp_brzina;
while(fscanf(in, "%d %s %s %d", &tmp_red_br, tmp_naziv, tmp_ip_adresa, &tmp_brzina) != EOF){
RACUNAR *new = create_new_item(tmp_red_br, tmp_naziv, tmp_ip_adresa, tmp_brzina);
add_to_tree(new, root);
}
}
void save_item_to(FILE *out, RACUNAR *x){
fprintf(
out, "%d %s %s %d\n",
x->red_br, x->naziv, x->ip_adresa, x->brzina
);
}
void save_tree_to(FILE *out, RACUNAR *root){
if(root != NULL){
save_tree_to(out, root->left);
save_item_to(out, root);
save_tree_to(out, root->right);
}
}
void destroy_tree(RACUNAR **root){
if(*root != NULL){
destroy_tree(&((*root)->left));
destroy_tree(&((*root)->right));
free(*root);
*root = NULL;
}
}
FILE *safe_fopen(char *filename, char *mode, int error_code){
FILE *fp = fopen(filename, mode);
if(fp == NULL){
printf("Nije moguce otvoriti fajl '%s'\n", filename);
exit(error_code);
}
return fp;
}
void update(FILE *upd, FILE *out, RACUNAR *root){
int s_red_br;
char s_ip_adresa[MAX_IP];
while(fscanf(upd, "%d %s", &s_red_br, s_ip_adresa) == 2){
int temp = root->red_br;
printf("%d\n", temp); // just testing to see if the function read data from file
printf("%d\n", s_red_br);
printf("%s\n", s_ip_adresa);
if ( temp == s_red_br){
*root->ip_adresa = *s_ip_adresa;
}
} printf("%s\n", root->ip_adresa); // checking if that ip adress has been changed
}
int main(int arg_num, char *args[]) {
if(arg_num != 4){
printf("Neispravan poziv programa!\n Pozvati sa: FILENAME_IN FILENAME_UPDATE FILENAME_OUT\n");
exit(1);
}
char *in_filename = args[1];
char *update_filename = args[2];
char *out_filename = args[3];
FILE *in = safe_fopen(in_filename, "r", 1);
FILE *upd = safe_fopen(update_filename, "r", 2);
FILE *out = safe_fopen(out_filename, "w", 3);
RACUNAR *root;
init_tree(&root);
read_tree_from(in, &root);
update(upd, out, root);
save_tree_to(out, root);
destroy_tree(&root);
fclose(in);
fclose(upd);
fclose(out);
return 0;
}
Second attempt:
Your update(upd, out, root); takes an input file, an output file and a pointer to an in-memory binary tree. Your save_tree_to(out, root); takes an output file and a pointer to root. Make up your mind which of those two functions will write to the file. Assuming we don't need the output file for update and that it can simply make changes within the root data structure, then:
void update( FILE *upd, RACUNAR *root )
{
int s_red_br;
char s_ip_adresa[MAX_IP];
while ( fscanf( upd, "%d %s", &s_red_br, s_ip_adresa ) == 2 )
{
RACUNAR *node = find( s_red_br, root );
if ( NULL != node )
{
strncpy(node->ip_adresa, s_ip_adresa, MAX_IP);
}
else
{
// Either insert new data or throw some kind of error here.
}
}
}
Your real problem is the fact that you have data structure that is not sorted by a primary key. Given a red_br value, you can't find the matching node without searching the entire tree.
RACUNAR* find( int red_br, RACUNAR *root )
{
RACUNAR *node = root;
while ( NULL != node )
{
if ( red_br == node->red_br )
{
return node;
}
// TODO: Need search code here, basically requires a tree sorted by red_br values.
node = NULL;
}
return node;
}
My insertion worked, so a new question, How do I set a data to NULL in C? Pls see the last part for illustration.!
I have defined a structure type
typedef struct node {
char* data;
int weight;
bool end_of_key;
struct node * left;
struct node * equal;
struct node * right;
} node_t;
int main(int argc, char *argv[]){
node_t* root=NULL;
int weight;
int i = 1;
insert(root,"cat",3);
insert(root,"at",2);
insert(root,"cute",4);
.....
return 0 ;}
This is my insert function
node_t* insert(node_t* pNode,char* word, int weight) {
/**
* Create a new pNode, and save a character from word
*/
pNode = (node_t*)malloc(sizeof(node_t));
if(*pNode->data == NULL){
pNode->left = NULL;
pNode->equal = NULL;
pNode->right = NULL;
pNode->data = word;
}
if (word[0] < *(pNode->data)) {
/**
* Insert the character on the left branch
*/
pNode->left = insert(pNode, word, weight);
}
else if (word[0] == *(pNode->data)) {
if ((word[1]) == '\0') {
/**
*set pNode end_of_key_flag to true and assign weight
*/
pNode->end_of_key = true;
pNode->weight = weight;
// printf("%c", *(pNode->data++));
}
else {
/**
* If the word contains more characters, try to insert them
* under the equal branch
*/
// printf("%c", *(pNode->data++));
pNode->equal = insert(pNode,word + 1, weight);
}
}
else {
/**
* If current char in word is greater than char in pData
* Insert the character on the right branch
*/
pNode->right = insert(pNode,word, weight);
}
return pNode;}
this code is trying to do this
So my insertion finally worked but it appears that it can only insert one thing,I am wondering how do I set data to NULL in C?
if(*pNode->data == NULL){
pNode->left = NULL;
pNode->equal = NULL;
pNode->right = NULL;
pNode->data = word;
}
I want to run this four lines of code when *pNode->data is empty but it apparently did not work the way I wanted it to.
Some improvements of your code
insert() must have first parameter to be node_t ** (see comments)
char *data must be char data, because every node contains only one char
weight can be calculated when the list is filled up
Here is corrected version of your code. Function get() is used to find the key in the filled up list (for testing).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node {
char data;
int weight;
struct node * left;
struct node * equal;
struct node * right;
} node_t;
void insert(node_t** pNode, char* word, int weight)
{
char data;
node_t **pNext;
node_t *pCurrent;
if (word == NULL)
{
return ;
}
data = word[weight];
if (*pNode == NULL)
{
*pNode = malloc(sizeof(node_t));
pCurrent = *pNode;
memset(pCurrent, 0, sizeof(node_t));
pCurrent->data = data;
}
else
{
pCurrent = *pNode;
}
if (data == pCurrent->data)
{
weight ++;
if (strlen(word) == weight)
{
pCurrent->weight = weight;
return;
}
pNext = &pCurrent->equal;
}
else if (data > pCurrent->data)
{
pNext = &pCurrent->right;
}
else
{
pNext = &pCurrent->left;
}
insert(pNext, word, weight);
}
int get(node_t** pNode, char *word, int weight)
{
char data;
node_t **pNext;
node_t *pCurrent;
if (word == NULL)
{
return 0;
}
data = word[weight];
if (*pNode == NULL)
{
return 0; // not found
}
pCurrent = *pNode;
if (data == pCurrent->data)
{
weight ++;
if (strlen(word) == weight)
{
return pCurrent->weight;
}
pNext = &pCurrent->equal;
}
else if (data > pCurrent->data)
{
pNext = &pCurrent->right;
}
else
{
pNext = &pCurrent->left;
}
return get(pNext, word, weight);
}
int main()
{
node_t * root = NULL;
insert(&root, "cat", 0);
insert(&root, "at", 0);
insert(&root, "cute", 0);
printf("cat=%d\n",get(&root,"cat",0)); // cat=3
printf("at=%d\n",get(&root,"at",0)); // at=2
printf("cute=%d\n",get(&root,"cute",0)); // cute=4
// todo: free memory
return 0;
}
The code is tested except freeing the memory.
First, there is something wrong with your insert() signature
(as already pointed by #MichaelWalz )
you'd rather
node_t* insert(node_t** pNode, char* word, int weight);
and then
insert(&root,"cute",4);
why don't you start fixing this and edit your post ?
I am trying to insert strings in the binary search tree.
So what I am to trying is,
parsing strings from a file(contains instruction set) and then inserting in the function
insertOpcodeFromFile().
So this function will execute
(*node) = Node_insert(&node,instruction).
the node will be the root of binary tree which is located in main function.
So in simple way to explain, I want to manipulate(insert) the root pointer in the main function by using double pointer in the other function contain insert function.
I have a simple understanding about the pointer, but in this situation, I need to use more than double pointer I think.
please explain me about the double pointer clearly using this example.
Here is my code(I commenting out insert_node)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef BINARYTREE_H_
#define BINARYTREE_H_
typedef struct node *NodePtr;
typedef struct node {
char *word;
int count;
NodePtr left;
NodePtr right;
} Node;
NodePtr Node_alloc();
NodePtr Node_insert(NodePtr node_ptr, char *word);
void clearArray(char a[]);
void insertOpcodeFromFile(FILE *opcodeFile, NodePtr *node);
void Node_display(NodePtr);
char *char_copy(char *word);
#endif
int main(int argc, const char * argv[]) {
FILE * opFile;
FILE * progFile;
struct node *root = NULL;
if ( argc != 4) { // # of flag check
fprintf(stderr, " # of arguments must be 4.\n" );
exit(1);
}
opFile = fopen ( argv[1], "r");
if(opFile == NULL)
{
fprintf(stderr,"There is no name of the opcode file\n");
exit(1);
}
progFile = fopen ( argv[2], "r");
if(progFile == NULL)
{
fprintf(stderr,"There is no name of the program file \n");
exit(1);
}
insertOpcodeFromFile(opFile, &root);
//Node_display(root);
}/* main is over */
void insertOpcodeFromFile(FILE *opcodeFile, NodePtr *node)
{
int fsize = 0;
int lengthOfInst = 0;
int c;
int i;
char buffer[100];
fsize = getFileSize(opcodeFile);
enum flag {ins,opc,form};
int flag = ins;
char instruction[6];
unsigned int opcode = 0;
unsigned char format;
while (c != EOF)
{
c = fgetc(opcodeFile);
buffer[i++] = c;
if (c == 32){
switch (flag) {
case ins:
flag = opc;
memcpy(instruction,buffer,i);
instruction[i] = '\0';
clearArray(buffer);
i = 0;
// printf("인스트럭션 : %s\n",instruction );
break;
case opc:
flag = form;
opcode = atoi(buffer);
clearArray(buffer);
i = 0;
// printf("옵코드 : %d\n",opcode );
break;
default:
break;
}/* end of switch */
}/* end of if(space) */
if((c == 10) || (c == EOF))
{
if (flag == form)
{
format = buffer[0];
clearArray(buffer);
i = 0;
// printf("포멧: %c\n", format);
}
flag = ins;
//node = Node_insert(node,instruction);
}
}
//Node_display(node);
}
int getFileSize(FILE *opcodeFile)
{ int fsize = 0;
fseek(opcodeFile,0, SEEK_SET);
fseek(opcodeFile,0, SEEK_END);
fsize = (int)ftell(opcodeFile);
fseek(opcodeFile,0, SEEK_SET);
return fsize;
}
int countUntilSpace(FILE *opcodeFile, int currentPosition)
{ char readword[1];
char *space = " ";
char *nextLine = "/n";
int i = 0;
//printf("현재: %d\n",currentPosition );
while(1)
{
fread(readword, sizeof(char),1,opcodeFile);
i++;
if(strcmp(readword,space) == 0 || strcmp(readword,nextLine) == 0)
{
//printf("break\n");
break;
}
}
fseek(opcodeFile,currentPosition ,SEEK_SET);
//printf("끝난 현재 :%d\n",ftell(opcodeFile) );
//printf("%I : %d\n",i );
return i - 1;
}
void clearArray(char a[])
{
memset(&a[0], 0, 100);
}
NodePtr Node_alloc()
{
return (NodePtr) malloc(sizeof(NodePtr));
}
NodePtr Node_insert(NodePtr node_ptr, char *word)
{
int cond;
if (node_ptr == NULL) {
node_ptr = Node_alloc();
node_ptr->word = char_copy(word);
node_ptr->count = 1;
node_ptr->left = node_ptr->right = NULL;
} else if ((cond = strcmp(word, node_ptr->word)) == 0) {
node_ptr->count++;
} else if (cond < 0) {
node_ptr->left = Node_insert(node_ptr->left, word);
} else {
node_ptr->right = Node_insert(node_ptr->right, word);
}
return node_ptr;
}
void Node_display(NodePtr node_ptr)
{
if (node_ptr != NULL) {
Node_display(node_ptr->left);
printf("%04d: %s\n", node_ptr->count, node_ptr->word);
Node_display(node_ptr->right);
}
}
char *char_copy(char *word)
{
char *char_ptr;
char_ptr = (char *) malloc(strlen(word) + 1);
if (char_ptr != NULL) {
char_ptr = strdup(word);
}
return char_ptr;
}
In this case, in main(),
Node *root;
Why do you need to use a "double" pointer ( Node ** ) in functions that alter root is because root value as to be set in these functions.
For instance, say you want to allocate a Node and set it into root.
If you do the following
void alloc_root(Node *root) {
root = malloc(sizeof (Node));
// root is a function parameter and has nothing to do
// with the 'main' root
}
...
// then in main
alloc_root( root );
// here main's root is not set
Using a pointer to pointer (that you call "double pointer")
void alloc_root(Node **root) {
*root = malloc(sizeof (Node)); // note the *
}
...
// then in main
allow_root( &root );
// here main's root is set
The confusion comes probably from the Node *root in main, root being a pointer to a Node. How would you set an integer int i; in a function f? You would use f(&i) to call the function f(int *p) { *p = 31415; } to set i to the value 31415.
Consider root to be a variable that contains an address to a Node, and to set its value in a function you have to pass &root. root being a Node *, that makes another *, like func(Node **p).
So I am trying to sort a linked list, from small to big based on the name. It sorts it but it is sorting it the reverse or wrong way.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
//declaring a struct
struct node {
char *name;
int num;
struct node *next;
};
struct node *list=NULL;
/*
* insert()
*/
struct node *insert(char word2[], int val){
struct node *tmp;
tmp = malloc(sizeof(struct node));
if(tmp ==NULL){
fprintf(stderr, "out of memory\n");
exit(1);
}
tmp->name = strdup(word2);
tmp->num = val;
tmp->next = list;
list = tmp;
return tmp;
}//read string
void print(){
struct node *ptr;
for(ptr= list; ptr!=NULL; ptr = ptr->next){
printf(" %s/%d\n", ptr->name, ptr->num);
}//for loop
}//print
void sort(){
struct node *ptr1, *ptr2;
char *tmp;
for(ptr1 = list; ptr1!=NULL; ptr1 = ptr1->next){
for(ptr2 = ptr1->next; ptr2!=NULL; ptr2 = ptr2->next){
if(strcmp(ptr1->name, ptr2->name)>0){
//ptr1->name is "greater than" ptr2->name - swap them
tmp = ptr1->name;
ptr1->name = ptr2->name;
ptr1->name = tmp;
}
}
}
}//sort
int main (){
char buff[81];
int status=0;
int len;
char word1[20];
char word2[20];
int val;
// char word3[20];
while(fgets(buff, 81, stdin)>0){
len = strlen(buff);
if(buff[len-1]!='\n'){
fprintf(stderr,"Error: string line length was too long\n");
exit(1);
}
sscanf(buff, "%s %s %d", word1, word2, &val);
if(strcmp(word1, "insert")==0){
insert(word2, val);
sort();
}else if(strcmp(word1, "print")==0){
print();
}else{
}
}//while loop
return status;
}
This is what my input looks like when I run it.
"insert a 1"
"insert b 2"
"insert c 3"
"print"
output
c/3
b/2
a/1
If have tried changing my sort method condition but it keeps sorting it the wrong way. I can't seem to find the bug. Any help will be greatly appreciated. But my output is supposed to look like this
Desired output
a/1
b/2
c/3
If you sort after every insert you do not need the full bubble-sort, just one round.
void sort()
{
struct node *ptr1 = list;
char *tmpname;
int tmpnum;
while (ptr1->next != NULL) {
if (strcmp(ptr1->name, ptr1->next->name) > 0) {
// swap content in this case, not the nodes
tmpname = ptr1->name;
tmpnum = ptr1->num;
ptr1->name = ptr1->next->name;
ptr1->num = ptr1->next->num;
ptr1->next->name = tmpname;
ptr1->next->num = tmpnum;
}
ptr1 = ptr1->next;
}
}