Reputation: 83
I have written such a piece of code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int compare_str(const void* a, const void* b)
{
char * const * aa=a;
char * const * bb=b;
return strcasecmp(*aa, *bb);
}
int sort_alphabetically(char tab[])
{
if(strlen(tab)<1 || tab[strlen(tab)-1]=='\n')
{
return 1;
}
for(unsigned int i=0; i<strlen(tab); i++)
{
if(tab[i]=='-')
{
return 1;
}
}
int spaces_count=0;
int first=0;
int ch=0;
for(unsigned int i=1; i<strlen(tab); i++)
{
if(tab[i]!=' ')
first=1;
if(tab[0]==' ' && tab[1]==' ')
ch=1;
if(tab[i]==' ' && tab[i+1]>=33 && tab[i+1]<=126 && first==1)
spaces_count++;
}
int words_count=spaces_count+1;
char **words=malloc(words_count * sizeof(char*));
char *pch;
int word_idx=0;
pch=strtok(tab, " ");
while(pch!=NULL)
{
words[word_idx++]=strdup(pch);
pch=strtok(NULL, " ");
}
qsort(words, words_count, sizeof(char*), compare_str);
for(int i=0; i<words_count; i++)
{
for(unsigned int j=0; j<strlen(words[i]); j++)
{
if(ch==0)
*(tab++)=words[i][j];
else
if(words[i][j]!=' ')
{
*(tab++)=words[i][j];
ch=0;
}
}
if(i!=words_count-1)
*(tab++)=' ';
else
*(tab++)='\0';
free(words[i]);
}
free(words);
for(unsigned int i=0; i<strlen(tab); i++)
if(tab[i]==' ' && tab[i+1]==' ')
tab[i]='\0';
return 0;
}
int main()
{
char input[1000];
printf("Enter text: ");
if(fgets(input, 1000, stdin))
{
if(input[strlen(input)-1]=='\n')
input[strlen(input)-1]='\0';
if(sort_alphabetically(input))
{
fprintf(stderr, "Incorrect input data");
return 2;
}
else
printf("%s", input);
}
return 0;
}
It sorts alphabetically words inputted by user. The thing is it makes the job but I would also like it to check if the words are the same. If they are word with first capital letter should stay before the word with first small letter. Ex.:
Enter text:
TeChnoLOGY iS TeAChiNg Us tO Be human aGAinSiMoN MainWARing IS
Output should be:
aGAinSiMoN Be human IS iS MainWARing TeAChiNg TeChnoLOGY tO Us
But it is:
aGAinSiMoN Be human iS IS MainWARing TeAChiNg TeChnoLOGY tO Us
What changes should I make?
Upvotes: 2
Views: 52
Reputation: 180181
Your comparison function compare_str
is a wrapper around strcasecmp()
, which explicitly and specifically performs a case-insensitive comparison. If you instead want a case-sensitive comparison then exchange that for a function that provides one, or write a replacement, or just add code to compare_str
to differentiate more finely in the cases where strcasecmp()
returns 0, depending on exactly what ordering you want.
Since the nature and details of the question lead me to suspect that this is an academic exercise, I leave it to you to work out the details. The objective is that compare_str()
must return a negative number if the first argument should be sorted before the second, a positive number if the second should be sorted before the first, or zero if either order is acceptable.
Upvotes: 2
Reputation: 18420
To achieve, what you want, you have to change your comparison function slightly.
As you observed, strcasecmp()
will put the order of two equal words indeterminate. So, if strcasecmp()
deems two words equal (barring the case), you have to compare them case-sensitive (with the appropriate function, you'll guess which ;) and return that result. Otherwise, just return the result of strcasecmp()
.
Upvotes: 4