I have an assignment for checking if some input words are from a dictionary and print and count the ones that are not. Initially the dictionary was an array and I had to change it to a trie to make it faster (the code that is between /* */ is the changed code). After trying to compile it I get this weird
I have no idea what to do now. The files and code that I used are the following:
dictionary.h:
// declares a dictionary
#ifndef DICTIONARY_H
#define DICTIONARY_H
#include <stdbool.h>
// maximum length for a word
#define LENGTH 45
//Nr of possible children=size of the alphabet
#define N 26
//a trie as dictionary
typedef struct dict
{
bool is_word;
struct dict *children[N];
} dict;
// a dictionary is an array
/* typedef struct dict {
int numWords;
int maxWords;
char **words;
} dict;
*/
dict *newEmptyDict();
void addWord(char word[LENGTH + 1], dict *d);
bool check(const char *word, dict *d);
void freeDict(dict *n);
#endif // DICTIONARY_H
dictionary.c:
// implements a dictionary
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dictionary.h"
#define CHAR_TO_INDEX(c) ((int)c - (int)'a')
/* dict *newEmptyDict() {
dict *d = malloc(sizeof(dict));
if (d == NULL) {
return NULL;
}
d->numWords = 0;
d->maxWords = 1;
d->words = malloc(sizeof(char*) * d->maxWords);
return d;
}
*/
//create an empty trie dictionary
dict *newEmptyDict() {
dict *pN = NULL;
pN=(dict*)malloc(sizeof(dict));
if (pN){
int i;
pN->is_word=false;
for (i=0;i<=N;i++)
pN->children[i]=NULL;
}
return pN;
}
// add word to the dictionary if it is is not already known
/* void addWord(char word[LENGTH + 1], dict *d) {
if (!check(word, d)) {
// if we need more space before adding the word, double the size
if (d->numWords == d->maxWords) {
d->words = realloc(d->words,(sizeof(char*)) * (d->maxWords * 2));
if (d->words == NULL) {
printf("Out of memory.\n");
exit(-1);
}
d->maxWords = d->maxWords * 2;
}
// now we actually add the word
d->words[d->numWords] = malloc(sizeof(char) * (LENGTH + 1));
strcpy(d->words[d->numWords],word);
d->numWords++;
}
} */
void addWord(char word[LENGTH + 1], dict *d) {
int level;
int len=strlen(word);
int index;
dict *pC = d;
for (level=0;level<len;level++){
index = CHAR_TO_INDEX(word[level]);
if(!pC->children[index])
pC->children[index] = newEmptyDict();
pC=pC->children[index];
}
pC->is_word = true;
}
// check whether word is in dictionary
/* bool check(const char *word, dict *d) {
for (int i = 0; i < d->numWords; i++) {
if (strcmp(d->words[i],word) == 0) {
return true;
}
}
return false;
} */
bool check(const char *word, dict *d) {
int level;
int len=strlen(word);
int index;
dict *pC = d;
for (level=0;level<len;level++){
index = CHAR_TO_INDEX(word[level]);
if (!pC->children[index])
return false;
pC=pC->children[index];
}
return (pC!=NULL && pC->is_word);
}
/* void freeDict(dict *d) {
for (int i = 0; i < d->numWords; i++) {
free(d->words[i]);
}
free(d->words);
free(d);
}
*/
void freeDict(dict *d) {
int i;
for (i=0;i<=N;i++)
if (d->children[i]) freeDict(d->children[i]);
free (d);
}
speller.c:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include "dictionary.h"
// remove non-alphabetic characters and convert to lower case
void trimWord(char *word) {
int k = 0;
for (int i = 0; i < (int) strlen(word); i++) {
if (isalpha(word[i])) {
word[k] = tolower(word[i]);
k++;
}
}
word[k] = '\0';
}
int main(int argc, char *argv[]) {
char word[LENGTH + 1] = "";
// step 1: read in the dictionary
dict *dictionary = newEmptyDict();
while (scanf("%45s",word) && word[0] != '!') {
trimWord(word);
addWord(word,dictionary);
memset(word,0,strlen(word));
}
// step 2: read in text
int counter = 0; // number of unknown words
// BUG: This loop is wrong. It will read "one,twwo" as one word "onetwwo".
/* while (scanf("%45s", word) != EOF) {
trimWord(word);
if (!check(word,dictionary)) {
counter++;
printf("%s\n",word);
}
}
*/
int index = 0; int wcheck=0; //wcheck is for knowing if a word has begun so no unnecesary \n's are printed
int c = EOF;
while ((c = getchar()) && c != EOF) {
if (isalpha(c)){
word[index]=c;
index++;
wcheck=1;
}else if (wcheck){
trimWord(word);
if(!check(word,dictionary)){
counter++;
printf("%s\n", word);
}
memset(word,0,strlen(word));
index=0;
wcheck=0;
}
}
// TODO: Replace the above while loop with a correct solution.
// Hints:
// - you should read one character at a time, using getchar()
// - alphabetical characters should be appended to the current word
// - any other symbol should terminate the word
// this code might be useful:
/*
int index = 0;
int c = EOF;
while ((c = getchar()) && c != EOF) {
// ...
}
*/
// step 3: print number of unknown words
printf("%d\n", counter);
freeDict(dictionary);
return 0;
}
Could you help please? I believe it has something to do with allocation but I'm still stuck. Thank you!
Related
So i have this program that has a structure and an array. The array is conj_jogos which is an array of a structure called jogo with MAX_SIZE (MAX_SIZE being 5).
Structure:
typedef struct
{
int id;
char equipas[2][1024];
int pont[2];
char nome[MAX_CHARS];
} jogo;
So to create this array i allocated memory in my main function like this:
int main()
{
char nome_jg[MAX_CHARS], team1[MAX_CHARS], team2[MAX_CHARS];
int score1;
int score2;
int i;
conj_jogos = (jogo*)calloc(MAX_SIZE,sizeof(jogo));
while ((c = getchar()) != x)
scanf("%1023[^:\n]:%1023[^:\n]:%1023[^:\n]:%d:%d",nome_jg,team1,team2,&score1,&score2);
remove_esp(nome_jg); /*removes the 1st char if its a space*/
a(nome_jg,team1,team2,score1,score2);
ident++;
}
free(conj_jogos);
return 0;
}
The problem is that valgrind is saying that i have a heap overflow on the "a" function and i dont know why so if someone can help i would appreciate it a lot.
Program:
#include<stdlib.h>
#include<stdio.h>
#include <string.h>
#define MAX_CHARS 1024 /* Max chars for a word*/
#define MAX_SIZE 5 /*Max size for an array*/
jogo *conj_jogos; /*array that saves the jogos*/
static int size_until2 = 0; /*count the size of conj_jogos*/
void a(char nome_jg[],char team1[],char team2[],int score1,int score2)
{
if (jogo_in(nome_jg) == 1) //confirms if the string nome_jg is in conj_jogos
{
printf("%d Jogo existente.\n",line);
line++;
}
else if ((nome_in_sis(team1) == 0) || (nome_in_sis(team2) == 0)) //confirms if the strings team1 or team2 are in sistem_eq
{
printf("%d Equipa inexistente.\n",line);
line++;
}
else
{
if (size_until2 < MAX_SIZE)
{
conj_jogos[size_until2] = cria_jogo(nome_jg,team1,team2,score1,score2);
size_until2++;
line++;
}
else
{
jogo *temp;
size_until2++;
temp = realloc(conj_jogos,sizeof(jogo)*(size_until2+1));
free(conj_jogos);
conj_jogos = temp;
conj_jogos[size_until2] = cria_jogo(nome_jg,team1,team2,score1,score2);
size_until2++;
line++;
free(temp);
}
}
}
I cannot re-run the code because so much relevant functions are not included in your code. But I would try :
conj_jogos = realloc(conj_jogos,sizeof(jogo)*(size_until2+1));
instead of :
temp = realloc(conj_jogos,sizeof(jogo)*(size_until2+1));
And you may also try:
*(conj_jogos + (size_until2 * sizeof(jogo))) = cria_jogo(nome_jg,team1,team2,score1,score2);
size_until2++;
Instead of:
conj_jogos[size_until2] = cria_jogo(nome_jg,team1,team2,score1,score2);
size_until2++;
While I was making a dictionary using C it showed me the meaning of the word which is not present in the dictionary itself. I checked the function for checking the equality of two strings and its working fine but when I implement that function in the lookup function of the dictionary where it searches for the word shows me the meaning of the word it is not working as I intended it to do. I am not looking for a good performance I was just revising my basics in the function and simple boolean functions.
Here is the Code:
struct Entry
{
char word[50];
char defination[500];
};
bool isEqualString(const char str1[], const char str2[])
{
bool flag = true;
int i;
for(i = 0; str1[i] != '\0'; i++)
if (str1[i] == str2[i])
{
flag = true;
}
if ((str1[i] == str2[i]) && str1[i] == '\0')
flag = true;
else
flag = false;
return flag;
}
int Lookup(const struct Entry dictionary[], const char search[], int entries)
{
int i;
bool isEqualString(const char str1[], const char str2[]);
for (i = 0; i < entries; i++)
{
if (isEqualString(search, dictionary[i].word))
{
printf("%d and its indice = %d\n", isEqualString(search, dictionary[i].word), i);
return i;
}
}
return -1;
}
void main()
{
struct Entry dictionary[2] =
{ {"Hello", "It means hi."},
{"Dead", "It means you are dead"} };
int Lookup(const struct Entry dictionary[], const char search[], int entries);
int entries = 2, searchEntry;
char searchWord[10];
printf("Give us a word to find in the dictionary: \n");
scanf("%s", searchWord);
searchEntry = Lookup(dictionary, searchWord, entries);
if (searchEntry != (-1))
printf("\n%s %s", dictionary[searchEntry].word, dictionary[searchEntry].defination);
}
the logic in this function:
bool isEqualString(const char str1[], const char str2[])
is not quite right.
Suggest:
#include <stdbool.h>
#include <string.h>
bool isEqualString(const char str1[], const char str2[])
{
bool flag = true;
for( size_t i = 0; i < (strlen(str1)+1); i++ )
{
if ( str1[i] != str2[i] )
{
flag = false;
break;
}
}
return flag;
}
I am currently practicing using pointers for an upcoming exam and am running through a few practice questions to brush up on them. I want to make my own version of the strrchr function with the given function signature:
char* mystrrchr(char*s, int c) {
And the main field:
int main(void) {
char* s = "ENCE260";
char* foundAt = mystrrchr(s, 'E');
if (foundAt == NULL) {
puts("Not found");
}
else {
printf("%zd\n", foundAt - s);
}
}
And I want the code to work without any changes to the main and function signature.
I want to return the index of the last time the character c appears in a string s as an integer. The jist of the code is fine, I just am unsure how to use the pointers correctly in this situation to return the desired output. For reference the error I am receiving is that I am making a pointer from integer without a cast.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <assert.h>
char* mystrrchr(char*s, int c) {
int position;
int len = strlen(s);
int i = 0;
while (i < len) {
if (c == s[i]) {
position = i;
i++;
}
else {
i++;
}
}
return position;
}
int main(void) {
char* s = "ENCE260";
char* foundAt = mystrrchr(s, 'E');
if (foundAt == NULL) {
puts("Not found");
}
else {
printf("%zd\n", foundAt - s);
}
}
That is my code thus far.
First you could change
char*mystrrchr(char*s, int c) {
...
return position;
}
to
char*mystrrchr(char*s, int c) {
...
return s + position;
}
because the first version returns the relative position.
Then you also need to initialize position:
char*mystrrchr(char*s, int c) {
int position = -1;
...
}
And then return NULL if nothing was found:
char*mystrrchr(char*s, int c) {
int position = -1;
...
if(position == -1) return NULL;
else return s + position;
}
At this point the function works correctly.
But you could improve the performance by using
while (s[i] != '\0')
instead of using strlen, as Jonathan Leffler pointed out in a comment.
Define mystrrchr as int mystrrchr and call int foundAt = mystrrchr(. Then printf("%d\n", foundAt).
char* mystrrchr(char*s, int c) {
if ( s == NULL ) return NULL;
char *position = NULL;
int i = 0;
while (s[i] != '\0' ) {
if (c == s[i]) {
position = &s[i];
}
i++;
}
return position;
}
You can also go backwards:
char* mystrrchr2(char*s, int c) {
if ( s == NULL ) return NULL;
char *position = NULL;
int i = strlen(s) - 1;
while (i > -1) {
if (c == s[i]) {
position = &s[i];
break;
}
i--;
}
return position;
}
I am having an error with the code we are using, was wondering if someone could help debug. Seems like we are getting a malloc error. Thanks.
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
int result = 0;
Word * current_pointer = malloc (sizeof(Word*));//creates a temporary variable for each pointer in the array
for (i=0; i<word_counter; i++) {
current_pointer = *(array+i); //accesses the current pointer
result = strcmp(norm_word, (current_pointer -> word)); //compares the string to each stored string
if (result == 0) {
found = true;
(current_pointer->freq)++;
break;
}
}
if(!found) {
if(pointer_counter == word_counter) {
array = realloc(array, sizeof(array)*2);
pointer_counter*=2;
}
Word * new_pointer = (Word*) malloc (sizeof(Word*));
strcpy(new_pointer -> word, norm_word);
*(array + (pointer_counter - 1)) = new_pointer;
word_counter++;
}
;
}
All pointers have the same size on your system. So a sizeof always returns the same size for any pointer. You want to allocate for the structure, so you need to use sizeof on the name without the star. malloc will return the pointer to that block of memory afterwards.
Here is a short implementation:
#include <iostream>
#include <string>
typedef struct
{
int num;
int numnum;
}numbers;
int main(int argc, char ** argv)
{
numbers* n = (numbers*)malloc(sizeof(numbers));
n->num = 1;
n->numnum = 2;
free(n);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAXSIZE 64
typedef struct word {
char word[MAXSIZE];
int freq;
} Word;
int word_counter = 0;
size_t pointer_counter = 16;//Number of pointers that ensure
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
Word *current_pointer = *array;
for (i=0; i<word_counter; i++) {
if(strcmp(norm_word, current_pointer->word) == 0){
found = true;
current_pointer->freq++;
break;
}
++current_pointer;
}
if(!found) {
if(pointer_counter == word_counter) {
pointer_counter *= 2;
*array = realloc(*array, sizeof(Word)*pointer_counter);
}
Word *new_pointer = *array + word_counter;
new_pointer->freq = 1;
strcpy(new_pointer->word, norm_word);
++word_counter;
}
}
int main(void){
Word *vocabulary = calloc(pointer_counter, sizeof(Word));
char norm_word[MAXSIZE];
while(1==scanf("%s", norm_word)){
readWords(norm_word, &vocabulary);
}
{
int i;
for(i = 0; i < word_counter; ++i){
printf("%s(%d)\n", vocabulary[i].word, vocabulary[i].freq);
}
}
free(vocabulary);
return 0;
}
I'm trying to store strings into dynamical allocated memory. I'm able to break the strings down and store them within the members of the struct and print them perfectly within the function readFile, but when it comes to printing it in main, it's only printing the last scan and everything else is null. I'm thinking that maybe I'm not allocating the array of structures correctly. Here's my program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#ifdef _MSC_VER
#include <crtdbg.h> // needed to check for memory leaks (Windows only!)
#endif
#define MEM_ERROR printf("Not enough memory\n")
#define FLUSH while( getchar() != '\n' )
typedef struct
{
char id[5];
char *name;
int *sales;
int total;
int low;
int high;
}PERSON;
typedef struct
{
int worker;
int weeks;
PERSON *pAry;
}HEADER;
// Function Declaration
void valiFile(char nameIn[]);
FILE* openFile(char nameIn[]);
void getHeader(FILE* fpFile, HEADER *pHead);
PERSON* aloPerson(int workers);
void readFile(FILE* fpFile, HEADER *pHead);
char* aloName(HEADER *pHead, int strCount);
void repeat(char nameIn[]);
int main ( void )
{
// Local Declaration
FILE* fpFile;
char nameIn[25];
char *endPro = "end";
HEADER *pHead = (HEADER*)calloc(1, sizeof(HEADER));
// Statement
printf("Please select file to to open.\nsales or sales_2: ");
scanf("%s", nameIn);
FLUSH;
do
{
valiFile(nameIn);
fpFile = openFile(nameIn);
getHeader(fpFile, pHead);
readFile(fpFile, pHead);
//printf("%s\n", pHead->pAry[0].id);
//free(pHead);
repeat(nameIn);
}
return 0;
}// main
/* ========== valiFile ==========
========== */
void valiFile(char nameIn[])
{
// Local Declaration
char *file = "sales";
char *file2 = "sales_2";
int i;
int check = 0;
// Statement
do
{
for(i = 0; nameIn[i]; i++)
{
nameIn[i] = tolower(nameIn[i]);
}
if(strcmp(file, nameIn) != 0)
{
if(strcmp(file2, nameIn) != 0)
{
printf("\nPlease enter a valid file.\n");
printf("sales or sales_2: ");
scanf("%s", nameIn);
FLUSH;
}
else
check = 1;
}
else
check = 1;
}
while(check != 1)
;
return;
}// valiFile
/* ========== openFile ==========
========== */
FILE* openFile(char nameIn[])
{
// Local Declaration
FILE* fpFile;
char *strSale = "sales";
// Statement
if(strcmp(strSale, nameIn) == 0)
{
fpFile = fopen("sales.txt", "r");
if(fpFile == NULL)
{
printf("File didn't read correcty.\n");
exit(100);
}
}
else
{
fpFile = fopen("sales_2.txt", "r");
if(fpFile == NULL)
{
printf("File didn't read correcty.\n");
exit(100);
}
}
return fpFile;
}// openFile
/* ========================= getHeader ========================
============================================================*/
void getHeader(FILE* fpFile, HEADER *pHead)
{
// Local Declaration
int worker, salesWeek, i;
PERSON *list;
// Statement
fscanf(fpFile, "%d %d", &worker, &salesWeek);
list = aloPerson(worker);
HEADER header = {worker, salesWeek, list};
*pHead = header;
return;
}// getHeader
/* aloPerson
*/
PERSON* aloPerson(int worker)
{
// Local Declaration
PERSON *list;
// Statement
list =(PERSON*)calloc(worker, sizeof(PERSON));
if(list == NULL)
{
MEM_ERROR, exit(103);
}
return list;
}// aloPerson
/* readFile
*/
void readFile(FILE* fpFile, HEADER *pHead)
{
// Local Declaration
char temp[50];
int strCount = 0;
char *loc;
char *ptr;
int i;
// Statement
fscanf(fpFile, "%*d %*d");
for(i = 0; i < pHead->worker; i++)
{
while(fgets(temp, sizeof(temp), fpFile))
{
ptr = temp;
loc = strchr(temp, ' ');
strncpy(pHead->pAry[i].id, temp, (loc - ptr));
ptr += (loc - temp);
*ptr++;
loc = strchr(temp, ';');
strCount = (loc - ptr);
pHead->pAry[i].name = aloName(pHead, strCount);
strncpy(pHead->pAry[i].name, ptr, (loc - ptr));
ptr += (loc - ptr);
printf("%s\n", pHead->pAry[i].name);
}
}
return;
}// readFile
/* aloName
*/
char* aloName(HEADER *pHead, int strCount)
{
// Local Declaration
char *names;
// Statement;
names = malloc((strCount + 1)*sizeof(char));
return names;
}