I accomplished the following task to practice allocating on the heap.
- reading words from stdin
- sorting them in lexicographical order
- printing the sorted words to stdout
To accomplish this is allocate the size of each word and the count of words.
I would like to hear any suggestions for improvements. Is there maybe an easier way to sort the words?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
struct Word {
char* signs; // pointer to a word
int sz;
int capacity;
};
// allocates factor 2 of the current capacity
void reserve_space_for_letter(char **c, int *capacity)
{
if (*capacity == 0) { // allocate the first time
*capacity = 1;
*c = malloc(sizeof(char) * ((*capacity)));
}
else {
*capacity *= 2; // double the new capacity
*c = realloc(*c, sizeof(char) * (*capacity));
}
}
void reserve_space_for_words(struct Word** w, int *capacity)
{
if (*capacity == 0) { // allocate the first time
*capacity = 1;
*w = malloc(sizeof(struct Word) * ((*capacity)));
}
else {
*capacity *= 2; // double the new capacity
*w = realloc(*w, sizeof(struct Word) * (*capacity));
}
}
void print_words(struct Word* words,int sz)
{
int i = 0;
for (i = 0; i < sz; ++i) {
printf("%s ", words[i].signs);
}
}
int cmp(void const *lhs, void const *rhs) {
struct Word left = *(const struct Word *)lhs;
struct Word right = *(const struct Word *)rhs;
return strcmp(left.signs, right.signs);
}
void deallocate_words(struct Word* words, int sz)
{
int i = 0;
for (i = 0; i < sz; ++i) {
free(words[i].signs);
}
free(words);
}
int main()
{
struct Word* words; // Pointer to several words
int sz = 0;
int capacity = 0;
int ch=0;
bool in_word = true;
reserve_space_for_words(&words, &capacity); // reserve space for first word
++sz;
words[sz - 1].capacity = 0;
words[sz - 1].sz = 0;
while ((ch = getc(stdin)) != EOF) {
if (words[sz - 1].sz == words[sz - 1].capacity) { // if current letter sz = capacity
reserve_space_for_letter(&words[sz - 1].signs, &words[sz - 1].capacity);
}
if (!isalnum(ch) && in_word) { // end of current word;
words[sz - 1].signs[words[sz - 1].sz] = '\0';
in_word = false;
continue;
}
else if (!isalnum(ch) && !in_word) { // not in a word so dont bother doing sth
continue;
}
else if (isalnum(ch) && !in_word) { // the next word is reached
in_word = true;
if (sz == capacity) { // maximum size of words reached
reserve_space_for_words(&words, &capacity); // reserve space for first word
}
++sz; // iterate to the new word
words[sz - 1].capacity = 0;
words[sz - 1].sz = 0;
reserve_space_for_letter(&words[sz - 1].signs, &words[sz - 1].capacity);
}
words[sz - 1].signs[words[sz - 1].sz] = ch; // append the sign in the array
++words[sz - 1].sz;
}
qsort(words, sz, sizeof(struct Word), cmp);
print_words(words, sz);
deallocate_words(words, sz);
getchar();
return 0;
}
strcmp
but i didnt included#include <string.h>
the c compiler of visual studio 2017 didnt cared. i turned it to cpp and got more warnings. is it a good practice to do (just for debug turn to c++) that because c++ catches more errors even in c? \$\endgroup\$