How to change value of a string in binary tree? - c

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;
}

Related

Build a linked list in c

I am attempting to create a linked list from a file using structs, when I run the print_list it is not printing the name or threat level, but it is printing the ID. I have little experience with structs but I believe I am not understanding if the pointers are being used correctly here.
void insert(struct poi_t_struct **head_ref, char *name, long int id, int threat_level) {
// printf("Name from insert %s \n", name); // debug
struct poi_t_struct newNode = { name, id, threat_level, NULL };
struct poi_t_struct *ptr_newNode = &newNode;
struct poi_t_struct *temp = *head_ref;
}
void buildLList(char *filename) {
FILE *poiProfiles;
// char line[MAX_LINE_LENGTH];
// have 3 char arrays. One for each name, id, threat level
char idLine[MAX_LINE_LENGTH];
char nameLine[MAX_LINE_LENGTH];
char threat_levelLine[MAX_LINE_LENGTH];
while (fgets(idLine, MAX_LINE_LENGTH, poiProfiles)) {
long int id;
id = atoi(idLine);
fgets(nameLine, MAX_LINE_LENGTH, poiProfiles);
char* name;
name = nameLine;
fgets(threat_levelLine, MAX_LINE_LENGTH, poiProfiles);
int threat_level;
threat_level = atoi(threat_levelLine);
insert(&head, name, id, threat_level);
}
void print_list(struct poi_t_struct *p) {
struct poi_t_struct *temp = p;
while (temp != NULL) {
print_record(temp);
temp = temp->next;
}
}
There are multiple problems in your code:
you do not open nor close the file for poiProfiles
there is a missing } at the end of the buildLList() function.
the insert function must allocate memory for the new node, inserting a local struct object is incorrect as this object becomes invalid as soon as the function returns. You attempt to insert the new node at the beginning of the list, but you neither set the next member of the struct, not set *head_ref to point to the new node.
Here is a modified version:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct poi_t_struct {
char *name;
long int id;
int threat_level;
struct poi_t_struct *next;
} *head;
int insert(struct poi_t_struct **head_ref, const char *name, long int id, int threat_level) {
// printf("Name from insert %s \n", name); // debug
struct poi_t_struct *ptr_newNode = malloc(sizeof *ptr_newNode);
if (ptr_newNode == NULL)
return -1;
ptr_newNode->name = strdup(name);
ptr_newNode->id = id;
ptr_newNode->threat_level = threat_level;
ptr_newNode->next = *head_ref;
*head_ref = ptr_newNode;
return 0;
}
int buildLList(const char *filename) {
// have 3 char arrays. One for each name, id, threat level
char idLine[MAX_LINE_LENGTH];
char nameLine[MAX_LINE_LENGTH];
char threat_levelLine[MAX_LINE_LENGTH];
FILE *poiProfiles;
int count = 0;
poiProfiles = fopen(filename, "r");
if (poiProfiles == NULL) {
fprintf(stderr, "cannot open %s: %s\n", filename, strerror(errno));
return -1;
}
while (fgets(idLine, MAX_LINE_LENGTH, poiProfiles)
&& fgets(nameLine, MAX_LINE_LENGTH, poiProfiles)
&& fgets(threat_levelLine, MAX_LINE_LENGTH, poiProfiles)) {
long int id = atoi(idLine);
char *name = nameLine;
int threat_level = atoi(threat_levelLine);
if (!insert(&head, name, id, threat_level))
count++;
}
fclose(poiProfiles);
return count;
}
void print_list(const struct poi_t_struct *p) {
const struct poi_t_struct *temp = p;
while (temp != NULL) {
print_record(temp);
temp = temp->next;
}
}

Double pointer in the function

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).

Writing a program to take data from file then store in BST

I'm writing a program to take data to store in a BST.
My problem is I don't know what's wrong with my MakeNewNode and Insert function.
I tried both of them the printed data didn't come out as expected. Please help
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct example
{
char MSKH[13];
char ten[30];
char tong[12];
int thucpham;
int dientu;
int maymac;
}KeyType;
typedef struct node
{
KeyType key;
struct node* left;
struct node* right;
}NodeType;
typedef NodeType* TreeType;
NodeType* MakeNewNode(KeyType a)
{
NodeType* NewNode;
NewNode = (NodeType *)malloc(sizeof(NodeType));
if (NewNode != NULL)
{
strcpy(a.MSKH,((NewNode)->key).MSKH);
strcpy(a.ten,((NewNode)->key).ten);
strcpy(a.tong,((NewNode)->key).tong);
((NewNode)->key).thucpham = a.thucpham;
((NewNode)->key).dientu = a.dientu;
((NewNode)->key).maymac = a.maymac;
/*strcpy(a.thucpham,(NewNode->key).thucpham);
strcpy(a.dientu,(NewNode->key).dientu);
strcpy(a.maymac,(NewNode->key).maymac);*/
(NewNode)->left = NULL;
(NewNode)->right= NULL;
}
return NewNode;
}
void Insert(KeyType a, TreeType *Root)
{
if(*Root == NULL)
{
*Root = (NodeType *)malloc(sizeof(NodeType));
strcpy(a.MSKH,((*Root)->key).MSKH);
strcpy(a.ten,((*Root)->key).ten);
strcpy(a.tong,((*Root)->key).tong);
((*Root)->key).thucpham = a.thucpham;
((*Root)->key).dientu = a.dientu;
((*Root)->key).maymac = a.maymac;
/*strcpy(a.thucpham,(Root->key).thucpham);
strcpy(a.dientu,(Root->key).dientu);
strcpy(a.maymac,(Root->key).maymac);*/
(*Root)->left = NULL;
(*Root)->right= NULL;
}
else if (strcasecmp(a.MSKH,((*Root)->key).MSKH) < 0) Insert(a,&(*Root)->left);
else if (strcasecmp(a.MSKH,((*Root)->key).MSKH) > 0) Insert(a,&(*Root)->right);
}
void Traverse(TreeType Root){
if (Root != NULL)
{
Traverse(Root->left);
printf("%s %s %s %d %d %d\n",(Root->key).MSKH,(Root->key).ten,(Root->key).tong,(Root->key).thucpham,(Root->key).dientu,(Root->key).maymac);
Traverse(Root->right);
}
}
int main(){
FILE* fin, *fout;
fin = fopen("F:\\text.txt","r");
char line[256];
TreeType root=NULL;
KeyType hoadon;
fscanf(fin,"%13s %30s %12s %d %d %d",&hoadon.MSKH,&hoadon.ten,&hoadon.tong,&hoadon.thucpham,&hoadon.dientu,&hoadon.maymac);
printf("%s %s %s %d %d %d\n",hoadon.MSKH,hoadon.ten,hoadon.tong,hoadon.thucpham,hoadon.dientu,hoadon.maymac);
root = MakeNewNode(hoadon);
printf("%s",(root->key).MSKH);
fclose(fin);
}
Example of data from txt file: CLA012032A1 NguyenNam 12000000 1 2 3

Insert a word into a binary search tree C

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).

Need to Merge Sort a Linked List of names

I need help with my merge sort function that is a linke list of names. I get a seg fault when I run the program, and I feel like something isnt right. Thanks for the help in advance.
The program is supposed to print out the list of names before sorting, then the list of names after sorting.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
#define MAX_STR_LEN 25
typedef struct Data_ {
char *name;
struct Data_ *next;
}Data;
void split_in_half(Data *source, Data **frontRef,Data **backRef);
Data* merge(Data *a, Data *b);
void merge_sort(Data **list);
Data* read_from_file(const char* file, const int size);
void display(Data *list);
void push(Data **head, char *name);
int main(int argc, char **argv){
if(argc != 2){
printf("Not enough parameters!");
exit(0);
}
Data *head = NULL;
int size = 10;
head = read_from_file(argv[1], size);
printf("\nBefore sort");
display(head);
printf("\nMerge Sort\n");
merge_sort(&head);
display(head);
}
void merge_sort(Data **list){
Data *head = *list;
Data *temp;
Data *temp2;
if((head == NULL) || (head->next == NULL))
{
return;
}
split_in_half(head, &temp, &temp2);
head = merge(temp, temp2);
}
Data *merge(Data *a, Data *b){
Data *result = NULL;
if(a == NULL)
return(b);
else if(b==NULL)
return (a);
if(strcmp(a->name, b->name) > 0)
{
result = a;
result->next = merge(a->next, b);
}
else
{
result = b;
result->next = merge(a, b->next);
}
return (result);
}
void split_in_half(Data *source, Data **frontRef,Data **backRef){
Data *fast;
Data *slow;
if(source == NULL || source->next == NULL)
{
*frontRef = source;
*backRef = NULL;
}
else
{
slow = source;
fast = source->next;
while(fast != NULL)
{
fast = fast->next;
if(fast != NULL)
{
slow = slow->next;
fast = fast->next;
}
}
}
*frontRef = source;
*backRef = slow->next;
slow->next = NULL;
}
void push(Data **head, char *name){
Data *temp = malloc(sizeof(Data));
temp->name = strdup(name);
temp->next = *head;
*head = temp;
}
Data* read_from_file(const char* file, const int size){
FILE *input;
input = fopen(file, "r");
Data *new_ = (Data*)malloc(sizeof(Data*));
new_->next = NULL;
int i;
char name[MAX_STR_LEN];
for(i = 0; i < size; i++){
fscanf(input, "%24s", &name);
push(&new_, name);
}
return new_;
}
void display(Data *list){
Data *current = list;
while(current->next != NULL){
printf("\n%s", current->name);
current = current->next;
}
}
The file that I read in is a list of names. It is:
Derek
Drew
Randell
Terrell
Carmen
Colin
Eddy
Pablo
Lamont
Dexter
In read_from_file you have:
Data *new_ = (Data*)malloc(sizeof(Data*));
new_->next = NULL;
However, you have only allocated space for a pointer, rather than allocated space for a Data structure. So you will be writing off the end of the allocated space in the second line above.
Instead, write:
Data *new_ = (Data*)malloc(sizeof(Data));
new_->next = NULL;
[ You can read about the cons of casting the result of malloc at Do I cast the result of malloc?, but I am just making the minimal change for progress above ]
Once you've made the fix above, try walking through the program in a debugger, or adding printf statements, so you can see exactly how the program is behaving, and understand where any other problems occur.

Resources