Function to read in a word into a struct array - c

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;
}

Related

Why when I try to access array of structures it returns random values? (C)

I have a function that returns pointer to array of structures. However, when I try to access any of the values of returned structure, it prints random symbols.
#include <stdio.h>
struct MY {
int i;
char string[30];
};
struct MY* myFunc() {
struct MY arrayOfStructs[3];
struct MY tempStruct;
struct MY* arrayOfStructsPtr = arrayOfStructs;
tempStruct.i = 1;
tempStruct.string[0] = 'H';
tempStruct.string[1] = 'i';
arrayOfStructs[0] = tempStruct;
tempStruct.i = 2;
tempStruct.string[0] = 'L';
tempStruct.string[1] = 'o';
arrayOfStructs[1] = tempStruct;
tempStruct.i = 3;
tempStruct.string[0] = 'M';
tempStruct.string[1] = 'Y';
arrayOfStructs[2] = tempStruct;
return arrayOfStructsPtr;
}
int main()
{
struct MY* arrayOfStructs = myFunc();
for(int i = 0; i < 3; i++) printf("%d\n", arrayOfStructs[i].i);
return 0;
}
You return a reference to the local array which stops to exist when function returns. It is Undefined Behaviour.
You need:
struct MY* myFunc(void) {
static struct MY arrayOfStructs[3];
or
struct MY* myFunc(void) {
struct MY *arrayOfStructs = malloc(3 * sizeof(*arrayOfStructs));
or pass the buffer allocated by the caller.
struct MY *myFunc(struct MY *arrayOfStructs) {
/* .... */
If you dynamically allocate memory you should free it after use
You return a pointer to a local variable which is out of scope when the function returns. Some alternatives:
The caller main() allocates variable and pass it to myFunc() for initialization.
#include <stdio.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
void myFunc(struct MY arrayOfStructs[N]) {
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < N; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
}
int main() {
struct MY arrayOfStructs[N];
myFunc(arrayOfStructs);
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
}
As used here you don't really need to store i as it's just index of the struct + 1.
myFunc() dynamically allocate the variables with malloc() and return the pointer. Caller is responsible for free'ing the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
struct MY *myFunc() {
struct MY *arrayOfStructs = malloc(N * sizeof *arrayOfStructs);
if(!arrayOfStructs) return NULL; // malloc failed
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < sizeof strings / sizeof *strings; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
return arrayOfStructs;
}
int main() {
struct MY *arrayOfStructs = myFunc();
if(!arrayOfStructs) return 1;
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
free(arrayOfStructs);
}
myFunc(): make variables static (not recommended).

Trouble using free() on a char *variable from a struct [duplicate]

This question already has answers here:
How can I correctly assign a new string value?
(4 answers)
Closed 3 months ago.
I am learning C and I have trouble correctly using free() on char *word from my struck. The code works in its currect form but crashes if I uncomment the line in the for loop ant the end of main. How do I free it correctly?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <errno.h>
typedef struct container
{
char *word;
int amount;
} wordContainer;
wordContainer *SetupWordList(int *size, int *lastInit, wordContainer *listIN, bool realloc);
int main(int argc, const char *argv[])
{
wordContainer *listWords = NULL;
int listSize = 10;
int listLastInit = 0;
listWords = SetupWordList(&listSize, &listLastInit, listWords, false);
for (int i = 0; i < listSize/2; i++)
{
fprintf(stdout, "Word: %s | Amount: %i\n", listWords[i].word, listWords[i].amount);
}
for (int i = 0; i < listSize/2; i++)
{
//free(listWords[i].word);
}
free(listWords);
exit(EXIT_SUCCESS);
}
wordContainer *SetupWordList(int *size, int *lastInit, wordContainer *listIN, bool reallocate)
{
if(!reallocate)
{
listIN = (wordContainer *)malloc((*size) * sizeof(wordContainer));
if (listIN == NULL)
{
fprintf(stderr, "Could not allocate enought memory.");
exit(EXIT_FAILURE);
}
}
else
{
listIN = (wordContainer *)realloc(listIN, (*size) * sizeof(wordContainer));
}
for (int i = (*lastInit); i < (*size); i++)
{
listIN[i].word = (char *)malloc(50*sizeof(char));
listIN[i].word = "empty";
listIN[i].word = "cow";
listIN[i].amount = 0;
}
*lastInit = *size;
*size *= 2;
return listIN;
}
I have honestly no idea what is the problem here, everything I could find online sugested that I am maybe using free() multiple times on the same location or that I have overwriten buffers but I don't see how this is the case here.
for (int i = (*lastInit); i < (*size); i++)
{
listIN[i].word = (char *)malloc(50*sizeof(char));
strcpy(listIN[i].word, "empty");
}
Solved my problem. Did not realise that "listIN[i].word = "empty";" makes me lose my mallocated pointer.

Memory allocation of an array of struct in a C function

I am trying to pass the pointer to a struct to a function to create an array of the struct there. The overall idea is:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct items
{
int number;
char *name;
char *description;
} ITEMS;
int process(ITEMS **items)
{
int i = 0, something = 200;
// for loop is for the representation.
// The actual data come from MySQL row loop
for (int j = 100; j < something; j++)
{
// Growing the array of struct
items = realloc(items, (i + 1) * sizeof(*items));
// Adding items here
items[i]->number = j;
strcpy(items[i]->name, "Some name"); // it comes from a variable
strcpy(items[i]->description, "Some text");
i++;
}
return i;
}
int main()
{
ITEMS *items;
int num_items = process(&items);
for (int i = 0; i < num_items; i++)
{
printf("%d - %s - %s\n", items[i].number, items[i].name,
items[i].description);
}
return 0;
}
but I am struggling with reallocating the memory for the struct (and with the pointers too).
The pointer to pointer must be de-referenced in the function so the allocation is visible in the calling function.
strdup is use to allocate memory to the pointers in the structure.
It is better to use a temporary variable for the reallocation.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct items
{
int number;
char *name;
char *description;
} ITEMS;
int process(ITEMS **items)
{
int i = 0;
// Growing the array of struct
*items = realloc(*items, (i + 1) * sizeof(**items));
// repeating this step in a loop of adding items
// Adding items here
(*items)[i].number = 72;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
*items = realloc(*items, (i + 1) * sizeof(**items));
// another item
(*items)[i].number = 88;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
return i;
}
int main()
{
ITEMS *items = NULL;
int num_items = process(&items);
for (int i = 0; i < num_items; i++)
{
printf("%d - %s - %s\n", items[i].number, items[i].name, items[i].description);
}
return 0;
}
With better error detection
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct items
{
int number;
char *name;
char *description;
} ITEMS;
int process(ITEMS **items)
{
ITEMS *temp = NULL;
int i = 0;
// Growing the array of struct
if ( NULL == ( temp = realloc(*items, (i + 1) * sizeof(**items)))) {
fprintf ( stderr, "realloc problem\n");
return i;
}
*items = temp;
// repeating this step in a loop of adding items
// Adding items here
(*items)[i].number = 72;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
if ( NULL == ( temp = realloc(*items, (i + 1) * sizeof(**items)))) {
fprintf ( stderr, "realloc problem\n");
return i;
}
*items = temp;
// another item
(*items)[i].number = 88;
(*items)[i].name = strdup( "Some name"); // it comes from a variable
(*items)[i].description = strdup ("Some text");
i++;
return i;
}
int main()
{
ITEMS *items = NULL;
int num_items = process(&items);
for (int i = 0; i < num_items; i++)
{
printf("%d - %s - %s\n", items[i].number, items[i].name, items[i].description);
}
return 0;
}

I get a weird sysmalloc: Assertion error when using a trie

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!

Getting a seg-fault when setting value of pointer

There really isnt much I can say here.
Here is my lexer file:
#include <ctype.h>
#include <stdio.h>
#include "vector.h"
enum TokenType
{
tok_let = -1,
tok_iden = -2,
tok_int = -3,
tok_end = -4
};
typedef struct
{
int type;
char* str_d;
int int_d;
} Token;
char* seed;
int i=0;
char next_char()
{
i++;
return seed[i-1];
}
vector* get_tokens(char* in)
{
vector *toks;
vector_new(toks);
seed = in;
char tap;
if(isalpha(tap = next_char()))
{
char* iden_str="";
iden_str += tap;
char nc;
while(isalnum((nc = next_char())))
iden_str += nc;
if(iden_str == "let")
{
Token* tp;
tp->type = tok_let;
vector_push(toks, (void*)tp);
goto out;
}
Token* tp;
tp->type = tok_iden;
tp->str_d = iden_str;
vector_push(toks, (void*)tp);
}
out:
return toks;
}
int main()
{
vector* toks;
toks = get_tokens("let");
Token* ftok = (Token*)vector_get(toks, 0);
switch(ftok->type)
{
case tok_let:
printf("Its a let\n");
break;
default:
printf("Ummm lol nup\n");
break;
}
}
And here is my vector file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct d_vector
{
void **items;
int capacity;
int total;
} vector;
void vector_new(vector *v)
{
v->capacity = 4;
v->total = 0;
v->items = malloc(sizeof(void*)*v->capacity);
}
int vector_total(vector *v)
{
return v->total;
}
static void vector_resize(vector *v, int capacity)
{
void** items = realloc(v->items, sizeof(void*) * capacity);
if(items)
{
v->items = items;
v->capacity = capacity;
}
}
void vector_push(vector *v, void* item)
{
if(v->capacity == v->total)
vector_resize(v, v->capacity * 2);
v->items[v->total++] = item;
}
void vector_set(vector *v, int index, void* item)
{
if(index >= 0 && index < v->total)
v->items[index] = item;
}
void* vector_get(vector *v, int index)
{
if(index >= 0 && index < v->total)
return v->items[index];
return NULL;
}
void vector_remove(vector *v, int index)
{
if(index < 0 || index >= v->total)
return;
v->items[index] = NULL;
for (int i = 0; i < v->total - 1; i++) {
v->items[i] = v->items[i + 1];
v->items[i + 1] = NULL;
}
v->total--;
if (v->total > 0 && v->total == v->capacity / 4)
vector_resize(v, v->capacity / 2);
}
void vector_free(vector *v)
{
free(v->items);
}
When I run the code above, I get a Seg-Fault.
How can this be happening? Here is the output of gdb:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400656 in vector_new (v=0x1) at vector.h:14
14 v->capacity = 4;
As you can see, its segfaulting when i set the vector capacity!
But why?
It segfaults because you dereference a garbage pointer:
vector* get_tokens(char* in)
{
vector *toks;
vector_new(toks);
The variable toks is not assigned to anything meaningful, just whatever garbage value happens to be floating about. This gets passed into vector_new() which immediately dereferences it:
void vector_new(vector *v)
{
v->capacity = 4;
Then BAM! it blows up because v points nowhere appropriate.
Try mallocing a vector before making your call to vector_new() or put the malloc in vector_new() and have it return the pointer to the new vector instead. It's also a good idea to check the return value from malloc().
You might try something like:
vector *vector_new(void)
{
vector *v;
if ( (v = malloc(sizeof(*v))) == NULL ) {
/* Replace with something appropriate */
exit(EXIT_FAILURE);
}
v->capacity = 4;
v->total = 0;
if ( (v->items = malloc(sizeof(*v->items)*v->capacity)) == NULL ) {
/* Replace with something appropriate */
exit(EXIT_FAILURE);
}
return v;
}
Then change how you call it:
vector* get_tokens(char* in)
{
vector *toks;
toks = vector_new();
And for every malloc(), let there be a free(). Don't forget to clean up this allocation too or you'll leak memory:
void vector_free(vector *v)
{
free(v->items);
free(v);
}
(You defined a vector_free(), but never called it. You might want to consider doing that too.)
invalid pointer dereference happened
vector *toks;
vector_new(toks);
Should be
vector *toks = (vector*)malloc(sizeof(vector));
vector_new(toks);

Resources