I am implementing a knowledge tree in c that can read from a file. I am getting a seg fault in my newStr function. I'm not able to test the rest of my code with this problem. I don't have much experience with c. Any help would be greatly appreciated.
my .c file
#include
#include
#include"animal.h"
#include
#include
/*returns a new node for the given value*/
struct Node * newNode (char *newValue)
{
struct Node * tree;
tree = (struct Node*)malloc(sizeof(struct Node));
tree -> value = newStr(newValue);
return tree;
}
/* returns a new string with value passed as an argument*/
char * newStr (char * charBuffer)
{
int i;
int length = strlen(charBuffer);
char newStr;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q'){
for(i=1; i<length; i++)
newStr += charBuffer[i];
}
return (newStr + "\0");
}
/*Read from a File and create a tree*/
struct Node * readATree(FILE * f)
{
char c;
char buffer[100];
struct Node * newTree;
c = fgetc(f);
if (c == 'A'){
fgets(buffer, 100, f);
newTree = newNode(buffer);
newTree -> left = NULL;
newTree -> right = NULL;
}
else{
fgets(buffer, 100, f);
newTree = newNode(newStr(buffer));
newTree->left = readATree(f);
newTree->right = (struct Node *) readAtree(f);
}
return newTree;
}
/*Write Tree to a File*/
void writeAFile(struct Node* tree, FILE * f)
{
char buffer[100];
strcpy(buffer, tree->value);
if(tree != 0){
if(tree->left == NULL && tree->right == NULL){
fputc((char)"A", f);
fputs(buffer,f);
} else{
fputc((char)"Q",f);
fputs(buffer,f);
writeAFile(tree->left, f);
writeAFile(tree->right,f);
}
}
}
/*The play should start from here*/
int main (){
struct Node* node;
struct Node* root;
char ans[100];
char q[100];
FILE * f;
f = fopen("animal.txt", "r+");
if(f != NULL)
readATree(f);
else{
node = newNode("Does it meow?");
node->right = NULL;
node->right->right=NULL;
node->left->left=NULL;
node->left=newNode("Cat");
root = node;
}
while(node->left != NULL && node->right != NULL){
printf(node->value);
scanf(ans);
if(ans[0] == (char)"Y" || ans[0] == (char)"y")
node = node->left;
else if(ans[0] == (char)"N" || ans[0] == (char)"n")
node = node->right;
else
printf("That is not a valid input.\n");
}
if(ans[0] == (char)"Y" || ans[0] == (char)"y")
printf("I win!");
else if(ans[0] == (char)"N" || ans[0] == (char)"n"){
printf("What is your animal");
scanf(ans);
printf("Please enter a yes or no question that is true about %s?\n", ans);
scanf(q);
node->right = newNode(q);
node->right->left = newNode(ans);
node->right->right = NULL;
}
writeAFile(root,f);
fclose(f);
return 0;
}
.h file
#include
struct Node {
char *value;
struct Node * left;
struct Node * right;
};
struct Node * newNode (char *newValue) ;
char * newStr (char * charBuffer);
struct Node * readATree(FILE * f);
void writeAFile(struct Node* tree, FILE * f);
There might be several more, but here's some points on what's wrong:
Your newStr function is just very,
very wrong. At a guess you'd want
something like:
char * newStr (char * charBuffer)
{
char *newStr;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q') {
newStr = strdup(&charBuffer[1]);
} else {
newStr = strdup("");
}
if(newStr == NULL) {
//handle error
}
return newStr;
}
You can't cast a string to a char
like you do here:
if(ans[0] == (char)"Y" || ans[0] == (char)"y")
Do instead(same for similar code
elsewhere too)
if(ans[0] =='Y' || ans[0] == 'y')
Same as above when you call putc,
don't do
fputc((char)"A", f);
Do
fputc('A', f);
scanf needs a format string, don't
do:
scanf(ans);
Do e.g. (or just use fgets again)
if(scanf("%99s",ans) != 1) {
//handle error
}
char * newStr (char * charBuffer)
{
int i;
int length = strlen(charBuffer);
char newStr;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q'){
for(i=1; i<length; i++)
newStr += charBuffer[i];
}
return (newStr + "\0");
}
Well, there's a few interesting things here... To get down to brass tacks, you're trying to copy the contents of a character pointer into another and this function isn't going to do that. All you're really doing is summing the value of each char in charBuffer into newStr because a char is really just an 8-bit integer and then you return that integer as a pointer through an implicit cast so it is now being treated as a memory address.
You should look to use strdup(), as has been noted, since this is exactly what the function is supposed to do. No need to reinvent the wheel. :)
"+" operator as string concatenation does not work in c.
If you actually want to copy the a string use strdup(). This function allocates memory and copies the string into it.
Don't forget to free the allocated memory when done using it.
Related
I am currently in the process of writing a program that acts as a circuit. I have a gate structure that takes a 2D char array in order to hold variable names, yet when I try to access these variable names stored in the array outside of the while loop, the content is empty.
typedef struct Gate
{
kind_t kind;
int size; // size of DECODER and MULTIPLEXER
char **params; // length determined by kind and size (CHANGED FROM INT TO CHAR)
// includes inputs and outputs, indicated by variable numbers
} Gate;
typedef struct Node
{
Gate *data;
struct Node *next;
} Node;
// Linked list of gates & attributes
while (fscanf(fp, "%16s", str) != EOF)
{
if (strcmp(str, "AND") == 0)
{
head = makeGate(fp, head, AND);
length++;
}
else if (strcmp(str, "OR") == 0)
{
head = makeGate(fp, head, OR);
length++;
}
else if (strcmp(str, "NAND") == 0)
{
head = makeGate(fp, head, NAND);
length++;
}
else if (strcmp(str, "NOR") == 0)
{
head = makeGate(fp, head, NOR);
length++;
}
else if (strcmp(str, "XOR") == 0)
{
head = makeGate(fp, head, XOR);
length++;
}
else if (strcmp(str, "NOT") == 0)
{
//head = makeGate(fp, head, NOT);
//length++;
}
else if (strcmp(str, "PASS") == 0)
{
//head = makeGate(fp, head, PASS);
//length++;
}
else if (strcmp(str, "DECODER") == 0)
{
//
}
else if (strcmp(str, "MULTIPLEXER") == 0)
{
//
}
printf("%s\n", head->data->params[2]);
}
// plugs in values to circuit
for (int i = 0; i < 3; i++)
{
printf("Stored string: %s\n", head->data->params[i]);
}
`
Node *makeGate(FILE *fp, Node *head, kind_t inGate)
{
char str[17];
Node *new_node = (Node *)malloc(sizeof(Node)); // Node of linkedlist that contains gate structure
new_node->data = (Gate *)malloc(sizeof(Gate)); // Gate structure that keeps information about a gate
new_node->next = head;
new_node->data->kind = inGate;
new_node->data->size = 3;
new_node->data->params = malloc(3 * sizeof(char*));
for (int i = 0; i < 3; i++)
{
new_node->data->params[i] = malloc(17 * sizeof(char));
}
fscanf(fp, "%16s", str);
new_node->data->params[0] = str;
fscanf(fp, "%16s", str);
new_node->data->params[1] = str;
fscanf(fp, "%16s", str);
new_node->data->params[2] = str;
return new_node;
}
`
The printf statement inside the while loop works perfectly fine and is there purely for testing, however the for loop that prints each value of the array is different and prints nothing.
I tried to fix this multiple times to no avail, I originally found this problem as I noticed that I had gotten memory leak, and when I freed where the memory leak should be, it throws that I am freeing a address that is not malloced.
My only thought is I am somehow losing/skipping a node, but I am out of ideas
The following does not copy data from str into the struct ( you'd need strcpy):
new_node->data->params[0] = str;
What it does is copy the address of str into each element. They all point to the same buffer/string. And, str goes out of scope when the function returns.
You can [and should] just scan into the struct directly.
So, change:
fscanf(fp, "%16s", str);
new_node->data->params[0] = str;
fscanf(fp, "%16s", str);
new_node->data->params[1] = str;
fscanf(fp, "%16s", str);
new_node->data->params[2] = str;
Into:
fscanf(fp,"%16s",new_node->data->params[0]);
fscanf(fp,"%16s",new_node->data->params[1]);
fscanf(fp,"%16s",new_node->data->params[2]);
I'm making a phonebook program with a binary search tree. Whenever I try to input a new data, the segmentation fault occurs. First, I have type definition structure which name is phoneData.
typedef struct phoneData {
char name[NAME_LEN];
char phoneNum[PHONE_LEN];
struct phoneData *right, *left;
} phoneData;
void InputPhoneData()
{ //phoneData *pData;
char name[NAME_LEN];
char phoneNum[PHONE_LEN];
/*if ((pData = (phoneData*)malloc(sizeof(phoneData))) == NULL) {
fprintf(stderr, "Memory Allocation failed\n");
return;
}*/
fputs("이름 입력: ", stdout);
if (fgetString(name, NAME_LEN, stdin) == 1) {
getchar();
return;
}
fputs("전화번호 입력: ", stdout);
if (fgetString(phoneNum, PHONE_LEN, stdin) == 1) {
getchar();
return;
}
insert_node(name, phoneNum);
numOfData++;
fputs("입력이 완료되었습니다.", stdout);
getchar();
}
And this is the function which I call to input a data. Please don't mind the Korean sentences. In the function, I call another function insert_node. This is the function which inserts the binary search tree node.
void insert_node(char name[], char phoneNum[])
{
phoneData *p, *t;
phoneData *n;
t = *root;
p = NULL;
while (t != NULL) {
if (strcmp(name, t->name) == 0)
return;
p = t;
if (strcmp(name, p->name) < 0)
t = p->left;
else
t = p->right;
}
n = (phoneData*)malloc(sizeof(phoneData));
if (n == NULL)
return;
strcpy(n->name, name);
strcpy(n->phoneNum, phoneNum);
n->left = n->right = NULL;
if (p != NULL) {
if (strcmp(p->name, name) < 0)
p->left = n;
else
p->right = n;
}
else
*root = n;
}
I'm still wondering which is the part that I'm getting a segmentation fault. I already checked the fgetString function, and it seems to be okay. Did I make any mistakes on InputPhoneData function or insert_node function?
And by the way, the variable 'root' is a global variable which is a double pointer initialized as NULL. (phoneData **root = NULL;)
That's your problem right there. *root will dereference a NULL pointer.
Change the declaration to:
phoneData *root = NULL;
and replace *root with root and root with &root in the rest of your code.
It will be easy, fun and interesting to debug such kind of issues.
Try to debug using gdb :)
You can check following link,
http://www.thegeekstuff.com/2010/03/debug-c-program-using-gdb
I am having an issue while deleting the vowel from a linked List. The program accept command line arguments, combines them in a single string and add each character to a linked list as node.
When i try to run the program with command line argument "lemon", the successfully deletes the vowels. i.e the program deletes the vowels successfully if the argument doesn't contain consequetive vowels.
On the other hand, if i try to do the same with command line argument "aeiou", the program crashes with message Segmentation fault(core dumped).. I am not getting any idea how to handle this..
The program must not create any global variables so i've used double pointer.
All the functions are working properly this problem may have occured due to some mistakes in locate() and removeVowels() function but i cannot figure out what the mistake is.
can this problem be solved using double pointer??
I cannot figure out what is wrong in this program.. I am new to c programming, please help me with this.. Please rectify me..
Thanks in advance.
The complete code is given below:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
struct linkedList {
char ch;
struct linkedList *node;
};
void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locate(struct linkedList**);
int delHead(struct linkedList **);
void removeVowels(struct linkedList**);
int isEmpty(struct linkedList **);
int main(int argc, char *argv[]) {
int choice, indexer = 0;
struct linkedList *s;
char *string;
if (argc == 1) {
printf("Parse a sentence");
} else {
s = (struct linkedList *) malloc(sizeof(struct linkedList));
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, &indexer);
while (1) {
printMenu();
scanf("%d", &choice);
if (choice == 1) {
printLinkedList(&s);
} else if (choice == 2) {
if (!delHead(&s))
printf("Failed.Empty linked list");
} else if (choice == 3) {
removeVowels(&s);
} else if (choice == 4) {
if(isEmpty(&s)){
printf("Empty LinkedList");
}
else
printf("Not Empty");
} else if (choice == 5) {
break;
} else
printf("Invalic choice");
printf("\n");
}
}
return 0;
}
int isEmpty(struct linkedList **s){
if(*s == NULL)
return 1;
else
return 0;
}
struct linkedList *locate(struct linkedList **s) {
if ((*s)->node->ch == 'a' || (*s)->node->ch == 'e' || (*s)->node->ch == 'i'
|| (*s)->node->ch == 'o' || (*s)->node->ch == 'u'
|| (*s)->node->ch == 'A' || (*s)->node->ch == 'E'
|| (*s)->node->ch == 'I' || (*s)->node->ch == 'O'
|| (*s)->node->ch == 'U') {
return *s;
} else if ((*s)->node->node == NULL) {
return NULL;
} else
return locate(&((*s)->node));
}
void removeVowels(struct linkedList **s) {
struct linkedList *temp, *tag;
/* Checking whether the first node is null or not */
if ((*s)->ch == 'a' || (*s)->ch == 'e' || (*s)->ch == 'i'
|| (*s)->ch == 'o' || (*s)->ch == 'u'
|| (*s)->ch == 'A' || (*s)->ch == 'E'
|| (*s)->ch == 'I' || (*s)->ch == 'O'
|| (*s)->ch == 'U')
delHead(s);
do {
tag = locate(s);
if (tag != NULL) {
temp = tag->node->node;
free(tag->node);
tag->node = temp;
}
} while (tag != NULL);
}
int delHead(struct linkedList **s) {
struct linkedList *temp;
if ((*s) == NULL) {
return 0;
} else {
temp = (*s)->node;
free(*s);
*s = temp;
return 1;
}
}
void printLinkedList(struct linkedList **s) {
if ((*s) != NULL) {
printf("%c", (*s)->ch);
printLinkedList(&(*s)->node);
}
return;
}
void addTolinkedList(char *str, struct linkedList **s, int *indexer) {
if (*indexer == strlen(str)) {
*s = NULL;
return;
} else {
(*s)->ch = *(str + *indexer);
(*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
++*indexer;
addTolinkedList(str, &(*s)->node, indexer);
}
}
char * combineWithNoSpaces(int argc, char *argv[]) {
int i, j;
int count = 0;
int memory = 0;
char *str;
for (i = 1; i < argc; i++) {
for (j = 0; j < strlen(argv[i]); j++) {
++memory;
}
}
str = (char *) malloc(memory * sizeof(char) + 1);
for (i = 1; i < argc; i++) {
for (j = 0; j < strlen(argv[i]); j++) {
*(str + count) = argv[i][j];
++count;
}
}
return str;
}
void printMenu(void) {
printf("\n\n"
"1. print input arguments (no spaces)\n"
"2. remove first character\n"
"3. remove vowels\n"
"4. is the linked list empty?\n"
"5. exit program\n"
"Enter your choice>");
}
The screen shot for output is :
For argument lemon
For argument aeiou
This code works to my satisfaction. It is more nearly an MCVE (Minimal, Complete, Verifiable Example.
I called the program rv19. When run like this, it gives the output shown:
$ rv19 apple
[apple]
[ppl]
$ rv19 nutmeg
[nutmeg]
[ntmg]
$ rv19 ply
[ply]
[ply]
$ rv19 aeiou
[aeiou]
[]
$ rv19 aardvark abstemiously facetiously aeiou minions lampoon shampoo
[aardvarkabstemiouslyfacetiouslyaeiouminionslampoonshampoo]
[rdvrkbstmslyfctslymnnslmpnshmp]
$
The code (rv19.c):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct linkedList
{
char ch;
struct linkedList *node;
};
char *combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int *);
void printLinkedList(struct linkedList **);
struct linkedList *locate(struct linkedList **);
int delHead(struct linkedList **);
void removeVowels(struct linkedList **);
void freeLinkedList(struct linkedList *);
int main(int argc, char *argv[])
{
int indexer = 0;
struct linkedList *s;
char *string;
if (argc == 1)
{
printf("Parse a sentence. Usage: %s word [word ...]\n", argv[0]);
}
else
{
s = (struct linkedList *) malloc(sizeof(struct linkedList));
printf("s = %p\n", (void *)s);
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, &indexer);
printLinkedList(&s);
removeVowels(&s);
printLinkedList(&s);
printf("s = %p\n", (void *)s);
freeLinkedList(s);
free(string);
}
return 0;
}
static inline int isvowel(char c)
{
return(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' ||
c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U');
}
struct linkedList *locate(struct linkedList **s)
{
if ((*s)->node == NULL)
return NULL;
if (isvowel((*s)->node->ch))
{
return *s;
}
else if ((*s)->node == NULL)
{
return NULL;
}
else
return locate(&((*s)->node));
}
void removeVowels(struct linkedList **s)
{
struct linkedList *temp, *tag;
/* Remove leading vowels */
while ((*s) != NULL && isvowel((*s)->ch))
{
//printf("Remove leading '%c'\n", (*s)->ch);
struct linkedList *ts = *s;
delHead(&ts);
*s = ts;
}
struct linkedList *n = *s;
while (n != NULL && (tag = locate(&n)) != NULL)
{
/* Remove multiple embedded or trailing vowels */
while (tag->node != NULL && isvowel(tag->node->ch))
{
temp = tag->node;
tag->node = tag->node->node;
free(temp);
}
n = tag->node;
}
}
int delHead(struct linkedList **s)
{
struct linkedList *temp;
if ((*s) == NULL)
return 0;
else
{
temp = (*s)->node;
free(*s);
*s = temp;
return 1;
}
}
void printLinkedList(struct linkedList **s)
{
struct linkedList *n = *s;
putchar('[');
while (n != NULL)
{
putchar(n->ch);
n = n->node;
}
putchar(']');
putchar('\n');
}
void addTolinkedList(char *str, struct linkedList **s, int *indexer)
{
if (*indexer == (int)strlen(str))
{
free(*s);
*s = NULL;
}
else
{
(*s)->ch = *(str + *indexer);
(*s)->node = (struct linkedList *) malloc(sizeof(struct linkedList));
++*indexer;
addTolinkedList(str, &(*s)->node, indexer);
}
}
char *combineWithNoSpaces(int argc, char *argv[])
{
int argl[argc+1];
int memory = 0;
for (int i = 1; i < argc; i++)
{
argl[i] = strlen(argv[i]);
memory += argl[i];
}
char *str = (char *) malloc(memory + 1);
char *base = str;
for (int i = 1; i < argc; i++)
{
strcpy(base, argv[i]);
base += argl[i];
}
return str;
}
void freeLinkedList(struct linkedList *node)
{
while (node != NULL)
{
struct linkedList *next = node->node;
free(node);
node = next;
}
}
This is still not as polished as it could be. I changed the printing so as to get a marker before the start and after the end of the output; it is easier to see unwanted blanks and other characters like that. It's now iterative. I'd change the interface to the function, too, so it takes a struct linkedList * instead of a struct linkedList **. The code in removeVowels() is tricky; it iterates to remove repeated initial vowels; it iterates to remove repeated vowels after a non-vowel. The locate() function now returns a pointer to a non-vowel node that has a vowel in the next node. This code frees both the string and the list (using a new function, freeLinkedList() to free the list).
I've checked it with a couple of debugging versions of malloc(), and it seems to be leak free and corruption free.
I still haven't run it with valgrind because I can't get it to run properly after building it on macOS Sierra 10.12:
valgrind: mmap-FIXED(0x0, 253952) failed in UME (load_segment1) with error 12 (Cannot allocate memory).
This was with the latest code downloaded from SVN (revision 16097).
I tried to simplify all the functions -- some were taking (pointers to) pointers as arguments when they needn't do so.
A few highlights of the many changes:
main: changed the main control structure to a switch statement. Initialized the linkedList pointer to NULL instead of a malloc'd one as entering an empty string would cause addTolinkedList() to leak this memory. Added a call to new function freeLinkedList() when the exit option is selected.
locate: renamed this locateVowel() and restructured with removeVowel() to have only one place that actually looks for vowels. Removed potential memory leak.
combineWithNoSpaces: rewrote this to be string oriented instead of character oriented.
addTolinkedList: made the index(er) argument a simple int that gets incremented on recursion which simplified a number of issues.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
struct linkedList {
char ch;
struct linkedList *node;
};
void printMenu(void);
char* combineWithNoSpaces(int, char *[]);
void addTolinkedList(char *, struct linkedList **, int);
void printLinkedList(struct linkedList *);
struct linkedList **locateVowel(struct linkedList **);
bool delHead(struct linkedList **);
void removeVowels(struct linkedList **);
bool isEmpty(struct linkedList *);
void freeLinkedList(struct linkedList *);
int main(int argc, char *argv[]) {
int choice;
char *string;
if (argc == 1) {
fprintf(stderr, "Enter a sentence\n");
return EXIT_FAILURE;
}
struct linkedList *s = NULL;
string = combineWithNoSpaces(argc, argv);
addTolinkedList(string, &s, 0);
free(string);
while (true) {
printMenu();
(void) scanf("%d", &choice);
printf("\n");
switch (choice) {
case 1:
printLinkedList(s);
break;
case 2:
if (!delHead(&s)) {
printf("Failed. Empty linked list\n");
}
break;
case 3:
removeVowels(&s);
break;
case 4:
if (isEmpty(s)) {
printf("Empty LinkedList\n");
} else {
printf("Not Empty\n");
}
break;
case 5:
freeLinkedList(s);
return EXIT_SUCCESS;
default:
printf("Invalid choice\n");
}
}
return EXIT_SUCCESS;
}
bool isEmpty(struct linkedList *s) {
return (s == NULL);
}
struct linkedList **locateVowel(struct linkedList **s) {
if (*s == NULL) {
return NULL;
}
char ch = tolower((*s)->ch);
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u') {
return s;
}
return locateVowel(&((*s)->node));
}
void removeVowels(struct linkedList **s) {
struct linkedList **vowel;
while ((vowel = locateVowel(s)) != NULL) {
struct linkedList *temporary = (*vowel)->node;
if (temporary == NULL) {
free(*vowel); // a vowel with nothing following it
*vowel = NULL;
break;
}
(*vowel)->ch = temporary->ch;
(*vowel)->node = temporary->node;
free(temporary);
s = vowel;
}
}
bool delHead(struct linkedList **s) {
if (*s == NULL) {
return false;
}
struct linkedList *temporary = (*s)->node;
free(*s);
*s = temporary;
return true;
}
void printLinkedList(struct linkedList *s) {
printf("\"");
while (s != NULL) {
printf("%c", s->ch);
s = s->node;
}
printf("\"\n");
}
void addTolinkedList(char *string, struct linkedList **s, int index) {
if (index == strlen(string)) {
*s = NULL;
} else {
*s = malloc(sizeof(struct linkedList));
(*s)->ch = string[index];
(*s)->node = NULL;
addTolinkedList(string, &(*s)->node, index + 1);
}
}
char *combineWithNoSpaces(int argc, char *argv[]) {
int characters = 0;
for (int i = 1; i < argc; i++) {
characters += strlen(argv[i]);
}
char *string = calloc(characters + 1, 1);
for (int i = 1; i < argc; i++) {
(void) strcat(string, argv[i]);
}
return string;
}
void freeLinkedList(struct linkedList *s) {
while (s != NULL) {
struct linkedList *temporary = s;
s = s->node;
free(temporary);
}
}
void printMenu(void) {
printf("\n"
"1. print string (no spaces)\n"
"2. remove first character\n"
"3. remove vowels\n"
"4. is the linked list empty?\n"
"5. exit program\n"
"Enter your choice: ");
}
i have to count how many times a word exists in the binary tree and i couldn't do this ,how can i do this? here is my code ;
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct treeNode
{
char data[20];
int count;
struct treeNode *leftPtr, *rightPtr;
};
int number = 1;
typedef struct treeNode TreeNode;
typedef TreeNode *TreeNodePtr;
void insertNode(TreeNodePtr *treePtr, char word[]);
void alphabetic(TreeNodePtr treePtr);
int main()
{
/*reading strings from the file and add them to the tree*/
char first[20];
FILE *fp1;
TreeNodePtr rootPtr = NULL;
int c;
fp1 = fopen("output.txt", "r");
do
{
c = fscanf(fp1, "%s", first);
if (c != EOF)
{
insertNode(&rootPtr, first);
}
} while (c != EOF);
fclose(fp1);
printf("%s", rootPtr->rightPtr->leftPtr->data);
//alphabetic(rootPtr);
system("PAUSE");
}
/*for adding nodes to tree*/
void insertNode(TreeNodePtr *treePtr, char word[20])
{
TreeNode *temp = NULL;
if (*treePtr == NULL )
{
temp = (TreeNode *) malloc(sizeof(TreeNode));
temp->leftPtr = NULL;
temp->rightPtr = NULL;
strcpy(temp->data, word);
*treePtr = temp;
}
else if (strcmp(word, (*treePtr)->data) < 0)
{
insertNode(&((*treePtr)->leftPtr), word);
}
else if (strcmp(word, (*treePtr)->data) > 0)
{
insertNode(&((*treePtr)->rightPtr), word);
}
}
/*traverse the tree*/
void alphabetic(TreeNodePtr treePtr)
{
if (treePtr != NULL )
{
alphabetic(treePtr->leftPtr);
printf("%s\n", treePtr->data);
alphabetic(treePtr->rightPtr);
}
}
i have a .txt file which contains some words more than once,and i need to count how many times a word exists in this tree.
Your code does not "work" because you are not inserting duplicate values. Since the duplicate values would return strcmp() as 0, they are not being added in the first place. Thus in the insertNode() function, you would need to consider the else case as well:
else if (strcmp(word, (*treePtr)->data) < 0) {
insertNode(&((*treePtr)->leftPtr), word);
} else if (strcmp(word, (*treePtr)->data) > 0) {
insertNode(&((*treePtr)->rightPtr), word);
} else {
//This is where the duplcate values should be inserted!
}
In fact, the else clause should simply increment the count as in (as in "(*treePtr)->count += 1;"). Also, make sure you initialize the value to 1 in the initial temp structure after you malloc the TreeNode (as in "temp->count = 1;").
This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Seg Fault in Knowledge Tree
I can't pinpoint my seg fault in my information tree. It is supposed to read from file or get user input if the file does not exist. It's supposed to guess the animal based on yes or no questions. I have limited experience with c so any help would be greatly appreciated.
.c file
#include<stdio.h>
#include<stdlib.h>
#include"animal.h"
#include<string.h>
#include<assert.h>
/*returns a new node for the given value*/
struct Node * newNode (char *newValue)
{
printf("Node test");
struct Node * tree;
tree = (struct Node*)malloc(sizeof(struct Node));
tree -> value = newStr(newValue);
printf("Node test");
return tree;
}
/* returns a new string with value passed as an argument*/
char * newStr (char * charBuffer)
{
printf("Str test");
char *newstr;
if(charBuffer[0] == 'A' || charBuffer[0] == 'Q'){
newstr = strdup(&charBuffer[1]);
}else{
newstr = strdup("");
}
return newstr;
}
/*Read from a File and create a tree*/
struct Node * readATree(FILE * f)
{
printf("ReadATree test");
char c;
char buffer[100];
struct Node * newTree;
c = fgetc(f);
if (c == 'A'){
fgets(buffer, 100, f);
newTree = newNode(newStr(buffer));
newTree -> left = NULL;
newTree -> right = NULL;
}
else{
fgets(buffer, 100, f);
newTree = newNode(newStr(buffer));
newTree->left = readATree(f);
newTree->right = (struct Node *) readATree(f);
}
return newTree;
}
/*Write Tree to a File*/
void writeAFile(struct Node* tree, FILE * f)
{
printf("WriteFile test");
char buffer[100];
strcpy(buffer, tree->value);
if(tree != 0){
if(tree->left == NULL && tree->right == NULL){
fputc('A', f);
fputs(buffer,f);
} else{
fputc('Q',f);
fputs(buffer,f);
writeAFile(tree->left, f);
writeAFile(tree->right,f);
}
}
}
/*The play should start from here*/
int main (){
printf("main test");
struct Node* node;
struct Node* root;
char ans[100];
char q[100];
FILE * f;
f = fopen("animal.txt", "r+");
if(f != NULL)
readATree(f);
else{
node = newNode("Does it meow?");
node->right = NULL;
node->right->right=NULL;
node->left->left=NULL;
node->left=newNode("Cat");
root = node;
}
while(node->left != NULL && node->right != NULL){
printf(node->value);
scanf(ans);
if(ans[0] == 'Y' || ans[0] == 'y')
node = node->left;
else if(ans[0] == 'N' || ans[0] == 'n')
node = node->right;
else
printf("That is not a valid input.\n");
}
if(ans[0] == 'Y' || ans[0] == 'y')
printf("I win!");
else if(ans[0] == 'N' || ans[0] == 'n'){
printf("What is your animal?\n");
scanf("%s",ans);
printf("Please enter a yes or no question that is true about %s?\n", ans);
scanf("%s",q);
node->right = newNode(q);
node->right->left = newNode(ans);
node->right->right = NULL;
}
writeAFile(root,f);
fclose(f);
return 0;
}
.h
#include<stdio.h>
struct Node {
char *value;
struct Node * left;
struct Node * right;
};
struct Node * newNode (char *newValue) ;
char * newStr (char * charBuffer);
struct Node * readATree(FILE * f);
void writeAFile(struct Node* tree, FILE * f);
Don't force the good people of SO to wade through and debug your code! Also, don't keep repeating your question. The reason it wasn't answered to your satisfaction earlier is that people were unwilling to compensate for your laziness.
That's what debuggers are for. Run your code in a debugger, and it will tell you when you're accessing a null pointer.
If you don't have a debugger, throw a bunch of print statements into your program. If you run your program, the last printout before the crash will be just above the place where your segmentation fault occurred. You may want to add even more print statements near that point, perhaps dumping out some pointer values.
From a cursory glance at the code:
node->right = NULL;
node->right->right=NULL;
The second line here will access a NULL pointer, which will cause a segfault.
In general, running the code in a debugger will let you see which line caused the error.
I'm guessing that these warnings are a clue:
animal.c: In function ‘main’:
animal.c:95: warning: format not a string literal and no format arguments
animal.c:96: warning: format not a string literal and no format arguments