user1032719
user1032719

Reputation:

Returning an array of structs without pointers in C

I have been working my way through Kochan's "Programming in C" 3rd Edition on my own to get ready for grad school next year, and I am stuck for the first time. I am a chapter away from pointers, yet the exercise at the end of this most recent chapter on character strings has a problem that my own research seems to indicate can only be solved by using pointers.

The question has to do with a data structure entry:

struct entry {
    char word[15];
    char definition[50];
};

We create an array of entries:

struct entry dictionary[10] = 
{{"aardvark", "a burrowing African mammal"},
 {"abyss", "a bottomless pit"},
 {"addle", "to become confused"},
 {"aerie", "a high nest"},
 {"ajar", "partially opened"},
 {"acumen", "mentally sharp; keen"},
 {"affix", "to append; attach"},
 {"agar", "a jelly made from seaweed"},
 {"ahoy", "a nautical call of greeting"},
 {"aigrette", "an ornamental cluster of feathers"}};

The prompt reads: "Write a function called dictionary_sort that sorts a dictionary, as defined [above], into alphabetical order."

I know there are subtleties to structures and arrays in relation to functions and how functions can take them as arguments or give them back as returned values. The only way that seemed to make sense to me was returning a struct, or specifically an array of structs, but I do not think I applying it correctly here:

struct entry dictionary_sort(struct entry dictionary)

In total, my current version of the program is as follows:

#include <stdio.h>
#include <stdbool.h>

struct entry {
    char word[15];
    char definition[50];
};

// Function to compare two character strings

int compare_strings(const char s1[], const char s2[])
{
    int i = 0, answer; 

    while (s1[i] == s2[i] && s1[i] != '\0' && s2[i] != '\0')
        i++;

    if (s1[i] < s2[i])
        answer = -1; // s1 < s2
    else if (s1[i] == s2[i])
        answer = 0; // s1 == s2
    else
        answer = 1; // s1 > s2

    return answer;
}

// Function to sort a dictionary structure

struct entry dictionary_sort(struct entry dictionary[])
{
    int dictionary_length = sizeof(dictionary) / sizeof(dictionary[0]);
    int i, j, minimum;
    struct entry temp;

    for (i = 0; i < dictionary_length; i++) {
        minimum = i;
        for (j = i + 1; j < dictionary_length; j++) {
            if (compare_strings(dictionary[j].word, 
                                dictionary[minimum].definition) == -1)
                minimum = j;
        }
        temp = dictionary[minimum];
        dictionary[minimum] = dictionary[i];
        dictionary[i] = dictionary[minimum];
    }

    return dictionary;
}

int main(void)
{
    struct entry dictionary[10] =
    {{"aardvark", "a burrowing African mammal"},
     {"abyss", "a bottomless pit"},
     {"addle", "to become confused"},
     {"aerie", "a high nest"},
     {"ajar", "partially opened"},
     {"acumen", "mentally sharp; keen"},
     {"affix", "to append; attach"},
     {"agar", "a jelly made from seaweed"},
     {"ahoy", "a nautical call of greeting"},
     {"aigrette", "an ornamental cluster of feathers"}};
    int i, dictionary_length = sizeof(dictionary) / sizeof(dictionary[0]);

    dictionary = dictionary_sort(dictionary);

    for (i = 0; i < dictionary_length; i++)
        printf("%s - %s.\n", dictionary[i].word, dictionary[i].definition);

    return 0;
}

The string comparison function behaves as expected since it is only returning an integer. I am really at a loss as to how to have the desired functionality without knowledge of pointers. There are enough examples with pointers to look up, but I am curious what fundamental principle I am missing here because I feel as though everything else in the book has come very naturally to me.

Thank you in advance!

Upvotes: 0

Views: 2586

Answers (4)

user1032719
user1032719

Reputation:

While not perfect and still requiring the explicit definition of pointers, this answer is within the scope of the problem and the book by not just calling libraries.

#include <stdio.h>
#include <stdbool.h>

struct entry {
    char word[15];
    char definition[50];
};

// Function to compare two character strings

int compare_strings(const char s1[], const char s2[])
{
    int i = 0, answer; 

    while (s1[i] == s2[i] && s1[i] != '\0' && s2[i] != '\0')
        i++;

    if (s1[i] < s2[i])
        answer = -1; // s1 < s2
    else if (s1[i] == s2[i])
        answer = 0; // s1 == s2
    else
        answer = 1; // s1 > s2

    return answer;
}

// Function to sort a dictionary structure

void dictionary_sort(struct entry *dictionary, int dictionary_length)
{
    int i, j, minimum;
    struct entry temp;

    for (i = 0; i < dictionary_length - 1; i++) {
        minimum = i;
        for (j = i + 1; j < dictionary_length; j++) {
            if (compare_strings(dictionary[j].word, 
                                dictionary[minimum].word) == -1)
                minimum = j;
        }
        temp = dictionary[minimum];
        dictionary[minimum] = dictionary[i];
        dictionary[i] = temp;
    }
}

// Prints the dictionary in its current state

void print_dictionary(struct entry *dictionary, int dictionary_length)
{
    int i;

    for (i = 0; i < dictionary_length; i++) {
        printf("%s - %s.\n", dictionary[i].word, dictionary[i].definition);
    }
}

// Demostrates the dictionary_sort function

int main(void)
{
    struct entry dictionary[10] =
    {{"aardvark", "a burrowing African mammal"},
     {"abyss", "a bottomless pit"},
     {"addle", "to become confused"},
     {"aerie", "a high nest"},
     {"ajar", "partially opened"},
     {"acumen", "mentally sharp; keen"},
     {"affix", "to append; attach"},
     {"agar", "a jelly made from seaweed"},
     {"ahoy", "a nautical call of greeting"},
     {"aigrette", "an ornamental cluster of feathers"}};

    int i, dictionary_length = sizeof(dictionary) / sizeof(dictionary[0]);

    print_dictionary(&dictionary, dictionary_length);
    printf("\nSorting...\n\n");
    dictionary_sort(&dictionary, dictionary_length);
    print_dictionary(&dictionary, dictionary_length);
    printf("\n");

    return 0;
}

Upvotes: 1

user529758
user529758

Reputation:

You do not have to return anything at all, you don't even need explicit pointers, none of that. Sort in-place, and don't reinvent the wheel: use strcmp() and qsort() (live demo here):

struct entry dictionary[] = {
    { "def", "second entry" },
    { "abc", "first entry" },
    { "ghi", "third entry" },
    { "mno", "fifth entry" },
    { "jkl", "fourth entry" }
};

int compare_entry(const void *l, const void *r)
{
    const struct entry *ll = l;
    const struct entry *rr = r;
    return strcmp(ll->word, rr->word);
}

#define COUNT(x) (sizeof(x) / sizeof(x[0]))

qsort(dictionary, COUNT(dictionary), sizeof(dictionary[0]), compare_entry);

Upvotes: 4

A statement like "Returning an array of structs without pointers in C" is a paradox in C because the only way to pass or return an array in C is through pointers.Even though it may seem that in something like char *foo(char arr_demo[]){} an array is being passed, essentially it's a pointer being passed as it reduces to char *foo(char *arr_demo){}.

Upvotes: 0

Olaf Dietsche
Olaf Dietsche

Reputation: 74078

When you declare a function parameter with [], you already use pointers. The function definition

int compare_strings(const char s1[], const char s2[])

is functionally the same as

int compare_strings(const char *s1, const char *s2)

Same with struct entry dictionary_sort(struct entry dictionary[]).

Since you get a pointer to struct entry as parameter dictionary, return dictionary returns a pointer to struct entry as well.

And all changes you make to dictionary are already visible outside, because you modify the array itself and not some local array.

Upvotes: 0

Related Questions