The snippets below are from my program that gets words, then prints them with the number of occurences.
It works almost fine except for it "forgots" that particular entry has been saved before and does NOT increment counter associated with it.
typedef struct {
char *word;
int occ;
}
words;
words *data=NULL;
int main(int argc, char **argv)
{
char *word;
words *temp;
int c,i,num;
words *ptr = NULL;
num=0;
while(1)
{
c=fgetc(infile);
if(c==EOF) break;
if(!isalpha(c)) continue;
else ungetc(c,infile);
word=getword(infile);
if(findword(word))
{
if(!(temp=realloc(data,sizeof(words)*(num+1))))
{ /* error handling */ }
else
data=temp;
}
else
free(word);
}
/* sort procedure here, irrelevant for the purpose of topic */
for(i=0;i<num;i++)
{
/*printf*/
}
return 0;
}
What's wrong with that code?
Thanks in advance!
The fundamental problem is that your "findword" function isn't actually finding a word; it's just looking at one item in the list. It needs to loop.
if ((strcmp(word, ptr->word)) == 0) {
//Do something to store the count
}
else {
return ptr;
}
Related
I have tried creating a program that uses simple stack functions like push to add the contents of the statement onto a stack from where I then print out each character and then reverse the statement. I have used the '.' and '->' member access variables to change the contents of the struct based stack. Upon compiling it prints out the original statement, but after that it gives a segmentation error, saying I am attempting to dereference an uninitialised pointer. Can someone guide me as to how I should solve this problem as it isn't stating the line I have made the problem either.
#include <stdio.h>
#define MAX 1000
#define FULL (MAX - 1)
#define EMPTY -1
typedef struct stack {char s[MAX]; int top;} stack;
int top = EMPTY;
int isFull()
{
if(top == FULL)
return 1;
else
return 0;
}
int isEmpty()
{
if(top == EMPTY)
return 1;
else
return 0;
}
void reset(stack *stk)
{
stk -> top = EMPTY;
}
void push(char c, stack *stk)
{
stk -> top++;
(*stk).s[(*stk).top] = c;
}
char pop(stack *stk)
{
return (*stk).s[(*stk).top--];
}
void print(stack *stk)
{
int i;
while(1)
{
if(isEmpty())
{
printf("Stack underflow\n");
break;
}
for(i = 0; i <= top; i++)
{
printf("%c\n", (*stk).s[i]);
}
printf("\n");
return;
}
}
void reverse(stack *stk)
{
int i;
while(1)
{
if(isEmpty())
{
printf("Stack underflow\n");
break;
}
for(i = top; i >= 0; i--)
{
printf("%c", (*stk).s[i]);
}
printf("\n");
return;
}
}
char peek(const stack *stk)
{
while(1)
{
if(isEmpty())
{
printf("Stack underflow\n");
break;
}
return (*stk).s[(*stk).top];
}
}
int main()
{
stack stack_of_char;
char *str = "i am otto am i";
int i;
reset(&stack_of_char);
printf("original is: %s\n", str);
while(str[i] != '\0')
{
push(str[i++], &stack_of_char);
}
print(&stack_of_char);
reverse(&stack_of_char);
return 0;
}
There are several issues with your program. Let's begin with the global variable top. This is causing problems because on the one hand you have a stack struct responsible for maintaining a stack, and that has its own top. But then you have this global which you're not even using anywhere. It's almost like you added it to get around compiler errors that you didn't understand ;)
So let's ditch that, and fix your stack functions. I'm rearranging the parameters of the push function so that the stack is the first argument. This is a bit more conventional.
typedef struct stack {
char s[MAX];
int top;
} stack;
int isFull(stack *stk)
{
return stk->top == FULL;
}
int isEmpty(stack *stk)
{
return stk->top == EMPTY;
}
void reset(stack *stk)
{
stk->top = EMPTY;
}
void push(stack *stk, char c)
{
if (isFull(stk))
return;
stk->s[++stk->top] = c;
}
char pop(stack *stk)
{
if (isEmpty(stk))
return '\0';
return stk->s[stk->top--];
}
For the pop function, I arbitrarily return a NUL character if the stack is empty, because something must be returned. But really, you should never call this function if the stack is empty.
Let's look at your display functions now. The first thing I notice is that these are really convoluted. There is no need for that complexity. Look here:
void print(stack *stk)
{
for(int i = 0; i <= stk->top; i++)
{
printf("%c\n", stk->s[i]);
}
printf("\n");
}
void reverse(stack *stk)
{
for(int i = stk->top; i >= 0; i--)
{
printf("%c", (*stk).s[i]);
}
printf("\n");
}
char peek(const stack *stk)
{
if (isEmpty(stk))
{
printf("Stack empty!\n");
return '\0';
}
return stk->s[stk->top];
}
And so all that remains is a little tidy-up of your main function, and adjust the parameter order for push.
int main()
{
const char *str = "i am otto am i";
printf("original is: %s\n", str);
stack stack_of_char;
reset(&stack_of_char);
for (int i = 0; str[i]; i++)
{
push(&stack_of_char, str[i]);
}
print(&stack_of_char);
reverse(&stack_of_char);
}
Note also that you shouldn't really be walking over your stack with those functions. The typical way you would use a stack to reverse something is to push values onto it and then pop them off. So, you can print the string in reverse like this:
// Pop characters from stack to print in reverse
while (!isEmpty(&stack_of_char))
{
char c = pop(&stack_of_char);
putc(c, stdout);
}
putc('\n', stdout);
Without initialization, the integer will be a random value. It is the root cause of the memory access error.
You will need to initialize the variable properly. In main function, instead of
int i;,
you should use
int i = 0;.
Assume that you plan to access the value starting from index 0.
I'm trying to implement a hash table in C. I have a csv file, which only consists of a list of surnames on separate lines each. e.g.
Synott
O Neill
Potter
that I am to read from. I then use a hash function, called hash1, to convert these strings into an integer which would give me my index for my hash table. I am then to store the frequency of the occurrence of each name. However, I am getting a segmentation fault which I have deduced is coming from my
void insert(struct individual *p)
function. I'm clueless as to how to solve this and have only started practising C.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define maxSize 500
/* Hash function that returns my key as an integer, giving me my index */
int hash1(char *s){
int hash = 0;
while(*s){
hash = hash + *s;
s++;
}
return hash;
}
/* Item to be stored */
struct individual{
int frequency; /* Value to be stored */
char name[50]; /* This is will be my key */
};
/* The hash table */
struct individual *hashArray[maxSize];
/* Initialising hash table */
void initArray(){
for (int i = 0; i < maxSize; i++){
hashArray[i]->frequency = 0;
hashArray[i]->name[i] = 0;
}
}
/* Function to load the names */
int next_field(FILE *f, char *buffer, int max){
int i = 0, end = 0;
for(;;){
buffer[i] = fgetc(f);
if(buffer[i] == '\n' || feof(f)){ end = 1; break; }
}
buffer[i] = 0;
return end;
};
/* Loading the names into structs - Done */
void reader(FILE *f, struct individual *n){
char buf[50];
next_field(f, n->name, maxSize);
};
/* Adding to the hash table */
void insert(struct individual *p){
struct individual *person = malloc(sizeof(struct individual));
int index = hash1(p->name) % maxSize;
// The issue is coming from this line here:
int primaryIndex = hash1(hashArray[index]->name) % maxSize;
/* Linear Probing */
printf("Do I get to here\n");
while(hashArray[index] != NULL){
if(primaryIndex == index){
hashArray[primaryIndex]->frequency++;
} else{
++index; /* Going to next block */
}
index %= maxSize; /* Looping through the hash table */
}
hashArray[index] = person;
};
void display(struct individual *duine){
printf("%s\n", duine->name);
};
int main(int argc, char *argv[]){
FILE *list;
struct individual in;
//initArray();
/* Opening file */
if( argc < 2 ) {
printf("Also include csv file name.\n");
return EXIT_FAILURE;
}
/* Checking if file is found */
list = fopen(argv[1], "r");
if(!list) {
printf("File not found. %s\n", argv[1]);
return EXIT_FAILURE;
}
while(!feof(list)){
reader(list, &in);
insert(&in);
display(&in);
}
fclose(list);
return EXIT_SUCCESS;
}
What I'm trying to do here is to compare two indices, one from the struct p being passed into this function and one from the hash table at this index. If they are the same, I wish to increase the frequency count stored there by 1. If I do remove this line, the rest of my code runs fine.
Thank you very much
I'm trying to implement a hash table in C. I have a csv file, which only consists of a list of surnames on separate lines each. e.g.
Sybott
O Neill
Potter
that I am to read from. I then use a hash function, called hash1, to convert these strings into an integer which would give me my index for my hash table. I am then to store the frequency of the occurrence of each name.
However, I am getting a segmentation fault which I have deduced is coming from my
void insert(struct individual *p)
function. I'm clueless as to how to solve this and have only started practising C.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define maxSize 500
/* Hash function that returns my key as an integer, giving me my index */
int hash1(char *s){
int hash = 0;
while(*s){
hash = hash + *s;
s++;
}
return hash;
}
/* Item to be stored */
struct individual{
int frequency; /* Value to be stored */
char name[50]; /* This is will be my key */
};
/* The hash table */
struct individual *hashArray[maxSize];
/* Initialising hash table */
void initArray(){
for (int i = 0; i < maxSize; i++){
hashArray[i]->frequency = 0;
hashArray[i]->name[i] = 0;
}
}
/* Function to load the names */
int next_field(FILE *f, char *buffer, int max){
int i = 0, end = 0;
for(;;){
buffer[i] = fgetc(f);
if(buffer[i] == '\n' || feof(f)){ end = 1; break; }
}
buffer[i] = 0;
return end;
};
/* Loading the names into structs - Done */
void reader(FILE *f, struct individual *n){
char buf[50];
next_field(f, n->name, maxSize);
};
/* Adding to the hash table */
void insert(struct individual *p){
struct individual *person = malloc(sizeof(struct individual));
int index = hash1(p->name) % maxSize;
// The issue is coming from this line here:
int primaryIndex = hash1(hashArray[index]->name) % maxSize;
/* Linear Probing */
printf("Do I get to here\n");
while(hashArray[index] != NULL){
if(primaryIndex == index){
hashArray[primaryIndex]->frequency++;
} else{
++index; /* Going to next block */
}
index %= maxSize; /* Looping through the hash table */
}
hashArray[index] = person;
};
void display(struct individual *duine){
printf("%s\n", duine->name);
};
int main(int argc, char *argv[]){
FILE *list;
struct individual in;
//initArray();
/* Opening file */
if( argc < 2 ) {
printf("Also include csv file name.\n");
return EXIT_FAILURE;
}
/* Checking if file is found */
list = fopen(argv[1], "r");
if(!list) {
printf("File not found. %s\n", argv[1]);
return EXIT_FAILURE;
}
while(!feof(list)){
reader(list, &in);
insert(&in);
display(&in);
}
fclose(list);
return EXIT_SUCCESS;
}
What I'm trying to do here is to compare two indices, one from the struct p being passed into this function and one from the hash table at this index. If they are the same, I wish to increase the frequency count stored there by 1. If I do remove this line, the rest of my code runs fine.
Thank you very much
I want to store words from a pointer of char strings in a double linked list. My function for storing the words in the char strings works perfect, but when it comes to storing in the dll elements it doesn't work anymore. I can't understand if there is a problem in the declarative zone of the list (I am new to lists, we just did some theory on them in the class) or with the node changing pointer.
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
int number_of_words (FILE *f) {
char x[1024];
int i=0;
while (fscanf(f, " %1023s", x) == 1) {
i++;
}
return i;
}
void words (FILE *f, char *words[]) {
char x[1024];
int i=0;
while (fscanf(f, " %1023s", x) == 1) {
words[i]=strdup(x);
i++;
}
}
typedef struct node{
int freq;
char *word_string;
struct node *next;
struct node *prev;
}node;
int main(int argc, const char * argv[]) {
FILE *input=fopen(argv[1], "r+");
if(input==NULL) printf("error in reading from file");
else printf("reading works.\n");
int k=number_of_words(input);
char *word[k];
char *word_unique[k];
rewind(input);
words(input, word);
int j=0,l=0,s=0;
for(j=0;j<k;j++) {
for (l=0; l<j; l++){
if (strcmp(word[j],word[l])==0)
break;
}
if (j==l){
word_unique[s]=word[j];
s++;
}
}
int *word_freq[s];
for(j=0;j<s;j++){
word_freq[j]=0;
}
for(j=0;j<s;j++) {
for (l=j; l<k; l++){
if (strcmp(word_unique[j],word[l])==0)
word_freq[j]++;
}
}
char *aux=malloc(30*sizeof(char));
for(j=0;j<s;j++){
for(l=j+1;l<s-1;l++){
if(strcasecmp(word_unique[j], word_unique[l])>0)
{
strcpy(aux,word_unique[j]);
strcpy(word_unique[j],word_unique[l]);
strcpy(word_unique[l],aux);
}
}
}
node *head, *curr=NULL;
int i=0;
head=NULL;
for(i=0;i<k;i++){
curr=(node *)malloc(sizeof(node));
curr->word_string=word_unique[i];
curr->freq=word_freq[i];
curr->next=head;
head=curr;
}
while(curr) {
if(curr->word_string!=NULL) printf("%s:%d\n", curr->word_string, curr->freq);
curr = curr->next;
}
return 0;
}
The input file is a text file and it looks like this:
Everything LaTeX numbers for you has a counter associated with it. The name of the counter
is the same as the name of the environment or command that produces the number, except
with no. Below is a list of some of the counters used in LaTeX’s standard document styles
to control numbering.
When I tried to print the unique elements in alphabetical order with their frequency, it actually prints out in reverse order with 4x frequency they actually have. It also separates "numbering." from the others + a new line at the beginning which I don't know where it comes from. This is what it prints:
reading works.
0- :2098416
numbering.:4
you:4
with:4
used:4
to:4
the:4
The:4
that:4
styles:4
standard:4
some:4
same:4
produces:4
or:4
of:4
numbers:4
number,:4
no:4
name:4
list:4
LaTeX’s:4
LaTeX:4
it.:4
is:4
in:8
has:24
for:16
except:8
Everything:4
environment:4
document:8
counters:4
counter:8
control:8
command:4
Below:4
associated:4
as:4
a:4
\.:4
Program ended with exit code: 0
This is program to count individual word count in a variable para as an input.
I tried this by using linked list.
Here variable complete is an array that acts like a hash code and stores all alphabets and I am linking new word as per the hash and if there is same word then I am increasing the count. This is the logic I followed.
But the thing is in the program it is not going into a particular part of the code which is written to take repeated words and it is not increasing the count.
This is my code can any one help me with this.
#include<stdio.h>
#include<conio.h>
#include<string.h>
#define NULL 0
struct wordcount
{
char *s;
int count;
struct wordcount *next;
};
struct checkletter
{
char alph;
struct wordcount *next;
};
struct wordcount * create(char *);
main()
{
char *c,*s1,*intm;
char hastlet;
int hash[26],len,i,k=0,r,j,m=0,t,flag=0;
struct checkletter complete[26];
struct wordcount *node;
clrscr();
for(r=0;r<=25;r++)
{ complete[r].alph=r+97;
complete[r].next=NULL;
}
for(r=0;r<=25;r++)
{
printf("%c",complete[r].alph);
}
printf("\n");
printf("Enter the para :");
gets(c);
len=strlen(c);
//arranging the words and putting them with count
for(i=0;i<len;i++)
{ k=0;
intm='\0';
if(c[i]==' ')
{ for(j=m;j<i;j++)
{
intm[k]=c[j];
k++;
}
intm[k]='\0';
strcpy(s1,intm);
m=k;
m++;
hastlet=s1[0];
for(t=0;t<26;t++)
{
if(complete[t].alph==hastlet)
{
node=complete[t].next;
if(node==NULL)
{
complete[t].next=create(s1);
node=complete[t].next;
break;
}
else
{ while(!strcmp(node->s,s1))
{
node=node->next;
if(node->next==NULL)
{ flag++;
break;
}
}
if(!strcmp(node->s,s1))
(node->count)+=1;
if(flag)
{ node->next=create(s1);
}
} break;
}
}
}
}
//displaying the word that are counted
for(i=0;i<26;i++)
{ node=complete[i].next;
if(complete[i].next!=NULL)
while(1)
{ printf("%s---%d",node->s,node->count);
if(node->next==NULL)
break;
}
}
getch();
}
struct wordcount * create(char *y)
{
struct wordcount *newnode;
newnode->s=y;
newnode->count=0;
newnode->next=NULL;
return newnode;
}
The following is incorrect:
char *c;
...
gets(c);
Using an un-initialized pointer c in gets function leads to a undefined behavior. You need to allocate memory for c which is one greater than the max number of characters you wish to store.
Same is the case with intm.
Also, use fgets in place of gets