0

So I'm supposed to do the sorting algorithm as a CS homework.

It should read arbitrary number of words each ending with '\n'. After it reads the '.', it should print the words in alphabetical order.

E.g.: INPUT: apple dog austria Apple

OUTPUT: Apple apple Austria dog

I want to store the words into a struct. I think that in order to work it for arbitrary number of words I should make the array of structs.

So far I've tried to create a typedef struct with only one member (string) and I planned to make the array of structs from that, into which I would then store each of the words.

As for the "randomness" of the number of words, I wanted to set the struct type in main after finding out how many words had been written and then store each word into each element of the struct array.

My problem is: 1. I don't know how to find out the number of words. The only thing I tried was making a function which counts how many times the '\n' occured, though it didn't work very good.

as for the datastructure, I've came up with struct having only one string member:

typedef struct{
char string[MAX];
}sort;

then in main function I firstly read a number of words to come (not the actual assignment but only for purposes of making the code work)

and after having the "len" I declared the variable of type sort:

int main(){
/*code, scanf("%d", &len) and stuff*/
sort sort_t[len];

for(i = 0; i < len; i++){
    scanf("%s", sort_t[i].string);
}

Question: Is such thing "legal" and do I use a good approach?

Q2: How do I get to know the number of words to store (for the array of structs) before I start storing them?

gudok
  • 4,029
  • 2
  • 20
  • 30
DemoVision
  • 71
  • 6
  • [Variable-length arrays](https://en.wikipedia.org/wiki/Variable-length_array) were introduced with the C99 standard. – Some programmer dude May 23 '19 at 14:04
  • @DemoVision You cn dynamically reallocate the array each time new words are added. Or you can use a list of words. To sort the array you can use the standard function qsort declared in the header stdlib.h. – Vlad from Moscow May 23 '19 at 14:11
  • I would recommend you take a look at **linked list data structure**, with this you could use each struct as a word and than you could apply your sort algorithm – Esdras Xavier May 23 '19 at 14:16
  • 1
    @Esdras Xavier thank you for the answer. If I get it correctly, could I create array of structs with a pointer always pointing to another element of struct array? – DemoVision May 24 '19 at 05:44
  • @Vlad from Moscow could you maybe help me on how to allocate it? I think firstly I should use malloc and then for every other realloc. But how do I get to know the number of words? Via counting the \n? Or how? And, thanks for answering! – DemoVision May 24 '19 at 05:49
  • There's not much point in using a `struct` with one element. Why don't you just `typedef char sort[MAX]`? – Armali May 24 '19 at 08:32
  • @DemoVision Yes that right, this ideia could be a solution – Esdras Xavier May 24 '19 at 22:12

1 Answers1

0

IMHO the idea of reserving the same maximal storage for each and every string is a bit wasteful. You are probably better off sticking to dynamic NUL-terminated strings as usually done in C code. This is what the C library supports best.

As for managing an unknown number of strings, you have a choice. Possibility 1 is to use a linked list as mentioned by Xavier. Probably the most elegant solution, but it could be time-consuming to debug, and ultimately you have to convert it to an array in order to use one of the common sort algorithms.

Possibility 2 is to use something akin to a C++ std::vector object. Say the task of allocating storage is delegated to some "bag" object. Code dealing with the "bag" has a monopoly on calling the realloc() function mentioned by Vlad. Your main function only calls bag_create() and bag_put(bag, string). This is less elegant but probably easier to get right.

As your focus is to be on your sorting algorithm, I would rather suggest using approach #2. You could use the code snippet below as a starting point.

#include  <stdlib.h>
#include  <string.h>
#include  <stdio.h>

typedef struct {
    size_t    capacity;
    size_t    usedSlotCount;
    char**    storage;
} StringBag;


StringBag* bag_create()
{
    size_t initialSize = 4;  /* start small */
    StringBag*   myBag = malloc(sizeof(StringBag));

    myBag->capacity      = initialSize;
    myBag->usedSlotCount = 0;
    myBag->storage       = (char**)malloc(initialSize*sizeof(char*));

    return myBag;
}

void bag_put(StringBag* myBag, char* str)
{
    if (myBag->capacity == myBag->usedSlotCount) {
        /* have to grow storage */
        size_t  oldCapacity = myBag->capacity;
        size_t  newCapacity = 2 * oldCapacity;
        myBag->storage = realloc(myBag->storage, newCapacity*sizeof(char*));
        if (NULL == myBag->storage) {
            fprintf(stderr, "Out of memory while reallocating\n");
            exit(1);
        }
        fprintf(stderr, "Growing capacity to %lu\n", (unsigned long)newCapacity);
        myBag->capacity = newCapacity;
    }

    /* save string to new allocated memory, as this */
    /* allows the caller to always use the same static storage to house str  */

    char* str2 = malloc(1+strlen(str));
    strcpy(str2, str);
    myBag->storage[myBag->usedSlotCount] = str2;
    myBag->usedSlotCount++;
}


static char inputLine[4096];


int main()
{
    StringBag*  myBag = bag_create();

    /* read input data  */
    while(scanf("%s", inputLine) != EOF) {
        if (0 == strcmp(".", inputLine))
            break;
        bag_put(myBag, inputLine);
    }

    /* TODO: sort myBag->storage and print the sorted array */

}
jpmarinier
  • 4,427
  • 1
  • 10
  • 23
  • `ultimately you have to convert it to an array in order to use one of the common sort algorithms.` Uhmm, no you don't! You can bubble sort a linked list of structs by swapping pointers. No need to put into an array. – Deanie Jun 24 '20 at 16:02