2

I have a program, that asks several strings and should sort them. My code is:

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

#define MAX_STR_LEN 256

int myStrCmp (const void * a, const void * b)
{
    return strcmp((const char *)a, (const char *)b);
}

int main(void) 
{
    int strNum; // expected number of input strings
    int strCnt; // counter of strings
    char ** storage; // pointr to the memory when strings are stored
    char strBuf[ MAX_STR_LEN]; // buffer for strings
    char * strPtr; 
    // input of strings number
    do{
        printf("How many strings will be entered: ");
        while( scanf("%d", &strNum) != 1)
        {
            printf("ERROR: Not number was entered!\n");
            while( getchar() != '\n' );
            printf("Please enter a number: ");
        }
        if( strNum < 2 )
        {
            printf("ERROR: Number less than 2 was entered!\n");
        }
        while( getchar() != '\n' );
    }
    while(strNum < 2);
    // allocation of memory for pointers
    storage = (char **) calloc(strNum, sizeof(char*) );
    if( storage == NULL )
    {
        printf("ERROR: Unexpected problems with memory allocation!\n");
        return 1;
    }
    // input of strings
    for( strCnt = 0; strCnt < strNum; strCnt++)
    {
        printf("Enter string #%d:\n", strCnt + 1);
        fgets(strBuf,  MAX_STR_LEN, stdin);
        strPtr = strchr(strBuf, '\n');
        if( strPtr )
        {
            *strPtr = '\0';
        }
        else
        {
            strBuf[ MAX_STR_LEN - 1] = '\0';
        }
        // allocation memory for particular string
        storage[strCnt] = (char *) malloc(strlen(strBuf) + 1);
        if(storage[strCnt] == NULL)
        {
            printf("ERROR: Unexpected problems with memory allocation!\n");
            return 2;
        }
        // move string to dynamic memory 
        strcpy(storage[strCnt], strBuf);
    }
    // sort the strings
    qsort(storage, strNum, sizeof(char**), myStrCmp);
    // output the result
    printf("\nSorted strings:\n");
    for( strCnt = 0; strCnt < strNum; strCnt++)
    {
        printf("%s\n", storage[strCnt]);
    }
    return 0;
}

The simplest test shows the trouble:

How many strings will be entered: 3
Enter string #1:
ddd
Enter string #2:
aaa
Enter string #3:
ccc

Sorted strings:
ddd
aaa
ccc

I have tryed Visual C++ and gcc, but the result is the same. Please, say me what is wrong in the code?

3
  • 1
    Hi SannyD! I appreciate that you included the source code and an example run of the program. You're doing far better than most with their first question on StackOverflow. One thing that you could do to make your question even better, is to hardcode the input. There's a significant amount of code before the call to qsort(). You could go in there and just hardcode it such that storage is always the same 5 strings. That would make your question awesome!
    – Bill Lynch
    Commented Apr 2, 2015 at 20:41
  • Thanks for advise. Next time, I will do.
    – user4744110
    Commented Apr 2, 2015 at 20:44
  • Note: rather than storage = (char **) calloc(strNum, sizeof(char*) );, consider storage = calloc(strNum, sizeof *storage); Easier to code and maintain.
    – chux
    Commented Apr 2, 2015 at 20:48

1 Answer 1

4

The problem is in myStrCmp function.

Because a and b are elements in not a simple array, but in array of pointers, their type must be char ** and function that compares two elements have to be as follows:

int myStrCmp (const void * a, const void * b)
{
    return strcmp(*(const char **)a, *(const char **)b);
}
4
  • This solution worked perfectly for me, though I'm not 100% sure I understand why this needs to be the case conceptually. Is anyone willing to try and explain this further? Commented Nov 16, 2017 at 4:33
  • 1
    I will try to explain need of the second * by associative example. Imagine, you have apples and you sort them by size (this is the simple case and to compare two apples you point by 2 fingers of different hands to 2 apples at one moment), them make the task more complex - you sort packages of apples (so objects to be compared are "objects in object package" and to reach an apple you need point a package (the first *) and then point particular apple (the second *)).
    – VolAnd
    Commented Nov 16, 2017 at 4:48
  • 1
    As soon as apple is like single char, and string (array) is like package of apples, you can imagine that strcmp is like a balance to compare packages without unpacking.
    – VolAnd
    Commented Nov 16, 2017 at 4:48
  • Wow, surprisingly made sense! Thanks a bunch! Commented Nov 16, 2017 at 5:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.