I've got a problem with reading words from file and passing it to binary tree. When I debug it, it says:
Unhandled exception at 0x76E7773B(ntdll.dll) in Projekt.exe: 0.C00000005:
Access violation reading location 0x0037902A.
Here is the source code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
typedef struct Tree {
int val;
char *word;
struct Tree *left;
struct Tree *right;
} Tree;
void show(Tree *hd) {
if (hd != NULL) {
show(hd->left);
show(hd->right);
printf("%s -- %d\n", hd->word, hd->val);
}
}
void zero(Tree *aTree) {
if (aTree == NULL)
return;
zero(aTree->left);
free(aTree);
zero(aTree->right);
}
int alpha(char *word1, char *word2) {
if (word1[0] == 0 && word2[0] == 0)
return 2;
else
if (word1[0] == word2[0])
return alpha(&word1[1], &word2[1]);
else
if (word1[0] < word2[0])
return 1;
else
return 0;
}
Tree *create(char *word) {
Tree *temp;
temp = (Tree*)malloc(sizeof(Tree));
temp->left = temp->right = NULL;
temp->val = 1;
temp->word = (char*)malloc(sizeof(char));
strcpy(temp->word, word);
return temp;
}
Tree *insert(Tree *aTree, char *word) {
if (aTree == NULL) {
aTree = create(word);
} else
if (alpha(aTree->word, word) == 0) {
aTree->left = insert(aTree->left,word);
} else
if (alpha(aTree->word, word) == 1) {
aTree->right = insert(aTree->right, word);
} else
if (alpha(aTree->word, word) == 2) {
aTree->val++;
}
return aTree;
}
int main(int argc, char *argv[]) {
Tree *myTree = NULL;
char buffer[256] = { 0 };
char temp = 0;
int i = 0;
FILE *fp = fopen(argv[1], "r");
if (fp) {
while (temp != EOF) {
temp = getc(fp);
temp = toupper(temp);
if (temp >= 65 && temp <= 90) {
buffer[i] = temp;
i++;
} else {
if (buffer[0] != 0) {
puts(buffer);
myTree = insert(myTree, buffer);
memset(buffer, 0, sizeof(buffer));
i = 0;
}
}
}
}
fclose(fp);
show(myTree);
return 0;
}
Your program has several problems:
in function zero
, you free the pointer too soon, you should move the free(aTree);
as the last statement, otherwise you invoke undefined behavior, possibly a crash (but not the one you have, since you never call this function):
void zero(Tree *aTree) { if (aTree != NULL) { zero(aTree->left); zero(aTree->right); free(aTree); }
In function alpha
, you use recursion where a simple loop would suffice. The compiler may convert this to a loop, but it does have to. This is not a bug but why not use a more idiomatic approach such as:
int alpha(const char *word1, const char *word2) { for (size_t i = 0;; i++) { if (word1[i] == '\\0' && word2[i] == '\\0') return 2; if (word1[i] == word2[i]) continue; if (word1[i] < word2[i]) return 1; else return 0; } }
In function create
, you allocate a single byte for the string, this is definitely a cause for the crash. You should allocate strlen(word) + 1
or use strdup(word)
. You should not cast the return value of malloc()
either:
Tree *create(const char *word) { Tree *temp; temp = malloc(sizeof(Tree)); temp->left = temp->right = NULL; temp->val = 1; temp->word = strdup(word); return temp; }
In function insert
you call alpha
multiple times, this is inefficient: you could use a switch
statement:
Tree *insert(Tree *aTree, const char *word) { if (aTree == NULL) { return create(word); switch (alpha(aTree->word, word)) { case 0: aTree->left = insert(aTree->left, word); break; case 1: aTree->right = insert(aTree->right, word); break; case 2: aTree->val++; break; } } return aTree; }
function main
has multiple issues:
argv[1]
is provided to the program. It would be NULL
if the program is run without a command line argument. temp
should be defined as int
and you should test its value after reading the byte from the file with getc()
, it is idiomatic to name c
a variable used for this. if (c >= 'A' && c <= 'Z')
would work for ASCII, which is almost universal today, but it is more reliable to use isupper(c)
instead. buffer
, setting a '\\0'
at the end before inserting the word is enough. fclose(fp)
when fp
is NULL
, this is undefined behavior. Here is a corrected version:
int main(int argc, char *argv[]) { Tree *myTree = NULL; char buffer[256]; int c; size_t i; FILE *fp; if (argc < 2) { printf("missing argument\\n"); return 2; } fp = fopen(argv[1], "r"); if (fp == NULL) { printf("cannot open %s\\n", argv[1]); return 1; } i = 0; while ((c = getc(fp)) != EOF) { c = toupper(c); if (isupper(c)) { if (i < sizeof(buffer)) buffer[i] = c; i++; } else { if (i > 0 && i < sizeof(buffer)) { buffer[i] = '\\0'; puts(buffer); myTree = insert(myTree, buffer); i = 0; } } } fclose(fp); show(myTree); return 0; }
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.