C - Errors when trying to make a hashtable - c

I'm working on a hash table that stores strings in linked lists so I can avoid collisions. However, I'm getting two errors that I'm not sure how to fix. The first error I am getting is in the line that says NewT->Table[i] == NULL;. It's saying warning: statement with no effects [-Wunused-value].
The second error I'm getting is in the same function. The error is in the line return NewT and the error is warning: return from incompatible pointer type[enabled by default]. I've been staring at this for awhile and I can't see where there is an unused value and I have no idea what the return error means even after a bit of research. Can someone explain these to me and help me fix them?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define HASH_MULTIPLIER 65599
/*Structures*/
typedef struct List_T
{
char *str;
int count;
struct List_T *next;
} ListT;
typedef struct Hash_T
{
int htsize;
ListT **Table;
} HashT;
/*Prototypes*/
unsigned int hash(const char *str);
HashT **ht_create(void);
int htsize;
int main(int argc, char *argv[])
{
if (argc <= 1)
{
printf("Please declare a table size");
return 1;
}
htsize = atoi(argv[1]);
return 0;
}
unsigned int hash(const char *str)
{
int i;
unsigned int h = 0U;
for (i = 0; str[i] != '\0'; i++)
h = h * HASH_MULTIPLIER + (unsigned char) str[i];
return h % htsize;
}
HashT **ht_create(void)
{
HashT *NewT;
int i;
if (htsize < 1) //invalid size for
{
fprintf(stderr,"Invalid Size for table");
exit(0);
}
if ((NewT = malloc(sizeof(HashT))) == NULL)
{
fprintf(stderr,"Invalid size for table");
exit(0);
}
if ((NewT->Table = malloc(sizeof(ListT *) * htsize)) == NULL)
{
fprintf(stderr,"Invalid size for table");
exit(0);
}
for (i = 0; i<htsize; i++)
{
NewT->Table[i] == NULL;
}
NewT->htsize = htsize;
return NewT;
}

The first error I am getting is in the line that says NewT->Table[i]
== NULL;. It's saying warning: statement with no effects [-Wunused-value].
This error shows up because the code is making a comparison and not an assignment. The value returned by the comparison (is Table[i] null?) is itself not assigned to anything else, which means it's unused.
Keep a single = operator instead of the doubled == to make sure you're actually assigning instead of comparing.
The second error I'm getting is in the same function. The error is in
the line return NewT and the error is warning: return from
incompatible pointer type[enabled by default].
Your function claims to be returning a pointer to a pointer to HashT, or HashT **, but you end up returning a pointer to HashT, or HashT * instead, which is the type of your NewT variable.
Your function's signature should use a single * instead of two.

Related

Adding words to a hash table in C

Before proceeding with PSET5 - SPELLER of the CS50 course, I have decided to practice with a made-up program that takes words from a file and sorts them into a Hash Table, but I think I`m doing something wrong with the Hash Function as I keep getting the following error:
array subscript is not an integer
table[hash] = n;
Some of the elements are taken from the task itself to understand how they work. I don`t have any previous knowledge, totally limited to the CS50 course.
Please have a look at my code and maybe give a few pointers to what I am doing wrong.
From what I understand - every new word`s first letter goes through Hash Functions and returns a number for the Bucket in which this word goes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int hash(const char *buffer);
const unsigned int LENGTH = 9;
typedef struct node
{
char word[LENGTH + 1];
struct node* next;
}
node;
node *table[26] = {NULL};
int hash(const char *buffer)
{
return toupper(buffer[0]) - 'A';
}
int main(void)
{
FILE *file = fopen("words", "r");
if (file != NULL)
{
char buffer[LENGTH];
while (fscanf(file, "%s", buffer) != EOF)
{
node *n = malloc(sizeof(node));
if (n == NULL)
{
return 1;
}
strcpy(n->word, buffer);
n->next = NULL;
table[hash] = n;
}
fclose(file);
}
}
You need to call the function hash(..) , it is not a variable.
Your line should be:
table[ hash(n->word) ] = n;

Error pops up at structs and double pointers in c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHARS 10
char **readText(void) ;
typedef struct text_t
{
char * * mt;
int words;
}
Text_t;
int main(void)
{
int i, words;
Text_t.mt = readText();
for (i=0; i<words; i++)
printf("%s\n", Text_t.mt[i]);
return 0;
}
char **readText(void)
{
*Text_t.mt = NULL;
char *word;
*words = 0;
while (scanf("%s", word=malloc(CHARS*sizeof(char))),
strcmp(word,"END"))
{
(*words) ++;
Text_t.mt = realloc(mytext, (*words)*sizeof(char *));
Text_t.mt[*words-1] = word;
}
free(word);
return Text_t.mt;
}
The goal of this programm is to take some words as input from the user untill the word "END" is entered. Then we print the given words with the same order as they were entered. The problem is when I try to run the programm, this error comes up:
main.c|16|error: expected identifier or '(' before '.' token|
You probably mean
Text_t tt;
tt.mt = NULL;
ie
create an instance ot the Text_t struct
set its 'mt' pointer to NULL
whether thats the correct thing for your main aim I cant say, but at least it will get you past your current compile error

How access with recursion to some element of a struct

I would write a function , that elaborates a struct and return the length of an array of character ,that is define in the same struct, in a recursive way.
The struct is:
typedef struct BinSeq {
char* data;
int dimension;
}BinSeq
data, the array of character,can have only two type of character: '0' and '1',while dimension is the length of array, but not of sequence of '0' and '1'.
So I try to write this function:
int length(BinSeq* bin_seq) {
int i;
if(bin_seq->data[i] == '0' || bin_seq->data[i] == '1')
{
i++;
return 1 + length(bin_seq->data[i]);
}else
return 0;
}
but I have may doubts about this. First caused by the compiler that says:
warning: passing argument 1 of ‘length’ makes pointer from integer without a cast [enabled by default]
return 1 + length(bin_seq->data[i]);
^
recursion.c:13:6: note: expected ‘struct BinSeq *’ but argument is of type ‘char’
int length(BinSeq* bin_seq) {
How can I work on the data , If I had to pass to my function the Binseq* bin_seq? I know that my code is in error for this , but if I want calculate the leght I had to increment the variable i, but the it won't , I think, increase. How can I work on this?
like this:
#include <stdio.h>
typedef struct BinSeq {
char *data;
int dimension;
} BinSeq;
int length(BinSeq* bin_seq) {
if(*bin_seq->data == '0' || *bin_seq->data == '1')
return 1 + length(&(BinSeq){bin_seq->data + 1, bin_seq->dimension});
return 0;
}
int main(int argc, char** argv) {
BinSeq binary;
binary.data = "0000110111";
binary.dimension = 2014;
int dimension_of_array = length(&binary);
printf("%d\n", dimension_of_array);
return 0;
}
by using the auxiliary recursive function
int aux_length(const char *data){
if(*data == '0' || *data == '1')
return 1 + aux_length(data + 1);
return 0;
}
int length(BinSeq* bin_seq) {
return aux_length(bin_seq->data);
}
If I interpreted correctly, this code should do what you want:
int length(BinSeq* bin_seq, int i) {
if(bin_seq->data[i] == '0' || bin_seq->data[i] == '1')
{
return 1 + length(bin_seq->data, ++i);
} else {
return 0;
}
}
Although there are more efficient ways to code this: in practice you can simply use pointer arithmetic to loop over the char array until you find anything but a 0 or 1. You have also not shown how you initialize the sequence; one would assume it is done correctly with a known terminator character (e.g. \0).
I had to write a function int length(BinSeq* bin_seq)that calculates recursively the length of the binary sequence bin_seq. The struct is:
typedef struct BinSeq {
char* data;
int dimension;
}BinSeq
and the main is:
int main(int argc, char** argv) {
Binseq* binary;
binary.data = "0000110111";
binary.dimension = 2014;
int dimension_of_array = length(BinSeq* bin_seq);
}
How can I calculate the length of data, if I had to pass bin_seq to function?

Segmentation Fault in C

My code is giving me a segmentation fault and I can't seem to find what I'm doing wrong:
#include <stdio.h>
#include <string.h>
char find(char name[], char allNames[][10], int length)
{
int i=0;
for (i = 0; i < length; i++) {
if (strcmp(allNames[i],name) == 1) {
printf("%i",i);
return *name;
}
}
return -1;
}
main(){
char allNames[][10] = {"cat","dog","frog","log","bog"};
char name[] = "log";
int length=5;
printf("%s",find(name,allNames,length));
}
I'm really keen to understand all the mechanisms happening here and what I'm doing wrong for tomorrows exam. Thanks for your help!
EDIT: Really Appreciate the answers and information guys! I'm really quite new to C and just getting used to what every thing means. The particular exam question I am looking at is :
(a) The following function is intended to find the string name in the array
allNames. If found, it returns the position of name in the array. If not
found, it returns -1. Modify the code so that it works correctly.
int find(char name[], char allNames[][10])
{
for (i = 0; i < 10; i++) {
if (allNames[i] == name) {
return name;
}
}
return -1;
}
And I'm trying to get a program to work within these parameters. Cheers :)
http://coliru.stacked-crooked.com/a/d400c9a56d732446
#include <stdio.h>
#include <string.h>
char* find(char name[], char allNames[][10], int length)
{
int i=0;
for (i = 0; i < length; i++) {
if (!strcmp(allNames[i],name)) {
printf("%i",i);
return name;
}
}
return NULL;
}
int main(){
char allNames[][10] = {"cat","dog","frog","log","bog"};
char name[] = "log";
int length=5;
printf("%s",find(name,allNames,length));
}
Returning a single char will do you no good if you're trying to return a string. I would also suggest that you return a NULL if you cannot find the string.
Also, include the int before main; this is better style.
The direct reason for your Segmentation Fault here is because the code tried to print the char type with %s(which needs an address value).
void main()
{
char c = 'a';
printf("%s", c); // will cause Segmentation fault here
}
Back to your code, that is
char find(char name[], char allNames[][10], int length)//return char
printf("%s",find(name,allNames,length));
The minimal change to make it work as follows,
1) To return char*
char* find(char name[], char allNames[][10], int length)//return char*
{
int i=0;
for (i = 0; i < length; i++) {
if (strcmp(allNames[i],name) == 0) { // here should 0
printf("%i",i);
return name; // change name* to name
}
}
return NULL; // change to NULL
}
//to print
printf("%s",find(name,allNames,length));
2) to return position value
int find(char name[], char allNames[][10])
{
for (i = 0; i < 10; i++) {
if (allNames[i] == name) {
return i; // here, change to return i
}
}
return -1;
}
//then, you can print like this
printf("find at position: %d",find(name,allNames,length));
//or to print string by
int pos = find(name,allNames,length);
if(pos >= 0)
printf("find the string: %s",allNames[pos]);
This code is wrong on several levels.
gcc -Wall -Wextra reveals:
meh.c:15:1: warning: return type defaults to ‘int’ [-Wreturn-type]
main(){
^
meh.c: In function ‘main’:
meh.c:19:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("%s",find(name,allNames,length));
^
meh.c:21:1: warning: control reaches end of non-void function [-Wreturn-type]
}
^
What's up with that? Do you compile with warnings enabled?
I am ignoring the lack of indentation.
#include <stdio.h>
#include <string.h>
char find(char name[], char allNames[][10], int length)
What? How about: char *name, **list, int size)
{
int i=0;
Why set it to 0 here?
for (i = 0; i < length; i++) {
if (strcmp(allNames[i],name) == 1) {
printf("%i",i);
return *name;
Have you read strcmp's manpage? It returns ZERO when a string matches, so this code makes no sense.
*name is of type char, but you don't want to return a char. You want to return a pointer, no?
}
}
return -1;
Well, given that you feed that into %s in printf, what do you expect to hapen here? Normally one would return NULL.
}
main(){
This is obsolete syntax, I don't know where you stole it from. Use 'int main(void)'.
char allNames[][10] = {"cat","dog","frog","log","bog"};
Normally people just return such arrays with a NULL pointer, so that these can be iterated over and there is no need to pass anything about the size.
char name[] = "log";
Why not char *name = "log".
int length=5;
Incorrect. It hardcodes the amount of stored strings in allNames table.
printf("%s",find(name,allNames,length));
}

warning: control may reach the end of non-void function in C [duplicate]

This question already has answers here:
What does "control reaches end of non-void function" mean?
(10 answers)
Closed 8 years ago.
Specifically about the put function: I've reviewed the answers to this question and followed some of the suggestions e.g. putting an else condition in the put function, with no luck.
I still get the above warning at compile time. I suspect there is something else going on in the code to cause it.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hashtable.h"
/* For a given string refered to by the pointer "string",
* calculate the hashcode and update the int "value".
*
* Return 1 if successful, return 0 if unsuccessful.
*/
int main(){
}
int hash(char *string, unsigned long *value) {
value = 0;
if(string == NULL) {
return 0;
}
while(string != NULL) {
*value = *value + *string;
string++;
}
return 1;
}
/* Add the string to the hashtable in the appropriate "bucket".
*
* Return 1 if successful, and 0 if unsuccessful.
*/
int put(char *string, hashtable *h) {
unsigned long hashValue = 0;
int hashcode = hash(string, &hashValue);
int index = hashValue %CAPACITY;
node *head = &head -> next[index];
node *newNode = malloc(sizeof(node));
if(newNode == NULL)
return 0;
else
return 1;
}
/*
* Determine whether the specified string is in the hashtable.
* Return 1 if successful, and 0 if unsuccessful.
*/
int get(char *string, hashtable *h) {
int i = *string;
int newNode;
for(i = 0; i <= newNode; i ++)
if(*string == newNode) {
return 1;
}
return 0;
}
This warning is due to your main function, which doesn't return anything.
Change this
int main(){
}
to this
int main(void) {
return 0; // everything OK
}
As you can see, I wrote main(void).
void here means that main() is not receiving any arguments! main can receive command line arguments.
An irrelevant logical error is here:
int hash(char *string, unsigned long *value) {
value = 0; // here you maybe forgot the *
if(string == NULL) {
return 0;
}
..
}
you probably want to set where the value points to, to zero, so change this
value = 0;
to this
*value = 0;
I have made a small example in my pseudo-site, in case you want to see more in functions and pointers.
You have mentioned int as the return type of main() function. So you will have to return some integer value from the main function at every exit from the function.
There are two solutions to the problem.
Solution 1: return 0/1 at the end of the function and at every exit from the function
int main(){
----
----
return 0;
}
Solution 2: Specify void as the return type of main() function, if you dont want to process the return type of main function.
void main() {
---
---
}

Resources