-
Hash Table Problem.
Hey, it's me again. Sorry to be such a bother but this should be the last time for a little while, I assure you.
The program I've been working on the past week or so is a hash table, using an array of linked lists to do various functions using an input file and an output file. I've been cobbling the program together from notes, a textbook, and several basic functions already written out. The problem is that now that I've written the code, the compiler has found a large number of errors, stemming from the fact that I stupidly assumed there was some kind of string variable in C that didn't exist. So now I've tried to fix the problem but I don't know how to make the errors stop. I'm totally lost.
So I'm posting my code here, and I'm hoping that somebody can help me iron out at least some of the issues. Thanks for any assistance you guys can give.
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXSTRING 100
int calcindex(char j[100]);
struct node* addnode(struct node *j, char k[100], int l);
int lookup(char j[100], struct node *k);
void changeref(char j[100], struct node *k);
int print(struct node *j, FILE *k);
int main(void)
{
/*Necessary variables.*/
FILE *ifp, *ofp;
char item[MAXSTRING];
char command[MAXSTRING];
int index;
int search;
int i;
/*Create linked list node structure.*/
struct StringNode {
char name[MAXSTRING];
int refcount;
struct node *next;
};
/*Create array[19] of these nodes.*/
struct StringNode strarray[19];
/*Open input file.*/
ifp = fopen("inputfile.txt", "r");
/*Open output file*/
ofp = fopen("outputfile.txt", "w");
/*Do until command equals end of input file.*/
while (fscanf(ifp, "%s", &command) != EOF) {
/*Get string from file.*/
fscanf(ifp, "%s", &item);
/*Print command and string to output file.*/
fprintf(ofp, "%s %s", command, item);
/*Check to see if command is Dec or Use.*/
/*If the command is Dec:*/
if (command == "DEC") {
/*Use calculate index function.*/
index = calcindex(item);
/*Check indexed linked list for name by searching list at specific index*/
search = lookup(item, strarray[index]);
/*If name exists in list*/
if (search == 1){
/*Print error message "***Duplicate Name***" to output file*/
fprintf(ofp, " ***Duplicate Name***");
/*Start a new line.*/
fprintf(ofp, "\n");
}
/*If name does not exist in list*/
else {
/*Use add node function with proper name, reference count, and pointer.*/
strarray[index] = addnode(strarray[index], item, strarray[index].refcount);
/*Start new line on output file.*/
fprintf(ofp, "\n");
}
}
/*If the command is Use:*/
else {
/*Use calculate index function.*/
index = calcindex(item);
/*Check indexed linked list for name by searching list at specific index*/
search = lookup(item, strarray[index]);
/*If name exists in list*/
if (search == 1) {
/*Reference count +1*/
changeref(item, strarray[index]);
/*Start new line on output file.*/
fprintf(ofp, "\n");
}
/*If name does not exist in list*/
else {
/*Print error message "***Undefined Name***" to output file*/
fprintf(ofp, " ***Undefined Name***");
/*Start a new line.*/
fprintf(ofp, "\n");
}
}
}
/*Cycle through array.*/
for (i = 0; i < 19; i++) {
/*If current linked list is empty*/
if (strarray[i] == NULL) {
/*Continue*/
continue;
}
/*If current linked list has data*/
else {
/*Print current array field.*/
fprintf(ofp, "%d ", i);
/*Use print function*/
print(strarray[i], *ofp);
}
}
/*Close input file.*/
fclose(ifp);
/*Close output file.*/
fclose(ofp);
/*End program.*/
return 0;
}
int calcindex(char value) {
int total = 0;
int i;
/*Until the end of the string*/
for (i=0; i<strlen(value); i++) {
/*If current character is a letter*/
if (isalpha(value[i])) {
/*If current character is uppercase*/
if (isupper(value[i])) {
/*Add to total this value*/
total = value[i] - 'A' + 1;
}
/*If current character is lowercase*/
else {
/*Add to total this value*/
total = value[i] - 'a' + 1;
}
}
/*If current character is a number*/
else {
/*Add to total this value*/
total = value[i] - '0';
}
}
/*Return total*/
return total;
}
struct node* addnode(struct node *list, char n, int rc) {
struct node *pNew = NULL;
struct node *created_list = NULL;
/*Creating default node*/
pNew = (struct node*)malloc(sizeof(struct node));
pNew.name = n;
pNew.refcount = rc;
pNew.next = NULL;
/*If new node is first node in list*/
created_list = list;
if (list == NULL)
return pNew;
/*If otherwise*/
while (list.next != NULL)
list = list.next;
list.next = pNew;
/*Return updated list*/
return created_list;
}
int lookup(char value, struct node *head) {
/*If list node is empty, return 0*/
if (head == NULL)
return 0;
/*If list node contains the value, return 1*/
else if (value == head.name)
return 1;
/*Otherwise continue down the list*/
else
return(lookup(value, head.next));
}
void changeref(char value, struct node *head) {
int rc;
/*If list node contains the value, raise reference count by 1*/
if (value == head->name) {
rc = head.refcount;
rc += 1;
head.refcount = rc;
}
/*Otherwise continue down the list*/
else {
changeref(value, head.next);
}
}
int print(struct node *list, FILE *ofp) {
struct node current = list;
/*While current node is not empty*/
while (current != NULL)
{
/*Print out the node information*/
fprintf(ofp, " %s %d\n", current.name, current.refcount);
/*Continue to the next node*/
current = current.next;
}
return 1;
}
-
Well in the event you get errors, and you want help on them, it's usually a good idea to actually tell us what error you're getting.
However, at a quick glance:
Code:
if (command == "DEC") {
You cannot compare strings this way. You must use something like strcmp.
Code:
int print(struct node *list, FILE *ofp) {
struct node current = list;
/*While current node is not empty*/
while (current != NULL)
{
/*Print out the node information*/
fprintf(ofp, " %s %d\n", current.name, current.refcount);
/*Continue to the next node*/
current = current.next;
}
return 1;
}
This is completely wrong.
1) Why are you returning anything, when all you ever return is 1? Why not make it void?
2) You should be using a pointer instead of assigning a pointer to a variable instance incorrectly.
3) As mentioned above, your assignment, should you wish to use an instance instead of a pointer, is wrong.
4) Current will never be NULL, because it's an actual instance, and until the function ends, it will always exist.
Consider:
Code:
void listprint(struct node *list, FILE *ofp) {
struct node *current = list;
/*While current node is not empty*/
while (current != NULL)
{
/*Print out the node information*/
fprintf(ofp, " %s %d\n", current->name, current->refcount);
/*Continue to the next node*/
current = current->next;
}
}
There very well may be more, I just didn't feel like compiling it.
Quzah.
-
You have a fundamental misunderstanding of arrays and pointers, you've clearly been weaned on Java, and it looks like you started using StringNode, but changed your mind halfway through writing the program. This compiles, but I didn't run it. Rather than just try and get it to work, I suggest you actually take the time to compare my changes with your code and to figure out why I made those changes:
Code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAXSTRING 100
/*Create linked list node structure.*/
struct node {
char name[MAXSTRING];
int refcount;
struct node *next;
};
int calcindex(char j[100]);
struct node* addnode(struct node *j, char k[100], int l);
int lookup(char j[100], struct node *k);
void changeref(char j[100], struct node *k);
int print(struct node *j, FILE *k);
int main(void)
{
/*Necessary variables.*/
FILE *ifp, *ofp;
char item[MAXSTRING];
char command[MAXSTRING];
int index;
int search;
int i;
/*Create array[19] of these nodes.*/
struct node *strarray[19] = {0};
/*Open input file.*/
ifp = fopen("inputfile.txt", "r");
/*Open output file*/
ofp = fopen("outputfile.txt", "w");
/*Do until command equals end of input file.*/
while (fscanf(ifp, "%s", &command) != EOF) {
/*Get string from file.*/
fscanf(ifp, "%s", &item);
/*Print command and string to output file.*/
fprintf(ofp, "%s %s", command, item);
/*Check to see if command is Dec or Use.*/
/*If the command is Dec:*/
if (strcmp(command, "DEC") == 0) {
/*Use calculate index function.*/
index = calcindex(item);
/*Check indexed linked list for name by searching list at specific index*/
search = lookup(item, strarray[index]);
/*If name exists in list*/
if (search == 1){
/*Print error message "***Duplicate Name***" to output file*/
fprintf(ofp, " ***Duplicate Name***");
/*Start a new line.*/
fprintf(ofp, "\n");
}
/*If name does not exist in list*/
else {
/*Use add node function with proper name, reference count, and pointer.*/
strarray[index] = addnode(strarray[index], item, strarray[index]->refcount);
/*Start new line on output file.*/
fprintf(ofp, "\n");
}
}
/*If the command is Use:*/
else {
/*Use calculate index function.*/
index = calcindex(item);
/*Check indexed linked list for name by searching list at specific index*/
search = lookup(item, strarray[index]);
/*If name exists in list*/
if (search == 1) {
/*Reference count +1*/
changeref(item, strarray[index]);
/*Start new line on output file.*/
fprintf(ofp, "\n");
}
/*If name does not exist in list*/
else {
/*Print error message "***Undefined Name***" to output file*/
fprintf(ofp, " ***Undefined Name***");
/*Start a new line.*/
fprintf(ofp, "\n");
}
}
}
/*Cycle through array.*/
for (i = 0; i < 19; i++) {
/*If current linked list is empty*/
if (strarray[i] == NULL) {
/*Continue*/
continue;
}
/*If current linked list has data*/
else {
/*Print current array field.*/
fprintf(ofp, "%d ", i);
/*Use print function*/
print(strarray[i], ofp);
}
}
/*Close input file.*/
fclose(ifp);
/*Close output file.*/
fclose(ofp);
/*End program.*/
return 0;
}
int calcindex(char value[]) {
int total = 0;
size_t i;
/*Until the end of the string*/
for (i=0; i<strlen(value); i++) {
/*If current character is a letter*/
if (isalpha(value[i])) {
/*If current character is uppercase*/
if (isupper(value[i])) {
/*Add to total this value*/
total = value[i] - 'A' + 1;
}
/*If current character is lowercase*/
else {
/*Add to total this value*/
total = value[i] - 'a' + 1;
}
}
/*If current character is a number*/
else {
/*Add to total this value*/
total = value[i] - '0';
}
}
/*Return total*/
return total;
}
struct node* addnode(struct node *list, char n[], int rc) {
struct node *pNew = NULL;
struct node *created_list = NULL;
/*Creating default node*/
pNew = malloc(sizeof(struct node));
strcpy(pNew->name, n);
pNew->refcount = rc;
pNew->next = NULL;
/*If new node is first node in list*/
created_list = list;
if (list == NULL)
return pNew;
/*If otherwise*/
while (list->next != NULL)
list = list->next;
list->next = pNew;
/*Return updated list*/
return created_list;
}
int lookup(char value[], struct node *head) {
/*If list node is empty, return 0*/
if (head == NULL)
return 0;
/*If list node contains the value, return 1*/
else if (strcmp(value, head->name) == 0)
return 1;
/*Otherwise continue down the list*/
else
return(lookup(value, head->next));
}
void changeref(char value[], struct node *head) {
int rc;
/*If list node contains the value, raise reference count by 1*/
if (strcmp(value, head->name) == 0) {
rc = head->refcount;
rc += 1;
head->refcount = rc;
}
/*Otherwise continue down the list*/
else {
changeref(value, head->next);
}
}
int print(struct node *list, FILE *ofp) {
struct node *current = list;
/*While current node is not empty*/
while (current != NULL)
{
/*Print out the node information*/
fprintf(ofp, " %s %d\n", current->name, current->refcount);
/*Continue to the next node*/
current = current->next;
}
return 1;
}
-
Actually, yeah, Prelude, I have been weaned on Java so to speak. I'm taking classes in both languages at the same time (out of necessity, not desire) so I guess I've gotten a little scatterbrained.
Anyway, to Quzah: I forgot about strcmp completely. It's been a while since I've had to do anything with strings at all, so thank you for pointing that out. That got rid of a lot of errors. Also, in reference to the print function, I took that function almost verbatim from some notes of mine, so that's why it returns a 1, but I also thought that didn't make sense when I wrote it to begin with so I took your advice and changed it to a void function that returns nothing.
To Prelude: All the changes you made make a lot of sense, and yes, I kind of lost track of a lot of things while I was building this code, such as the whole [] thing, and where the pointers had to be, and the position of the node structure code. Thank you so much for all of your help.
The program compiles fine now, but it also doesn't run. When I run it, it doesn't do anything for a while and then it tells me that it has had an error and has to close. Doesn't specify what the error is at all, but I assume it has to do with the files, possibly?
I'm going to attach the input file to this post. The output file is just a blank Notepad file. Can someone see if they can get the program to run? Without knowing what's causing the trouble, I don't even know what to change in the code.
Actually, looking at my folder with the files and program, it seems like my computer tried to add data to the output file and failed in the process, since there's a file with no extension called output in addition to the txt. file.
-
We won't solve all of your problems for you. A huge portion of programming is debugging, and since you have to learn it eventually, it might as well be now.
-
I wasn't asking for all my problems to be solved, and I'm sorry if I sounded that way. I am trying to solve it on my end. I'm just asking for help, which doesn't necessarily ask for a solution, just for help.
EDIT: I also don't know how to use the debugger. It's a foreign language to me.
-
I ran the debugger and it says "Unhandled exception in program.exe: 0xC0000005: Access Violation."
I don't know what that means.
And then it points to this line:
strarray[index] = addnode(strarray[index], item, strarray[index]->refcount);
But as near as I can tell, there's nothing wrong with that line of code.
I don't understand.
-
You are probably running off of the end of an array. Try showing the value of index before the call. Access violations and segmentation faults are you trying to tinker with memory where you don't belong.
Quzah.
-
Well, what you said really helped because I realized my calcindex function was totally wrong, as the formula called for all letters to be multiplied by 3, all numbers by 5, both totals added together, and the whole thing modded by 19 to get the hash index. I printed the value of index to the screen after the adjustments and it's getting the right index for everything, so that isn't the problem, unfortunately.
-
Oh holy ........, I figured it out. I never set each node's reference value equal to anything. I changed the addnode function so that it no longer takes in a reference value, it assigns the value to 0 when it creates the node, and now the program works. Works without a hitch.
Thank you all so much for your assistance in making this beautiful program come to life.