Segmentation fault (core dumped) in c linux - c

My code returns a Segmentation fault and I do not know why.
It prints part of the output and gives a Segmentation fault. I cannot find the error.
It should number words & sentences & paragraphs & top words with highest frequencies in order.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocessing_header.h"
#include "calculations_header.h"
int main(int argc, char* argv[])
{
if (argc != 3)
{
printf("Error: number of arguments must be 3\n");
exit(-1);
}
char* file_name;
file_name = argv[1];
int N = atoi(argv[2]);
char final_string[number_of_char_aprox];
char *string;
string = Preprocessing(file_name);
strcpy(final_string, string);
printf("%s\n", final_string);
calculations(final_string, N);
return 0;
}
/* The main function for sorting the file in the appropriate form */
char* Preprocessing(char file_name[])
{
char final_string[number_of_char_aprox];
char *string;
FILE *in = fopen(file_name,"r");
if (in == NULL) {
printf("Not found");
exit(-1);
}
Head lines_list = (Head)malloc(sizeof(struct line)); // list of the lines from the file
lines_list->next = NULL;
readFile(lines_list, in); // read the file and put each line in a node in the list
fclose(in);
remove_spaces(lines_list); // make only a single space after each word in the lines
to_lower(lines_list); // convert all charachter in each line to small letter
punctuation_marks(lines_list); // make a one single space after punctuation marks
lines_list = reverse_list(lines_list); // reverse the list
string = concat_string(lines_list);// put all line in one string
strcpy(final_string, string);
free_list(lines_list);
string = Atter_punctuation_marks(final_string); // make letters atter punctuation
strcpy(final_string, string);
string = add_point(final_string);
strcpy(final_string, string);
//string = remove_line_feed(final_string);// remove line feed in the same paragraph
//strcpy(final_string, string);
string = final(final_string);// the final form of the string
return string;
}
/* Make the needed calculations */
void calculations(char final_string[],int N)
{
int i;
int number_of_words;
int number_of_sentences;
int number_of_paragraphs;
Head_word lw[26];// array of linked list of the words
for(i = 0; i < 26; i++)
{
lw[i] = (Head_word)malloc(sizeof(struct word));
lw[i]->next = NULL;
}
number_of_words = count_words(final_string, lw);
number_of_sentences = count_sentences(final_string);
number_of_paragraphs = count_paragraphs(final_string);
printf("\n******************************************************\n\n");
printf("\n******************************************************\n\n");
printf("number_of_words = %d\n",number_of_words);
printf("\nnumber_of_sentences = %d\n",number_of_sentences);
printf("\nnumber_of_paragraphs = %d\n",number_of_paragraphs);
printf("\n******************************************************\n\n");
printf("Top %d words with highest frequencies in order : \n\n",N);
Head_word most_repeated[N];
most_repeated_words(lw,most_repeated, N);
free_lists_words(lw);
sort(most_repeated,N); //sort the most frequently used words
print_most_repeated_words(most_repeated, N);
}
here is preprocessing_header.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "preprocessing_header.h"
/*read the file and put each line in a node in a linked list*/
void readFile(Head l, FILE *in)
{
position p;
while(!feof(in))
{
p = (position)malloc(sizeof(struct line));
fgets(p->string,10000,in);
p->next = l->next;
l->next = p;
}
}
/* make only a single space after each word in the lines*/
void remove_spaces(Head l)
{
int i = 0;
int j = 0;
int k;
position p = l->next;
char temp[1000];
while(p != NULL)
{
i = 0;
j = 0;
for(k = 0;k<1000;k++)
{
temp[k] = '\0';
}
while(p->string[i] != '\0')
{
if(p->string[0] == ' ')
{
while(p->string[i] == ' ')
i++;
}
while(p->string[i] != ' ' && p->string[i] != '\0')
{
temp[j] = p->string[i];
i++;
j++;
}
while(p->string[i] == ' ')
{
i++;
}
temp[j++] = ' ';
}
temp[j+1] = '\0';
strcpy(p->string,temp);
p = p->next;
}
}
void to_lower(Head l)
{
position p = l->next;
int i = 0;
while(p != NULL)
{
i = 1;
while(p->string[i] != '\0')
{
if(p->string[i]>= 65 && p->string[i]<=90)
{
p->string[i]+= 32;
}
i++;
}
p = p->next;
}
}
/*make a one single space after punctuation marks and no space before it*/
void punctuation_marks(Head l)
{
position p = l->next;
int i,j,k;
char temp[1000];
while(p != NULL)
{
i = 0;
j = 0;
for(k = 0;k<1000;k++)
{
temp[k] = '\0';
}
while(p->string[i] != '\0')
{
if(p->string[i] == '.' || p->string[i] == ',' || p->string[i] == ';' ||p->string[i] == '?' )
{
if(p->string[i-1] == ' ')
{
temp[--j] = p->string[i];
}
if(p->string[i+1] != ' ')
{
temp[j++] = p->string[i++];
temp[j++] = ' ';
}
}
temp[j++] = p->string[i++];
}
temp[j+1] = '\0';
strcpy(p->string,temp);
p = p->next;
}
}
/*reverse linked list*/
Head reverse_list(Head l)
{
Head l2 = (Head)malloc(sizeof(struct line));
l2->next = NULL;
position p = l->next;
while(p != NULL)
{
l->next = p->next;
p->next = l2->next;
l2->next = p;
p = l->next;
}
free(l);
return l2;
}
/* put all line in one string*/
char* concat_string(Head l)
{
char *temp = malloc(number_of_char_aprox*sizeof(char));
int k;
for(k = 0;k<number_of_char_aprox;k++)
{
temp[k] = '\0';
}
position p = l->next;
while(p != NULL)
{
strcat(temp,p->string);
p = p->next;
}
return temp;
}
/*remove line feed in the same paragraph*/
char* remove_line_feed(char final_string[])
{
int i;
char *temp = malloc(number_of_char_aprox*sizeof(char));
for(i = 0;i<number_of_char_aprox;i++)
{
temp[i] = '\0';
}
int j=0;
//printf("%s",final_string);
for(i = 0;i<strlen(final_string);i++)
{
if(final_string[i] == 13)
{
if(final_string[i-2]== '.')
{
temp[j++] = final_string[i++];
}
else
{
i = i+2;
}
}
temp[j++] = final_string[i];
}
return temp;
}
/*make letters atter punctuation marks capital letters*/
char* Atter_punctuation_marks(char string[])
{
char *temp = malloc(number_of_char_aprox*sizeof(char));
int k;
int i=0,j=0;
for(k = 0;k<number_of_char_aprox;k++)
{
temp[k] = '\0';
}
while(string[i] != '\0')
{
if(string[i] == '.' || string[i] == ';' ||string[i] == '?' || string[i] == '\n' )
{
if(string[i+2] >= 97 && string[i+2]<=122)
{
temp[j++] = string[i++];
temp[j++] = string[i++];
temp[j++] = string[i++]-32;
}
}
if(string[i] == 'i' && string[i-1] == ' ' && string[i+1] == ' ')
{
string[i]-= 32;
}
temp[j++] = string[i++];
}
temp[j+1] = '\0';
return temp;
}
char* to_lower_case(char string[])
{
int i = 0;
while(string[i] != '\0')
{
if(string[i]>= 65 && string[i]<=90)
{
string[i]+= 32;
}
i++;
}
return string;
}
/*make only one empty line between paragraphs and return the stirng with the final form*/
char* final(char s[])
{
int i;
int j = 0;
char *temp = malloc(number_of_char_aprox*sizeof(char));
for(i = 0;i<number_of_char_aprox;i++)
{
temp[i] = '\0';
}
j = 0;
for(i = 0;i<strlen(s);i++)
{
if(s[i]== ' ' && s[i-1] == '\n')
{
i++;
}
if(s[i] == '\n')
{
while(s[i+3] == '\n')
{
i+=3;
}
temp[j++] = '\n';
}
temp[j++] = s[i];
}
return temp;
}
void free_list(Head l)
{
position temp;
while(l->next != NULL)
{
temp = l->next;
l->next = temp->next;
free(temp);
}
free(l);
}
char* add_point(char s[])
{
int i,j=0;
char *temp = (char*)malloc(10000*sizeof(char));
for(i=0;i<strlen(s);i++)
{
if(s[i]==13 && !strchr(".,?;",s[i-1]) && !strchr(".,?;",s[i-2]) )
{
temp[j++] = '.';
i++;
}
temp[j++] = s[i];
}
return temp;
}
and here is my calculations_header.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "calculations_header.h"
/*count the number of words in the string and put the word in an array of linked list
which index is the first letter in each word eg (a)re in the linked list of index 0.
The word will be put in the list if it is a new word only if it is repeated the counter
of the node containing the word will increase*/
int count_words(char string[],Head_word lw[])
{
int i,j,k=0, length=0, count=0;
char word[50];
position_word p;
for(j=0;j<50;j++)
{
word[j] = '\0';
}
length= strlen(string);
for (i=0; i<length; i++)
{
if((string[i] == ' ' && string[i+1] != ' ') || string[i] == 10 || string[i] == 13)
{
if(!is_exist(word,lw[word[0]-97]))
{
//printf("%s\n",word);
p = (position_word)malloc(sizeof(struct word));
strcpy(p->string,word);
p->counter = 1;
p->next = lw[word[0]-97]->next;
lw[word[0]-97]->next = p;
}
//printf("%d",word[1]);
//printf("%s\n",word);
if((word[1]>=97 && word[1]<=123) || (word[1]>=65 && word[1]<=91))
count++;
k = 0;
for(j=0;j<50;j++)
{
word[j] = '\0';
}
}
if((string[i]>=97 && string[i]<=123) || (string[i]>=65 && string[i]<=91))
{
if(string[i] >= 65 && string[i] <= 90)
{
word[k] = string[i]+32;
}
else
{
word[k] = string[i];
}
k++;
}
}
return count;
}
/*test if the word is exist in the list*/
int is_exist(char word[], Head_word l)
{
int flag = 0;
Head_word p;
p = l->next;
while(p!=NULL)
{
if(strcmp(word,p->string) == 0)
{
p->counter++;
flag = 1;
break;
}
p = p->next;
}
return flag;
}
/*decide which N word are the most frequently used*/
void most_repeated_words(Head_word lw[],Head_word most_repeated[],int n)
{
int i,j;
int least;
position_word p;
for(i = 0 ;i<n;i++)
{
most_repeated[i] = (Head_word)malloc(sizeof(struct word));
most_repeated[i]->next = NULL;
most_repeated[i]->counter = 0;
}
for(i = 0;i<26;i++)
{
p = lw[i]->next;
while(p!= NULL)
{
for(j = 0 ; j<n;j++)
{
if(p->counter > most_repeated[j]->counter)
{
least = get_least(most_repeated,n);
strcpy(most_repeated[least]->string,p->string);
most_repeated[least]->counter = p->counter;
break;
}
}
p = p->next;
}
}
}
/*get the least repeated word in the array*/
int get_least(Head_word l[],int n)
{
int i;
int least = 10000;
int index;
for(i = 0;i<n;i++)
{
if(l[i]->counter < least)
{
least = l[i]->counter;
index = i;
}
}
return index;
}
/*count the number of sentences*/
int count_sentences(char s[])
{
int i;
int count = 0;
for(i=0;i<strlen(s);i++)
{
if(strchr(".?;,",s[i]))
{
count++;
}
}
return count;
}
/*count the number of paragraphs*/
int count_paragraphs(char s[])
{
int i;
int count = 0;
for(i=0;i<strlen(s);i++)
{
if(s[i] == '\n' && s[i+1]>=65 && s[i+1]<=90 )
{
count++;
}
}
return count+1;
}
/*print the most repeated N words and how many time it has been used*/
void print_most_repeated_words(Head_word most_repeated[],int N)
{
int i;
for(i=0;i<N;i++)
{
printf("%s\t%d\n",most_repeated[i]->string,most_repeated[i]->counter);
}
}
/*sort the N most frequently used word in ascending order */
void sort(Head_word most_repeated[],int N)
{
int i,j;
Head_word temp = (Head_word)malloc(sizeof(struct word));
for (i = 0 ; i < ( N - 1 ); i++)
{
for (j = 0 ; j < N - i - 1; j++)
{
if (most_repeated[j]->counter < most_repeated[j+1]->counter)
{
temp->counter = most_repeated[j]->counter;
strcpy(temp->string,most_repeated[j]->string);
most_repeated[j]->counter = most_repeated[j+1]->counter;
strcpy(most_repeated[j]->string,most_repeated[j+1]->string);
most_repeated[j+1]->counter = temp->counter;
strcpy(most_repeated[j+1]->string,temp->string);
}
}
}
}
void free_lists_words(Head_word l[])
{
int i;
position_word temp;
for(i = 0;i<26;i++)
{
while(l[i]->next != NULL)
{
temp = l[i]->next;
l[i]->next = temp->next;
free(temp);
}
free(l[i]);
}
}
and here is my calculations_header.h:
#ifndef CALCULATIONS_HEADER_H_INCLUDED
#define CALCULATIONS_HEADER_H_INCLUDED
/*This structure to save each word to make calculations*/
typedef struct word *ptr_word;
struct word
{
char string[50];
int counter;
ptr_word next;
};
typedef ptr_word Head_word;
typedef ptr_word position_word;
/*calculation functions prototypes*/
char* Preprocessing(char []);
void calculations(char [],int);
int count_words(char [],Head_word[]);
int is_exist(char [], Head_word);
void print(Head_word[]);
void most_repeated_words(Head_word [],Head_word[],int);
int get_least(Head_word[],int);
int count_paragraphs(char []);
int count_sentences(char []);
void print_most_repeated_words(Head_word[],int);
void sort(Head_word [],int);
void free_lists_words(Head_word []);
#endif // CALCULATIONS_HEADER_H_INCLUDED
and here is my preprocessing_header.h:
#ifndef PREPROCESSING_HEADER_H_INCLUDED
#define PREPROCESSING_HEADER_H_INCLUDED
#define number_of_char_aprox 10000
/*This structure for saving each line read from the file*/
typedef struct line *ptr;
struct line
{
char string[10000];
ptr next;
};
typedef ptr Head;
typedef ptr position;
/*preprocessing functions prototypes*/
void readFile(Head,FILE *);
void remove_spaces(Head);
void to_lower(Head);
void punctuation_marks(Head );
Head reverse_list(Head);
char* concat_string(Head);
void free_list(Head);
char* Atter_punctuation_marks(char []);
char* remove_line_feed(char []);
char* final(char []);
#endif // PREPROCESSING_HEADER_H_INCLUDED
it give me just warning on line 60 in main( string = add_point(final_string); )
i think the function calculations it make the error.

char final_string[number_of_char_aprox];
What's number_of_char_aprox? You don't even declare it as a variable. A segmentation fault happens when you are trying to access not assigned memory. As there is no value for that variable (actually there is no variable at all), it probably defaults to 0 (or NULL, or imploding universe, who knows), and when you use it to reserve memory for final_string you got your segmentation fault.
By the way, DDD is a great graphical debugger.

Related

reversed string not being returned in a c function in program of infix to prefix

Below is the code for infix to prefix conversion. My code works fine until the use of reverse function where it does not print any string after copying. I have tried using a for loop to copy the reversed string but the outcome remains the same and the program terminates without giving proper output. Print statements in the reverse function work before copying but not after that. Could anyone let me know where the problem is?
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct stack{
int size;
int top;
char *arr;
};
void display(struct stack *ptr)
{
if(ptr->top == -1)
{
printf("Stack is Empty");
}
else
{
for(int i = ptr->top ; i>=0 ; i--)
{
printf("Element: %d\n",ptr->arr[i]);
}
}
}
int isEmpty(struct stack *ptr)
{
if(ptr->top == -1)
{
return 1;
}
else
{
return 0;
}
}
int isFull(struct stack *ptr)
{
if(ptr->top == ptr->size - 1)
{
return 1;
}
else
{
return 0;
}
}
void push(struct stack *ptr,int data)
{
if(isFull(ptr))
{
printf("Stack Overflow");
}
else
{
ptr->top = ptr->top + 1;
ptr->arr[ptr->top] = data;
}
}
char pop(struct stack *ptr)
{
if(isEmpty(ptr))
{
printf("Stack Underflow");
return 0;
}
else
{
char ch = ptr->arr[ptr->top];
ptr->top = ptr->top - 1;
return ch;
}
}
char stackTop(struct stack *ptr)
{
return ptr->arr[ptr->top];
}
int isOperator(char a)
{
if(a == '+'|| a == '-'|| a == '*'|| a == '/')
{
return 1;
}
else
{
return 0;
}
}
int precedence(char a)
{
if(a == '*' || a == '/')
{
return 3;
}
else if(a == '+' || a == '-')
{
return 2;
}
else
{
return -1;
}
}
char * reverse(char exp[])
{
int l = strlen(exp);
int j = 0;
char temp[l];
for(int i=l-1;i>=0;i--,j++)
{
temp[j] = exp[i];
}
temp[j] = '\0';
printf("prefix is %s",temp);
strcpy(exp,temp);
// for(int i=0;i<=l;i++)
// {
// exp[i] = temp[i];
// }
printf("prefix is %s",exp);
return exp;
}
char * infix_prefix(char *infix)
{
struct stack *sp = (struct stack *) malloc(sizeof(struct stack));
sp->size = 100;
sp->top = -1;
sp->arr = (char *) malloc(sp->size * sizeof(char));
char *prefix = (char *) malloc((strlen(infix+1)) * sizeof(char));
infix = reverse(infix);
int i=0;
int j=0;
while(infix[i] != '\0')
{
if(infix[i] == ')')
{
push(sp,infix[i]);
i++;
}
else if(infix[i] == '(')
{
while(!isEmpty(sp) && stackTop(sp) != ')')
{
prefix[j] = pop(sp);
j++;
}
if(!isEmpty(sp))
{
pop(sp);
i++;
}
else
{
printf("Incorrect Expression");
exit(0);
}
}
else if(!isOperator(infix[i]))
{
prefix[j] = infix[i];
i++;
j++;
}
else if(isOperator(infix[i]))
{
while(!isEmpty(sp) && precedence(infix[i])<=precedence(stackTop(sp)))
{
prefix[j] = pop(sp);
j++;
}
push(sp,infix[i]);
i++;
}
else
{
printf("Incorrect expression");
exit(0);
}
}
while(!isEmpty(sp) && stackTop(sp) != '(')
{
prefix[j] = pop(sp);
j++;
}
if(stackTop(sp) == ')')
{
printf("Incorrect expression");
exit(0);
}
prefix = reverse(prefix);
prefix[j] = '\0';
return prefix;
}
int main(void)
{
char *infix = "(x-y/z-k*d)";
printf("prefix is %s",infix_prefix(infix));
return 0;
}
The reverse indeed has a problem: the temp array is defined with a length of l: that's not long enough to store the null terminator at temp[j] after the loop, causing undefined behavior.
There are more problems:
char *prefix = (char *) malloc((strlen(infix+1)) * sizeof(char)); does not allocate enough space for a copy of infix. You should write char *prefix = malloc(strlen(infix) + 1);
infix = reverse(infix); will crash because the argument to infix_prefix is a string literal which must not be modified. You should declare the argument as const char *infix and make a modifiable copy with strdup() if reversing is really needed, which I doubt very much.
Here is a modified version of reverse that performs the reverse operation in place:
char *reverse(char exp[]) {
int i = 0;
int j = strlen(exp);
while (j-- > i) {
char c = exp[j];
exp[j] = exp[i];
exp[i++] = c;
}
return exp;
}

When passing through void pointer values changing and getting segmentation fault?

Background: Creating a hash table library which allows 3 different implementations 2 which solve collisions with open addressing (one being of fixed size and the other dynamic) and a 3rd which uses separate chaining with linked lists.
Background to the Problem: Started by creating the fixed size open addressing. At first this worked perfectly, however, had to make some changes to to adapt the library to cater for the other two implementations. For this I needed to record the size of the list (used structures) and void pointers as structures for the open addressing and separate chaining are different.
The Actual Problem: For some reason my save function is no longer working while debugging I've noticed two issues which I cannot discern the cause of:
passing a structure through a void pointer to this function the
values change (please note that this only happens in this functions
and while I uses the same method in the rest of the functions I do
not get the same problem)
I get a segmentation fault on an fprintf statement (that previous to the above mentioned amendments was working.
The Save Function in Question:
void hashtbl_savetofile(void* hashtbl, const char *path){
Hashtbl *temp;
temp = hashtbl;
int i;
FILE *f = fopen(path, "w");
if (f == NULL){
printf("FILE NOT FOUND!");
}else {
for(i = 0; i<SIZE; i++) {
fprintf(f, "%s", temp->data[i].subscript); // segmentation fault occurs
fprintf(f, "%s", temp->data[i].value);
}
fclose(f);
free(temp);
}
}
The Header File:
#ifndef TASK2_HASHTABLE_H
#define TASK2_HASHTABLE_H
#define SIZE 20
#define MAX_LENGTH 100
#define INIT_SIZE 64000
typedef struct Data_struct{
char *subscript;
char *value;
} Data;
typedef struct Hashtbls{
int numberOfEntries;
int allocatedEntries;
Data *data;
}Hashtbl;
int hashtbl_hashKey(void* hashtbl, const char *subscript ); // generates hash key for hash table
Data hashtbl_lookup(void* hashtbl, const char *subscript); //looks up and retrieves a given subscript and its value hash table
void* hashtbl_insert(void* hashtbl, const char *subscript, const char *value); //adds a given subscript and its value to hash table
void* hashtbl_delete(void* hashtbl, const char *subscript); //deletes a given subscript and its value from hash table
void hashtbl_savetofile(void* hashtbl, const char *path); //saves hash table to file
void* hashtbl_loadfromfile(void* hashtbl, const char *path); //loads hash table from file
void* hashtbl_init();
#endif //TASK2_HASHTABLE_H
The Test Driver:
#include <stdio.h>
#include "hashtable.h"
int main() {
Hashtbl *nums;
Data d;
nums = hashtbl_init();
hashtbl_insert(nums, "tea", "40c");
hashtbl_insert(nums, "coffee", "50c");
hashtbl_insert(nums, "biscuit", "4c");
hashtbl_insert(nums, "tart", "30c");
d = hashtbl_lookup(nums, "tart");
printf("%s", d.subscript);
printf("%s", d.value);
hashtbl_savetofile(nums, "test.txt");
}
The Implementation (for reference):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hashtable.h"
void* hashtbl_init(){ //initiates static 2D hash table when called
Hashtbl* hashtbl;
hashtbl = malloc(INIT_SIZE);
hashtbl->numberOfEntries = SIZE;
hashtbl->allocatedEntries = 0;
hashtbl->data = calloc(SIZE, sizeof(Data));
for(int i = 0; i<SIZE; i++){
hashtbl->data[i].subscript = malloc(MAX_LENGTH + 1);
strcpy(hashtbl->data[i].subscript, "ZERO\n");
hashtbl->data[i].value = malloc(MAX_LENGTH + 1);
strcpy(hashtbl->data[i].value, "ZERO\n");
}
return hashtbl;
}
Data hashtbl_lookup(void* hashtbl, const char *subscript){
Data item;
Hashtbl *temp;
temp = hashtbl;
int i = 0;
char *c;
c = malloc(MAX_LENGTH);
strcpy(c, subscript);
strct(c, "\n");
while (strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) != 0){
i++;
if(hashtbl_hashKey(hashtbl, subscript)+i == temp->numberOfEntries){
break;
}
}
if(hashtbl_hashKey(hashtbl, subscript)+i != temp->numberOfEntries) {
if(strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) == 0) {
item.subscript = temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].subscript;
item.value = temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].value;
}
}else{
for(i = 0; i<hashtbl_hashKey(hashtbl, subscript); i++){
if(strcmp(temp->data[i].subscript, c) == 0){
item.subscript = temp->data[i].subscript;
item.value = temp->data[i].value;
}
}
}
free(hashtbl);
free(c);
free(temp);
return item;//what if not found
}
void* hashtbl_insert(void* hashtbl, const char *subscript, const char *value){
Hashtbl *temp;
temp = hashtbl;
int i = 0;
char *c1;
c1 = malloc(MAX_LENGTH);
strcpy(c1, subscript);
strcat(c1, "\n");
char *c2;
c2 = malloc(MAX_LENGTH);
strcpy(c2, value);
strcat(c2, "\n");
if(temp->allocatedEntries == temp->numberOfEntries){
free(c1);
free(c2);
free(temp);
return hashtbl;
}else {
if (strcmp(temp->data[hashtbl_hashKey(hashtbl, subscript) + i].subscript, "ZERO\n") == 0) {
temp->data[hashtbl_hashKey(hashtbl, subscript)].subscript = c1;
temp->data[hashtbl_hashKey(hashtbl, subscript)].value = c2;
temp->allocatedEntries++;
} else {
while ((strcmp(temp->data[hashtbl_hashKey(hashtbl, subscript) + i].subscript, "ZERO\n") != 0)) {
i++;
if (hashtbl_hashKey(hashtbl, subscript) + i == temp->numberOfEntries) {
break;
}
}
if (hashtbl_hashKey(hashtbl, subscript) + i != temp->numberOfEntries) {
if ((strcmp(temp->data[hashtbl_hashKey(hashtbl, subscript) + i].subscript, "ZERO\n") == 0)) {
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].subscript = c1;
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].value = c2;
temp->allocatedEntries++;
}
} else {
for (i = 0; i < hashtbl_hashKey(hashtbl, subscript); i++) {
if (strcmp(temp->data[i].subscript, "ZERO\n") == 0) {
temp->data[i].subscript = c1;
temp->data[i].value = c2;
temp->allocatedEntries++;
}
}
}
}
free(c1);
free(c2);
return temp;
}
}
void* hashtbl_delete(void* hashtbl, const char *subscript){
Hashtbl *temp;
temp = hashtbl;
int i = 0;
int j = 0;
char *c;
c = malloc(MAX_LENGTH);
strcpy(c, subscript);
strcat(c, "\n");
while ((strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) != 0)){
i++;
if((hashtbl_hashKey(hashtbl, subscript)+i) == temp->numberOfEntries) {
break;
}
}
if(hashtbl_hashKey(hashtbl, subscript)+i != temp->numberOfEntries) {
if(strcmp(temp->data[(hashtbl_hashKey(hashtbl, subscript)+i)].subscript, c) == 0) {
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].subscript = "ZERO\n";
temp->data[(hashtbl_hashKey(hashtbl, subscript) + i)].value = "ZERO\n";
temp->allocatedEntries--;
}
}else{
for(j = 0; j<hashtbl_hashKey(hashtbl, subscript); j++){
if(strcmp(temp->data[j].subscript, c) == 0){
temp->data[j].subscript = "ZERO\n";
temp->data[j].value = "ZERO\n";
temp->allocatedEntries--;
}
}
}
hashtbl=temp;
free(c);
free(temp);
return hashtbl;
}
void hashtbl_savetofile(void* hashtbl, const char *path){
//provided above
}
void* hashtbl_loadfromfile(void* hashtbl, const char *path){
Hashtbl *temp;
temp = hashtbl;
temp->allocatedEntries=0;
int i = 0;
int j =0;
int c = 0;
char line[100];
char* string[temp->numberOfEntries];
FILE *f = fopen(path, "r");
if(f == NULL){
free(temp);
return NULL;
}else {
while(fgets(line, sizeof line, f)){
j++;
}
if((j/2)>temp->numberOfEntries){
free(temp);
return NULL;
}else {
while (fgets(line, sizeof line, f)) {
string[i] = malloc(strlen(line) + 1);
if (string[i] == NULL) {
break;
return NULL;
} else {
strcpy(string[i], line);
i++;
if (i == sizeof string / sizeof *string) {
break;
}
}
}
fclose(f);
for (i = 0; i < (SIZE * 2); i++) {
if (strlen(string[i]) >= MAX_LENGTH) {
char *k = realloc(temp->data[c].subscript, strlen(string[i]));
if (k == NULL) {
break;
return NULL;
} else {
temp->data[c].subscript = k;
strcpy(temp->data[c].subscript, string[i]);
if(temp->data[c].subscript != "ZERO\n"){
temp->allocatedEntries++;
}
i++;
c++;
}
} else {
temp->data[c].subscript = malloc(strlen(string[i]) + 1);
strcpy(temp->data[c].subscript, string[i]);
if(temp->data[c].subscript != "ZERO\n"){
temp->allocatedEntries++;
}
i++;
c++;
}
}
c = 0;
for (i = 1; i < (SIZE * 2); i++) {
if (strlen(string[i]) >= MAX_LENGTH) {
char *k = realloc(temp->data[c].value, strlen(string[i]));
if (k == NULL) {
break;
return NULL;
} else {
temp->data[c].value = k;
strcpy(temp->data[c].value, string[i]);
i++;
c++;
}
} else {
temp->data[c].value = malloc(strlen(string[i]) + 1);
strcpy(temp->data[c].value, string[i]);
i++;
c++;
}
}
hashtbl=temp;
free(temp);
free(string);
return hashtbl;
}
}
}
int hashtbl_hashKey(void* hashtbl, const char *subscript){
int i;
int h = 0;
for(i = 0; subscript[i]; i++){
h += subscript[i];
}
h = h%SIZE;
return h;
}

word frequency of string counter is sometimes wrong

I hope you can help me I worked on this code. The code works like this
user inputs a string for example "hey john, how are you john?
the program erases signs like "'?' , ',' '!' " etc.
the program writes a string after erasing the signs : "hey john how are you john?"
and the code outputs the frequency of each word:
hey : 1
john: 2
how : 1
are : 1
you : 1
but my code counts sometimes wrong. For example when I type "bye bye bye hello hello hello"
the output is :
bye : 3
hello : 1
My code does the john example right, but the bye bye... example wrong.
How do I have to change my code? Thank you
#include <stdio.h>
#include <string.h>
char words[80][80];
void clear_string(char *text);
int extract_and_count(char *source, int *count);
void clearArray(char array[]);
int indexInWords(char string[]);
void print(int countOfWords, int count[]);
int equals(char *string1, char *string2);
int main() {
char string[80];
int count[80];
printf("please enter your text: ");
scanf("%[^\n]s", string);
clear_string(string);
printf("%s\n", string);
int countOfWords = extract_and_count(string, count);
print(countOfWords, count);
return 0;
}
void clear_string(char *text){
int i = 0;
for(;i < strlen(text);++i){
if( text[i] == '.' || text[i] == ',' || text[i] == '!' || text[i] == '?'){
int k = i + 1;
for(; k < strlen(text);++k){
text[k-1] = text[k];
}
k = strlen(text) - 1;
text[k] = ' ';
}
}
}
int extract_and_count(char *source, int *count){
int wordCounter = 0;
char string[80];
int i = 0, k = 0;
clearArray(string);
for(; i < strlen(source);++i, ++k){
if(source[i] != ' '){
string[k] = source[i];
}else{
if(string[0] == '\0'){
break;
}
int index = indexInWords(string);
if(index == -1){
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
}else{
count[index] += 1;
}
clearArray(string);
k = -1;
}
}
return wordCounter;
}
void clearArray(char array[]){
memset(array,0,strlen(array));
//array[0] = '\0';
}
int indexInWords(char string[]){
int i = 0;
for(;i < 80;++i){
if(equals(words[i], string) == 0){
return i;
}
}
return -1;
}
void print(int countOfWords, int count[]){
for(int i = 0;i < countOfWords; ++i){
printf("%s : %d\n",words[i], count[i]);
}
}
int equals(char string1[], char string2[]){
return strcmp(string1, string2);
}
The most significant problem I found was in extract_and_count() -- it doesn't count the last word as it only counts words followed by space. The bandaid is to check if string has anything in it after the loop, and if so, process it. Below is my rework for that fix and general style:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
void clear_string(char *text);
int extract_and_count(char *source, int count[]);
void clearArray(char array[]);
int indexInWords(char string[]);
void print(int countOfWords, int count[]);
bool equals(char *string1, char *string2);
#define BUFFER_SIZE (512)
#define MAX_WORD_COUNT (80)
#define MAX_WORD_SIZE (64)
char words[MAX_WORD_COUNT][MAX_WORD_SIZE];
int main() {
char string[BUFFER_SIZE];
int count[MAX_WORD_COUNT];
printf("Please enter your text: ");
while (fgets(string, BUFFER_SIZE, stdin) == NULL) {
printf("Please (re)enter your text: ");
}
clear_string(string);
int countOfWords = extract_and_count(string, count);
print(countOfWords, count);
return 0;
}
void clear_string(char *text) {
for (int i = 0; i < strlen(text); i++) {
if (text[i] == '.' || text[i] == ',' || text[i] == '!' || text[i] == '?' || text[i] == '\n') {
int length = strlen(text);
for (int k = i + 1; k < length; k++) {
text[k - 1] = text[k];
}
text[length - 1] = '\0';
i--;
}
}
}
int extract_and_count(char *source, int count[]) {
int wordCounter = 0;
char string[MAX_WORD_SIZE] = {'\0'};
for (int i = 0, k = 0; i < strlen(source); i++, k++) {
if (source[i] != ' ') {
string[k] = source[i];
} else {
if (string[0] == '\0') {
break;
}
int index = indexInWords(string);
if (index == -1) {
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
} else {
count[index] += 1;
}
clearArray(string);
k = -1;
}
}
if (string[0] != '\0') {
int index = indexInWords(string);
if (index == -1) {
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
} else {
count[index] += 1;
}
}
return wordCounter;
}
void clearArray(char array[]) {
memset(array, 0, strlen(array));
}
int indexInWords(char string[]) {
for (int i = 0; i < MAX_WORD_COUNT; i++) {
if (equals(words[i], string)) {
return i;
}
}
return -1;
}
void print(int countOfWords, int count[]) {
for (int i = 0; i < countOfWords; i++) {
printf("%s : %d\n", words[i], count[i]);
}
}
bool equals(char string1[], char string2[]) {
return strcmp(string1, string2) == 0;
}
The next most significant issue I see is you don't keep track of how many entries in words[][] are used, so indexInWords() could easily wander off making comparisons against uninitialized memory.
In extract_and_count you break out of the for-loop when you find 2 spaces. Also you did not check for the last word of source. Changed it to:
int extract_and_count(char *source, int *count){
int wordCounter = 0;
char string[80];
int i = 0, k = 0;
clearArray(string);
for(; i < strlen(source)+1;++i, ++k){
if(source[i] != ' ' && source[i] != 0){
string[k] = source[i];
}else{
if(string[0] != '\0'){
int index = indexInWords(string);
if(index == -1){
strcpy(words[wordCounter], string);
count[wordCounter] = 1;
wordCounter++;
}else{
count[index] += 1;
} }
clearArray(string);
k = -1;
}
}
return wordCounter;
}

char array input with space

my program works fine if i give hard code value to char *w="ls -l" but i am trying to take input form user not working help my code:: using input error occur
i don't understand the concept of fgets using fgets its gives the garbig value to execv
#include<stdio.h>
#include<sys/wait.h>
#include<stdbool.h>
void func(char **arr, char *w)
{
int i = 0, j = 0, k = 0;
char temp[100];
for (i = 0; i < 100; i++)
{
if (w[i] == '')
{
arr[k] = temp;
arr[k+1] = NULL;
break;
}
if (w[i] == ' ')
{
arr[k] = temp;
k++;
j = 0;
}
else
{
temp[j] = w[i];
j++;
}
}
}
int main()
{
char *n = "/bin/ls";
char *arr[10] = {''};
char p[100] = {''};
char *w = "ls -l";
int i = 0;
//printf("bilal-hassan-qadri $ >>");
//fgets(p, 100, stdin);
arr[2] = NULL;
bool found = false;
for (i = 0; i < sizeof(w); i++)
{
if (w[i] == ' ')
{
found=true;
func(arr,w);
break;
}
}
if (!found)
arr[0] = w;
int status;
int id = fork();
if (id == 0)
{
if (execv(n,arr) < 0)
{
printf("invalid commandn");
}
else
{
printf("ninvalid command");
}
}
else
{
wait(&status);
}
}
In the function func, You have to copy the string to elements of arr
instead of just passing the address of temp, which will vanish on leaving the function.
You can use strdup instead of copy_string if your system supports it.
You have to terminate the string in temp before copying it.
Empty string constant '' seems invalid. You shouldn't use it.
fgets stores new-line character \n if it exists. Check for it and remove if it isn't wanted.
Fixed code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/wait.h>
#include<stdbool.h>
char *copy_string(const char *str) {
char *s = malloc(strlen(str) + 1);
if (s) strcpy(s, str); else {perror("malloc"); exit(1);}
return s;
}
void func(char **arr, char *w)
{
int i = 0, j = 0, k = 0;
char temp[100];
for (i = 0; i < 100; i++)
{
if (w[i] == '\0' || w[i] == '\n')
{
temp[j] = '\0';
arr[k] = copy_string(temp);
arr[k+1] = NULL;
break;
}
if (w[i] == ' ')
{
temp[j] = '\0';
arr[k] = copy_string(temp);
k++;
j = 0;
}
else
{
temp[j] = w[i];
j++;
}
}
}
int main(void)
{
char *n = "/bin/ls";
char *arr[10] = {NULL};
char p[100] = {0};
char *w = "ls -l";
int i = 0;
//printf("bilal-hassan-qadri $ >>");
fgets(p, 100, stdin);
w = p;
arr[2] = NULL;
bool found = false;
for (i = 0; w[i] != '\0'; i++)
{
if (w[i] == ' ')
{
found=true;
func(arr,w);
break;
}
}
if (!found)
arr[0] = w;
int status;
int id = fork();
if (id == 0)
{
if (execv(n,arr) < 0)
{
printf("invalid commandn");
}
else
{
printf("ninvalid command");
}
}
else
{
wait(&status);
for (i = 0; arr[i] != NULL; i++) free(arr[i]);
}
return 0;
}

C int pointer allocation size [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
its a very very anoing problem what i get. My problem is, gcc seems not allocate enough space to my int pointer.
Here is the code:
fns = (int*)calloc(c,sizeof(int));
So, after then i fill up this in a simple loop ones and zeros:
offset = seekToFirstParam(fnString,n);
i = 0;
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
fns[i] = 1;
} else {
fns[i] = 0;
}
i++;
}
So this is a "flag" array, but when i debug this, and print the elements i get:
156212102, 0, 0, 0, 1, 1
Or som. like this. I don't get it, because if in the calloc method i write 1000 like this:
fns = (int*)calloc(1000,sizeof(int));
After works fine.
Ok, this is a hole function:
char **readFnParams(char *fnString, int n, int *count, int **func) {
char **tmp;
int *fns = NULL;
int c,i = 0,offset,s;
c = getParamsCount(fnString,n);
if (!c) {
return NULL;
}
tmp = (char**)calloc(c,sizeof(char));
fns = (int*)calloc(c,sizeof(int*));
offset = seekToFirstParam(fnString,n);
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
tmp[i] = readNextFunctionParam(fnString,n,offset,&s);
offset = seekToNextParam(fnString,n,offset + s - 1);
fns[i] = 1;
} else {
fns[i] = 0;
offset = seekToNextParam(fnString,n,offset);
}
i++;
}
*func = fns;
*count = c;
return tmp;
}
:) Ok, this is a hole .c file. Yes my previous q. end this connected, becouse its a homework.
#ifndef exccel_builder_source
#define exccel_builder_source
#include "exccel_builder.h"
#include "exccel_utils.h"
#include "exccel_function.h"
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
table* _processing;
//A végére fűzi az új elemeket
void addProcess(cell_process **LIST, cell_process *new) {
if (*LIST == NULL) {
new->next = NULL;
*LIST = new;
return;
}
new->next = *LIST;
*LIST = new;
}
void build(table* table) {
int col = table->matrix->col;
int row = table->matrix->row;
int i,j;
table_cell *cellTemp;
_processing = table;
for (i = 1; i<=row; i++) {
for (j = 1; j<=col; j++) {
cellTemp = getCell(table,i,j);
if (cellTemp != NULL) {
buildCell(cellTemp);
}
}
}
}
void buildCell(table_cell *cell) {
//Begins with '='
if (isFunction(cell)) {
buildCellWithFunction(cell);
}
}
void printProcesses(cell_process *LIST, int tab) {
cell_process *tmp = NULL;
int i = 0;
tmp = LIST;
while(tmp != NULL) {
i = 0;
while(i++<tab) printf(" ");
printf("%s, %d, paramPos: %i\n",tmp->func->name,tmp->func->paramsCount,tmp->paramPos);
if (tmp->childs != NULL) {
i = 0;
while(i++<tab + 3) printf(" ");
printf("Childs\n");
printProcesses(tmp->childs, tab + 3);
}
tmp = tmp->next;
}
}
void buildCellWithFunction(table_cell *cell) {
cell_process *HEAD = NULL;
buildCellProcessList(cell,&HEAD);
cell->cp = HEAD;
printf("%d,%d - cella:\n",cell->row,cell->col);
printProcesses(HEAD,0);
}
void buildCellProcessList(table_cell *cell, cell_process **HEAD) {
char *fnString;
int size;
fnString = getCellStringValue(cell, &size);
readFn(fnString,size,1,cell,HEAD,-1);
}
int readFn(char *fnString, int n, int offset, table_cell *cell, cell_process **LIST, int paramPos) {
char *fnName, *fnParam;
int fnNameLength;
int *fnSig;
int fnSigN;
int fnSigI;
int sig;
exccel_var *vtmp;
exccel_function *ftmp;
cell_process *ptmp;
char **parameters;
int *fnIndexes;
int paramsCount;
int paramI;
int i;
fnName = readFnName(fnString,n,offset,&fnNameLength);
ftmp = getExccelFunction(fnName);
if (ftmp == NULL) {
return 0;
}
ptmp = (cell_process*)malloc(sizeof(cell_process));
ptmp->cell = cell;
ptmp->func = ftmp;
ptmp->paramPos = paramPos;
ptmp->t = _processing;
ptmp->childs = NULL;
addProcess(LIST,ptmp);
parameters = readFnParams(fnString,n,&paramsCount,&fnIndexes);
allocParams(ptmp->func,paramsCount);
paramI = 0;
fnSig = ftmp->signature;
fnSigN = fnSig[0];
fnSigI = 1;
while(fnSigI <= fnSigN) {
sig = fnSig[fnSigI];
if (sig == FN_SIG_RANGE) {
fnParam = parameters[paramI];
vtmp = createExccelRangeVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
paramI++;
} else if (sig == FN_SIG_LITERAL) {
fnParam = parameters[paramI];
if (fnIndexes[paramI] == 1) {
readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
} else {
vtmp = createExccelVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
}
paramI++;
} else if (sig == FN_SIG_LIST) {
while(paramI<paramsCount) {
fnParam = parameters[paramI];
if (fnIndexes[paramI] == 1) {
readFn(fnParam,strlen(fnParam),0,cell,&((*LIST)->childs),paramI);
} else {
vtmp = createExccelVarFromString(fnParam);
//addParamToFunction(ftmp,vtmp);
addParamToFunctionAtPosition(ftmp,vtmp,paramI);
}
paramI++;
}
} else {
printf("Invalid signature %d\n",sig);
exit(1);
}
fnSigI++;
}
return 1;
}
char *readFnName(char *fnString, int n, int offset, int *size) {
char *fnName;
int nameBuffer, i, j;
i = offset;
j = 0;
nameBuffer = 8;
fnName = (char *)calloc(nameBuffer,sizeof(char));
while(*(fnString + i) != '(' && i<n) {
*(fnName + j++) = *(fnString + i++);
if (j>=nameBuffer) {
nameBuffer += 8;
fnName = (char *)realloc(fnName, nameBuffer);
}
}
*(fnName + j++) = '\0';
*size = j;
return fnName;
}
char **readFnParams(char *fnString, int n, int *count, int **func) {
char **tmp;
int *fns = NULL;
int c,i = 0,offset,s;
c = getParamsCount(fnString,n);
if (!c) {
return NULL;
}
tmp = (char**)calloc(c,sizeof(char));
fns = (int*)calloc(c,sizeof(*fns));
offset = seekToFirstParam(fnString,n);
while(i<c) {
tmp[i] = readNextParam(fnString,n,offset,&s);
if (isFunctionString(tmp[i])) {
tmp[i] = readNextFunctionParam(fnString,n,offset,&s);
offset = seekToNextParam(fnString,n,offset + s - 1);
fns[i] = 1;
} else {
fns[i] = 0;
offset = seekToNextParam(fnString,n,offset);
}
i++;
}
*func = fns;
*count = c;
return tmp;
}
int getParamsCount(char *fnString, int n) {
int i = 0, c = 0, jump = 0;
while(i<n) {
if (fnString[i] == '(') {
jump++;
} else if (fnString[i] == ',') {
if (jump == 1) c++;
} else if (fnString[i] == ')') {
jump--;
}
i++;
}
if (c > 0) {
return c + 1;
} else {
return 1;
}
}
int seekToFirstParam(char *fnString, int n) {
int i = 0;
while(fnString[i++] != '(' && i<n);
return i;
}
int seekToNextParam(char *fnString, int n, int offset) {
int i = offset;
while(fnString[i++] != ',' && i<n);
return i;
}
char *readNextParam(char *fnString, int n, int offset, int *size) {
char *params, c;
int paramBuffer, i, j;
i = offset;
j = 0;
paramBuffer = 8;
params = (char*)calloc(paramBuffer,sizeof(char));
while((c = fnString[i++]) != ',' && c != ')' && c != '(' && i<n) {
params[j++] = c;
if (j >= paramBuffer) {
paramBuffer += 8;
params = (char*)realloc(params,paramBuffer);
}
}
params[j] = '\0';
*size = j;
return params;
}
//Megfelelő számú nyitó ( - hez kell hogy legyen ugyanannyi )
char *readNextFunctionParam(char *fnString, int n, int offset, int *size) {
char *fn, c;
int fnBf, i, j, fnStarted = 0, fnClosed = 0;
i = offset;
j = 0;
fnBf = 8;
fn = (char*)calloc(fnBf, sizeof(char));
while((fnStarted != fnClosed || fnStarted == 0) && i<n) {
c = *(fnString + i++);
if (c == '(')
fnStarted++;
else if (c == ')')
fnClosed++;
*(fn + j++) = c;
if (j >= fnBf) {
fnBf += 8;
fn = (char*)realloc(fn, sizeof(char) * fnBf);
}
}
//*(fn + j++) = ')';
*(fn + j++) = '\0';
*size = j;
return fn;
}
#endif
And input like this:
=SZORZAT(MDETERM(A1:D4),NAGY(A1:D4,0),10,20,30)
It looks to me like you aren't allocating correctly, you have:
tmp = (char**)calloc(c,sizeof(char));
The first line, tmp, is allocating c elements of size char (c elements of 1 byte), I think you want c elements of size char * (c elements of size 4 or 8 bytes per element depending on if you are 32 or 64 bit platform). Since your routine readNextParam() is returning char * to store in this array, you need to change the calloc sizeof for tmp to:
tmp = calloc(c,sizeof(char*));
Because of this, I believe you have memory overwrites when you write into the tmp array that bleed into your other array. By making both "1000" elements, you've padded out that first calloc far enough that the overwrites are still in that same piece of memory.

Resources