Weird sorting of string in C

I was trying to solve this question. Question states that

An 'Abecedarian' is a word whose letters appear in alphabetical order. Write a program which will determine whether the given word is abecedarian or not and print 1 if abecedarian, 0 if not.

Input : user enter a string or word.
Output: print `1` if word is Abecedarian else `0`.

Now I solved the problem that I will sort the string and if the sorted string is same as original string then it will be Abecedarian. But in C code it is giving wied result for inputs. Code is below with input and outputs

// is added by me in output for explanation

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

int cmpfunc (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b );
}

int main(void) {
    char orginalString[80];
    char copiedString[80];
    scanf("%s",orginalString);

    strcpy(copiedString,orginalString);
    printf("Original string before sorting = %s \n",orginalString);
    printf("Copied original string before sorting = %s \n",copiedString);

    qsort(orginalString,strlen(orginalString),sizeof(char),cmpfunc);

    printf("Original string after sorting = %s \n",orginalString);
    printf("Copied original string after sorting = %s \n",copiedString);

    if(strcmp(orginalString,copiedString) == 0) {
        printf("%s is an Abecedarian word\n",copiedString);
    }
    else 
        printf("%s is not an Abecedarian word\n",copiedString);
    
    return 0;
}

Input 1

abcdef

Output 1

Original string before sorting = abcdef 
Copied original string before sorting = abcdef 
Original string after sorting = fedabc // should remain abcdef, if obeying desc sort then should be fedcba
Copied original string after sorting = abcdef 
abcdef is not an Abecedarian word

Input 2

fedcba

Output 2

Original string before sorting = fedcba 
Copied original string before sorting = fedcba 
Original string after sorting = abcdef // here it is correct 
Copied original string after sorting = fedcba 
fedcba is not an Abecedarian word

You can check with other inputs and will see that sorting is not working as it should be. Now I'm not very good in memory management in C.

Is there any memory issue/tweak that is doing this kind of trouble?

Upvotes: 1

Views: 137

Answers (3)

Connell Donaghy
Connell Donaghy

Reputation: 87

To answer your actual question, the reason this fails is because you're dereferencing the data as an int, not a char. This means you're dereferencing more bytes than necessary, and comparing bytes that might have nothing to do with 'a'. 'a' by ascii standards is 0x61. If you dereference 'a' as an int, you might end up with 0x61FFFFFF or 0xFFFFFF61 depending on how the type cast is implemented. Thus you're not actually comparing the chars, but the chars and surrounding bytes as well.

Upvotes: 2

thus spake a.k.
thus spake a.k.

Reputation: 1637

You can do this more efficiently by simply checking that the characters in a string are non-descending:

int
is_abecedarian(char *s)
{
    if(s[0]==0) return 1;

    while(s[1] && s[0]<=s[1]) ++s;
    return s[1]==0;
}

Note that I'm assuming that the string s is either all uppercase or all lowercase. And a character encoding that has a-z in increasing numerical order.

Upvotes: 2

this
this

Reputation: 5290

You are comparing characters, char, not integers, int.

Change your comparison function to

int cmpfunc (const void * a, const void * b)
{
   return ( *(char*)a - *(char*)b );
}

Upvotes: 1

Related Questions