Home > Back-end >  C programming sort the strings given
C programming sort the strings given

Time:12-16

#include <stdio.h>
int main()
{
    char * str[ ]={"C  program", "Basic", "Foxbase ", "Fortran", "Pascal"};
    int i,j;
    char * temp;        
    int k;                  
    for(i=0;i<4;i  )  
    {
        k=i;          
        for(j=i 1;j<5;j  )  
            if(str[i] < str[j]) k=j;
        temp=str[i]; str[i] = str[k]; str[k] = temp;  
    }
    for(i=0;i<5;i  )
        printf("%s\n",str[i]);
    return 0;
}

I wanna sort the strings given above by the order of letter(ASCII), but I just couldn't do it, I already know that the wrong part of this code is the

if(str[i] < str[j]) k=j;

And I tried to fix it many times, just doesn't work out. I already tried: *str[i] < *str[j] (didn't work, which I think is reasonable?)

Btw, using string.h is not allowed, how can I make everything right here?

CodePudding user response:

As arising from the comments to the question you are not allowed to use any library functions – thus you need to compare those strings manually (note that you cannot just compare the pointers, these might be arbitrary addresses, you need to compare what the strings point to!) – and as you even don't seem to be allowed to write a separate function you need to inline this code as well.

In general string comparison might look as follows (here still as a function):

int cmp(char const* x, char const* y)
{
    for(; *x && *y;   x,   y)
    {
         if(*x != *y)
             // first position where the strings differ:
             // x < y lexicographically if *x < *y, thus *x - *y < 0
             // x > y analogously, so:
             return *x - *y;
             // this gives you the equivalence: x # y <=> cmp(x, y) # 0
             // with # being any comparison operator
    }
#if 0
    if(*x)
        return 1; // x is longer, thus x > y
    if(*y)
        return -1; // y is longer, thus x < y
    return 0; // both equal
#else
    // actually, as the null terminator is smaller than any other character
    // anyway, we still can simply:
    return *x - *y;
#endif
}

Edit: An even simpler solution (thanks @Lundin for the hint) just iterates as long as the strings yet can be equal:

while(*x && *x == *y) // covers *y being 0, too!
{
      x;   y;
}
return *x - *y;

Side note: There's an issue with the comparison if your strings include values in the upper half of the character range (from 128 up to 255 inclusive; not an issue with your example): It is unspecified if raw char is signed or unsigned, if you want to have portable/stable behaviour on all platforms and compilers you might want to cast to unsigned char at any comparison (above and below):

return static_cast<unsigned char>(*x) - static_cast<unsigned char>(*y);

Using such a function is, in general, the solution to prefer. Maybe you ask once more if you are allowed to write a new function after all!

Otherwise in your case you could reduce the code for testing on being smaller only, so:

char const* cur = str[j];
char const* min = str[k];
while(*cur && *cur == *min)
{
      cur;   min;
}
if(*cur < *min)
{
    // cur is lexicographically smaller or shorter than min!
    // -> found a new minimum
    k = j;
}

CodePudding user response:

Rather than compare pointers with

if(str[i] < str[j])  // Compare pointers

code need to compare the strings refenced by those pointers.

if (strcmp(str[i], str[j]))  // Compare strings

As OP is obliged to not use strcmp(), make your own by comparing the strings, one character at a time (as unsigned char) for equality (and not a null character). Report zero when the same or a negative or positive corresponding to the sign of the difference.

// Use const to allow for pointers to const strings. 
int my_strcmp(const char *x, const char *y) {
  // Convert to unsigned char * as `strcmp()` compares "as if"
  // the characters were all unsigned.
  const unsigned char *ux = (const unsigned char*) x;
  const unsigned char *uy = (const unsigned char*) y;

  // Test for equality and null character.
  // I like to place the more likely to fail one first.
  while ((*ux == *uy) && *ux) {
    ux  ;
    uy  ;
  }

  // On rare machines, using `return *ux - *uy` may overflow. 
  // To avoid overflow, use 2 tests.
  // Good compilers see this idiom and emit efferent code.
  return (*ux > *uy) - (*ux < *uy);
}
  •  Tags:  
  • c
  • Related