I am trying to insert Node to Binary tree. This is my function for creating Node (rest is done).
void BVSCreate_function(TNodef *rootPtr, function_save token) {
TNodef *newPtr = malloc(sizeof(struct tnodef));
if (newPtr == NULL) {
fprintf(stderr, "99");
return;
}
TNodef init;
string initStr;
initStr.str = NULL;
initStr.length = 0;
initStr.alloc = 0;
newPtr = &init;
newPtr->content = &initStr;
newPtr->leftPtr = NULL;
newPtr->rightPtr = NULL;
newPtr->return_type = token.ret_value;
newPtr->parameters = token.param_count;
strCpyStr(newPtr->content, token.content);
rootPtr = newPtr;
}
void BVSInsert_function(TNodef *rootPtr, function_save token) {
if (rootPtr == NULL) {
BVSCreate_function(rootPtr, token);
} else {
if ((strCmpStr(token.content, rootPtr->content)) < 0) {
BVSCreate_function(rootPtr->leftPtr, token);
} else
if ((strCmpStr(token.content, rootPtr->content)) > 0) {
BVSCreate_function(rootPtr->rightPtr, token);
}
}
}
When TNodef and function_save are structs:
typedef struct {
string *content;
int param_count;
int ret_value;
} function_save;
typedef struct tnodef {
string *content;
struct tnodef *leftPtr;
struct tnodef *rightPtr;
int parameters;
int return_type;
} TNodef;
Where string is defined as this struct:
typedef struct {
char *str; // content of string
int length; // length of string
int alloc; // amount of memory allocated
} string;
strCpystr function :
int strCpyStr(string *s1, string *s2) {
int len2 = s2->length;
if (len2 > s1->alloc) {
if (((s1->str) = (char *)realloc(s1->str, len2 + 1)) == NULL) {
return 1;
}
s1->alloc = len2 + 1;
}
strcpy(s1->str, s2->str);
s1->length = len2 + 1;
return 0;
}
I am trying to create a node in binary tree and put there information from struct function_save.
But when I try to print this tree after insert it shows me that tree is still empty.
Your code in BVSCreate_function has undefined behavior because:
newPtr = &init; discards the allocated node and instead uses a local structure that will become invalid as soon as the function returns.
newPtr->content = &initStr; is incorrect for the same reason: you should allocate memory for the string too or possibly modify the TNodeDef to make content a string object instead of a pointer.
Function BVSInsert_function does not return the updated root pointer, hence the caller's root node is never updated. You could change the API, passing the address of the pointer to be updated.
There is also a confusion in BVSInsert_function: it should call itself recursively when walking down the tree instead of calling BVSCreate_function.
Here is a modified version:
/* Allocate the node and return 1 if successful, -1 on failure */
int BVSCreate_function(TNodef **rootPtr, function_save token) {
TNodef *newPtr = malloc(sizeof(*newPtr));
string *newStr = malloc(sizeof(*content));
if (newPtr == NULL || newStr == NULL) {
fprintf(stderr, "99");
free(newPtr);
free(newStr);
return -1;
}
newStr->str = NULL;
newStr->length = 0;
newStr->alloc = 0;
newPtr->content = newStr;
newPtr->leftPtr = NULL;
newPtr->rightPtr = NULL;
newPtr->return_type = token.ret_value;
newPtr->parameters = token.param_count;
strCpyStr(newPtr->content, token.content);
*rootPtr = newPtr;
return 1;
}
int BVSInsert_function(TNodef **rootPtr, function_save token) {
if (*rootPtr == NULL) {
return BVSCreate_function(rootPtr, token);
} else {
if (strCmpStr(token.content, rootPtr->content) < 0) {
return BVSInsert_function(&rootPtr->leftPtr, token);
} else
if ((strCmpStr(token.content, rootPtr->content)) > 0) {
return BVSInsert_function(&rootPtr->rightPtr, token);
} else {
/* function is already present: return 0 */
return 0;
}
}
}
Note also that function strCpyStr may write beyond the end of the allocated area is len2 == s1->alloc, assuming s1->len is the length of the string, excluding the null terminator.
Here is a modified version:
int strCpyStr(string *s1, const string *s2) {
int len2 = s2->length;
if (len2 >= s1->alloc) {
char *newstr = (char *)realloc(s1->str, len2 + 1);
if (newstr == NULL) {
return 1;
}
s1->str = newstr;
s1->alloc = len2 + 1;
}
strcpy(s1->str, s2->str);
s1->length = len2;
return 0;
}
I'm trying to write a code that uses linked lists and files, to maintain actions (functions) that are given on a text file, instead of receiving them from the user.
For some reason i'm encountering an error which says:
"Severity Code Description Project File Line Suppression State
Error C2040 'rename': 'hw_component *(char *,char *,hw_component *)' differs in levels of indirection from 'int (const char *,const char *)' EX5_313410961 c:\users\edave\source\repos\ex5_313410961\ex5_313410961\shahar_connection.c 172"
I'm having trouble understanding if the problem is the actual function rename() or because of the actions() function.
The code is very long so ill post the relevant section only.
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define NAME_LENGTH 200
typedef struct hw_component
{
char name[NAME_LENGTH];
int copies;
struct hw_component *next;
}hw_component;
hw_component *create_component(char* name,int copies)
{
if (name != NULL && strlen(name) > NAME_LENGTH)
return NULL;
hw_component *comp = (hw_component*)malloc(sizeof(hw_component));
if (comp == NULL)
{
printf("Error: memory allocation failed\n");
return NULL;
}
strcpy(comp->name, name);
comp->copies = copies;
comp->next = NULL;
return comp;
}
hw_component *add_sort(hw_component* head, int copies, char *name)
{
hw_component *iter, *prev = NULL;
hw_component *new_comp = create_component(name, copies);
if (head == NULL)
return new_comp;
if (strcmp(new_comp->name, head->name) < 0)
{
new_comp->next = head;
return new_comp;
}
iter = head;
while (iter != NULL && strcmp(iter->name, new_comp->name) < 0)
{
prev = iter;
iter = iter->next;
}
prev->next = new_comp;
new_comp->next = iter;
return head;
}
hw_component *initialize(char *argv[])
{
hw_component *list_of_comp = NULL;
FILE *fp = NULL;
char dolar[2] = "$";
fp = fopen(argv[1],"r");
if (fp == NULL)
{
printf("Error: opening %s failed\n", argv[1]);
exit(1);
}
while (!feof(fp))
{
char str[400], *token, *str_num;
fgets(str, 400, fp);
int numb;
token = strtok(str,dolar);
str_num = strtok(NULL, dolar);
numb = atoi(str_num);
list_of_comp=add_sort(list_of_comp, numb, token);
}
fclose(fp);
return list_of_comp;
}
void finalize(hw_component *head, char *argv[])
{
hw_component *temp;
FILE *fp = NULL;
int temp_num;
char *str,*num_str;
fp = fopen(argv[3], "w");
if (fp==NULL)
{
printf("Error: opening %s failed\n", argv[3]);
while (head!=NULL)
{
temp = head;
head = head->next;
free(temp);
}
}
while (head!=NULL)
{
temp = head;
fprintf(fp,"%s $$$ %d\n",temp->name,temp->copies);
head = temp->next;
free(temp);
}
fclose(fp);
}
hw_component *remove_comp_by_name(hw_component *head_comp, char comp_name[NAME_LENGTH + 1])
{
hw_component *temp_ptr = head_comp;
hw_component *prev_ptr;
hw_component *zero_copies_check = head_comp;
if (head_comp == NULL)
{
return head_comp;
}
if (strcmp(temp_ptr->name, comp_name) == 0)
{
head_comp = head_comp->next;
free(temp_ptr);
return head_comp;
}
while (temp_ptr != NULL && strcmp(temp_ptr->name, comp_name) != 0)
{
prev_ptr = temp_ptr;
temp_ptr = temp_ptr->next;
}
if (temp_ptr != NULL)
{
prev_ptr->next = temp_ptr->next;
free(temp_ptr);
}
while (zero_copies_check != NULL)
{
if (zero_copies_check->copies == 0)
{
free(zero_copies_check);
}
zero_copies_check = zero_copies_check->next;
}
return head_comp;
}
hw_component *rename(char old_name[NAME_LENGTH], char new_name[NAME_LENGTH], hw_component *head_comp)
{
hw_component *temp_comp = head_comp;
int num_of_copies = 0;
if (head_comp == NULL)
{
return head_comp;
}
while (temp_comp != NULL && strcmp(temp_comp->name, old_name) != 0)
{
temp_comp = temp_comp->next;
}
num_of_copies = temp_comp->copies;
head_comp=remove_comp_by_name(head_comp, old_name);
head_comp=add_sort(head_comp, num_of_copies, new_name);
return head_comp;
}
hw_component *return_comp(hw_component *head, char name_of_comp[], int copies)
{
hw_component *temp_comp = head;
if (head == NULL)
{
return head;
}
while (temp_comp != NULL && strcmp(temp_comp->name, name_of_comp) != 0)
{
temp_comp = temp_comp->next;
}
if (temp_comp != NULL)
{
temp_comp->copies += copies;
}
else
{
add_sort(head, name_of_comp, copies);
}
return head;
}
int choose_act(char *str)
{
char init[12] = "Initialize ", rename[8]="Rename ",fire[6]="Fire ";
char retu[24] = "Returned_from_customer ", prod[12]="Production " ,fatal[19]="Fatal_malfunction ";
char finalize[] = "Finalize";
if (strcmp(str,init)==0)
return 1;
if (strcmp(str, rename)==0)
return 2;
if (strcmp(str, retu)==0 || strcmp(str, prod)==0)
return 3;
if (strcmp(str, fire)==0 || strcmp(str, fatal)==0)
return 4;
if (strcmp(str, finalize)==0)
return 5;
}
void actions(char *argv[])
{
char dolar[2] = "$";
hw_component *head;
FILE *fp = NULL;
char str[400], *token, *name, *old_name;
int choise = 0, numb;
fp = fopen(argv[2], "r");
if (fp == NULL)
{
printf("Error: opening %s failed\n", argv[2]);
exit(1);
}
while (!feof(fp))
{
fgets(str, 400, fp);
token = strtok(str,dolar);
choise = choose_act(token);
head = initialize(argv);
switch (choise)
{
case 1:
break;
case 2:
old_name = strtok(str, dolar);
name = strtok(str, dolar);
printf("%s %s", old_name, name);
head=rename(old_name,name,head);
break;
case 3:
name = strtok(str, dolar);
numb = atoi(strtok(str, dolar));
head=return_comp(head, name, numb);
break;
case 4:
name = strtok(str, dolar);
numb = atoi(strtok(str, dolar));
head=fatal_maf(head, name, numb);
break;
case 5:
finalize(head,argv);
break;
default:
break;
}
}
}
int check_argc(int argc)
{
int numb = argc;
if (argc != 3)
{
printf("Error: invalid number of arguments (<%d> instead of 3)\n", numb);
return 0;
}
return 1;
}
int main(int argc, char *argv[])
{
int res = 0;
res=check_argc(argc);
if (res == 1)
actions(argv);
return 0;
}
You library already defines a function called rename(), which is prototyped in and included by adding stdio.h, which is creating the conflict with your user-defined function.
As per the lined manual, the signature of the library-defined rename() is int rename (const char *, const char*), whereas as er your function definition, you have a signature as hw_component *rename(char *, char *, hw_component *) - which does not match and your compiler is showing you correct warning (and error) message.
Solution: Use a different name for your function.
You cannot name your custom function rename while including stdio.h, because the name collides with the standard library function rename. Name your own function something different.
The standard function is
int rename(const char *old, const char *new);
So it has type int (const char *, const char *), the same type that the compiler is complaining about a conflict with.
I am writing a function to read from a text file and extract the strings word by word and store them to a binary search tree. The function should ignore all punctuations and discard duplicate words(only adds to the word frequency).
My problem with the code now is that every time "while (fscanf(fp, "%s", line)!=EOF)" runs, my rootWord gets replaced by the newly read word. I cannot figure out how is it possible for fscanf to be able to do this.
typedef struct word * wordPtr;
typedef struct position * positionPtr;
typedef struct position
{
int position;
positionPtr nextPosition;
} Position;
typedef struct word
{
char * word;
unsigned freq;
positionPtr firstPosition;
wordPtr leftWord;
wordPtr rightWord;
} Word;
typedef struct bstWord
{
wordPtr rootWord;
unsigned wordCount;
} BSTWord;
int BSTCreate(BSTWord* bst, char* fileName)
{
FILE * fp = fopen(fileName,"r");
char line[MAX_WORD_LEN + 1];
int charCount = 0;
char * token;
char delimit[] = "\t\r\n\v\f,.-;:\"\' ";
while (fscanf(fp, "%s", line)!=EOF)
{
wordPtr prev = NULL, curr = bst->rootWord;
wordPtr newWord;
positionPtr newPosition;
int lessThen;
int status = 1;
token = strtok(line, delimit);
charCount = charCount + 1;
while(curr!=NULL)
{
prev = curr;
if(strcmp(token, curr->word)<0)
{
printf("\nless");
lessThen = 1;
curr = curr->leftWord;
status = 1;
}
else if(strcmp(token, curr->word)>0)
{
printf("\nmore");
lessThen = 0;
curr = curr->rightWord;
status = 1;
}
else if(strcmp(token, curr->word)==0) //If word is already in tree, add freq + update position
{
if ( ( newPosition = malloc( sizeof( Position ) ) ) == NULL )
return FAILURE;
newPosition->position = charCount;
newPosition->nextPosition = NULL;
positionPtr prevPosition = NULL, currPosition = curr->firstPosition;
while(currPosition!=NULL)
{
prevPosition = currPosition;
currPosition = currPosition->nextPosition;
}
prevPosition->nextPosition = newPosition;
status = 0;
curr = NULL;
break;
}
}
if(status == 1)
{
if ( ( newWord = malloc( sizeof( Word ) ) ) == NULL )
return FAILURE;
if ( ( newPosition = malloc( sizeof( Position ) ) ) == NULL )
return FAILURE;
newPosition->position = charCount;
newWord->word = token;
newWord->freq = 1;
newWord->firstPosition = newPosition;
newWord->leftWord = NULL;
newWord->rightWord = NULL;
if(bst->rootWord == NULL)
bst->rootWord = newWord;
else
{
if(lessThen)
{
prev->leftWord = newWord;
}
else
{
prev->rightWord = newWord;
}
}
}
bst->wordCount++;
}
fclose(fp);
free(fp);
return SUCCESS;
}
newWord->word = token;
Every token points to the same memory you allocated at:
char line[MAX_WORD_LEN + 1];
You need to allocate additional memory and copy the string there:
newword->word = malloc(strlen(token) + 1);
strcpy(newword->word, token);
The problem is when I try to print the values of
(*names)[*number], I get only the last one stored.
I'll explain what I mean with an example — what I want is this:
(*names)[0] = "john"
(*names)[1] = "bill"
(*names)[2] = "nick"
and what I get when I print the values of (*names)[*number] is this:
(*names)[0] = "nick"
(*names)[1] = "nick"
(*names)[2] = "nick"
Here is the code:
int GetFiles(char **dir,char ***names,int *number)
{
struct dirent *dp;
DIR *fd;
int i;
if ((fd = opendir(*dir)) == NULL)
{
printf("Can't open directory %s!\n",*dir);
return 0;
}
*number = 0;
//*names = (char**)malloc(((*number)+1) * sizeof(char*));
*names = (char**)malloc(17*sizeof(char*));
while ((dp = readdir(fd)) != NULL)
{
if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, ".."))
{
continue;
}
(*names)[*number] = dp->d_name;
(*number)++;
//*names = (char**)realloc(*names,((*number)+1) * sizeof(char*));
}
closedir(fd);
for(i=0;i<*number;i++)
{
printf("--%s\n",(*names)[i]);
}
system("PAUSE");
return 1;
}
I want to print the data between tags from a text file using C.
Input statement :
<PERSON> Mark Zuckerberg </PERSON> is a entrepreneur from <LOCATION> USA </LOCATION>. He is also the CEO of <ORGANIZATION> Facebook </ORGANIZATION>.
Output: Mark Zuckerberg USA Facebook.
My Program code is :
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, "/>");
tok && *tok;
tok = strtok(NULL, ">"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
char line[500000];
while (fgets(line, 500000, stdin))
{
char *arg = line;
const char *tok;
while ((tok = getfield(arg, 2)) != NULL) {
printf("%s\n", tok);
arg = NULL;
}
}
}
My output is :
Mark Zuckerberg </PERSON
USA </LOCATION
Facebook </ORGANIZATION
I want to get rid of </Tag and get only Mark Zuckerberg USA Facebook as output. Where do I need to change the code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getfield(char **sp){
char *left; //point to <
char *right;//point to >
if((left = strchr(*sp, '<')) == NULL)
return NULL;
if((right = strchr(left, '>')) == NULL)
return NULL;
size_t len = right - left;//if len == 1, tag is nothing(<>)
char *tag = malloc(len);
memcpy(tag, left + 1, len -1);
tag[len-1] = '\0';
char *etag = malloc(len + 3);
sprintf(etag, "</%s>", tag);
left = right + 1;
if((right = strstr(left, etag)) == NULL)//right point to end tag
{
free(tag);
free(etag);
return NULL;
}
len = right - left;
char *text = malloc(len + 1);
memcpy(text, left, len);
text[len] = '\0';
*sp = right + strlen(etag);
free(tag);
free(etag);
return text;
}
int main(void){
char line[500000];
while (fgets(line, sizeof line, stdin)){
char *arg = line;
char *text;
while ((text = getfield(&arg)) != NULL){
printf("%s\n", text);
free(text);
}
}
return 0;
}