-2

I am trying to do the following coding challenge in C:

Challenge: Using the C language, have the function AlphabetSoup(str) take the str string parameter being passed and return the string with the letters in alphabetical order (ie. hello becomes ehllo). Assume numbers and punctuation symbols will not be included in the string.

Attempt:

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

int cmpfunc(const void* val_1, const void* val_2){
    return (*(char *)val_1 - *(char *)val_2);
}

int str_size(char* str[]){
    int size = 0;
    while(str[size] != '\0')
         size++;
    return size;
}

void AlphabetSoup(char * str[]) { 
  qsort(str,str_size(str), sizeof(char), cmpfunc);
  printf("%s", str); 

}

int main(void) { 

  // disable stdout buffering
  setvbuf(stdout, NULL, _IONBF, 0);

  // keep this function call here
  AlphabetSoup(gets(stdin));
  return 0;

} 

I am not getting any output for this code. I think the problem is the cmpfunc function. I am not implementing it correctly. I neither understand how it works inside qsort. My understanding is that val_1 and val_2 are pointers to two chunks of memory in the array and somehow I have to cast these chunks to the right type.

I am also getting a non-zero status for the following code:

void AlphabetSoup(char * str[]) {
  int str_size_ = str_size(str);
  int int_rpr[str_size_];
  int i;
  for(i = 0; i < str_size; i++){
      int_rpr[i] = (int)str[i];
  }
  printf("%i", str_size_);
    //printf("%s", str);
  //qsort(int_rpr,str_size_, sizeof(int), cmpfunc);

  //for(i = 0; i < str_size; i++){
   // printf("%c", str[i]); 
 // }

}

when I get rid of int_rpr[i] = (int)str[i];and replace it by any random statement like int b; b = 0; , it works.

coding challenge link: https://coderbyte.com/editor/Alphabet%20Soup:C

patzi
  • 353
  • 4
  • 13
  • 3
    What does `gets` return versus what `AlphabetSoup` takes as a parameter? Have you considered a debugger? You might also read: https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used – Retired Ninja Jan 12 '18 at 04:54
  • That was part of the starter code provided by the website coderByte. – patzi Jan 12 '18 at 04:56
  • What was part of the starter code? The `gets` function is dangerous, but it returns a `char*`, not a `char*[]` so both the `AlphabetSoup` and `str_size` functions are incorrect. If corrected, it works fine: https://ideone.com/6iGthR – Retired Ninja Jan 12 '18 at 05:02
  • 6
    Even if you decide to use the unsafe gets(), it takes a char array as its only argument, not a file/stream descriptor like 'stdin'. – Martin James Jan 12 '18 at 05:06
  • 6
    I think you would be better served by finding another challenge website: these folks can't even generate valid C code for their initial boilerplate. How are you supposed to know if your code is correct based on their judgment? – Mark Benningfield Jan 12 '18 at 05:16
  • [This](http://anyexample.com/programming/c/qsort__sorting_array_of_strings__integers_and_structs.xml) may help you – ntshetty Jan 12 '18 at 06:11
  • 1
    Read about [Why the `gets()` function is too dangerous to be used — ever!](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-dangerous-why-should-it-not-be-used) – Jonathan Leffler Jan 12 '18 at 07:33
  • treat the string as an array of characters, then perform a bubble sort on that array. – user3629249 Jan 12 '18 at 07:43
  • the function: `gets()` has been depreciated for years and completely removed in the more recent versions of C. Your compiler should have told you about that. Strongly suggest you use the function: `fgets()` – user3629249 Jan 12 '18 at 07:45
  • 2
    It is poor programming practice to name a variable the same as a function name. (regarding `str_size` and `str_size()`) Unless there is some prohibition about it, strongly suggest including the header file: `string.h` and then calling the function: `strlen()` thereby eliminating the function: `str_size()` – user3629249 Jan 12 '18 at 07:48
  • 1
    regarding: `void AlphabetSoup(char * str[]) {` this is declaring that `str` is an array of pointers to char. NOT what you want. Suggest: `void AlphabetSoup(char str[]) {` Note: no `*`, Similar considerations exist for the signature: `int str_size(char* str[]){` – user3629249 Jan 12 '18 at 07:50
  • regarding: `setvbuf(stdout, NULL, _IONBF, 0);` This is a bad idea. Suggest removing that statement and modifying the format string of all calls to `printf()` to end with '\n'. – user3629249 Jan 12 '18 at 07:57
  • this statement: `AlphabetSoup(gets(stdin));` will put an indeterminate amount of data on the stack. This is a very bad idea. Suggest using a local buffer to fill with the `gets()` then passing the address of that buffer to the function: `AlphabetSoup()` – user3629249 Jan 12 '18 at 08:02
  • Your not using a parameter, use `argv[1]` after checking `argc >= 2` of course – Henno Brandsma Jan 12 '18 at 10:02
  • I don't know why I am getting down-votes. I think the question is valid. – patzi Jan 13 '18 at 00:09

1 Answers1

1

It was asked you parse an argument (not a string from stdin), so you need to use argc and argv. Also sizeof(char) is 1 by the C standard, so is superfluous. Don't duplicate strlen either, we have libraries for a reason.

I'd do it this way (which I confirmed works on my system)

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

int char_cmp(const void *pa, const void *pb){

    char a = *((char *) pa), b= *((char *) pb);
    if (a < b){ 
        return -1;
    } else if (a > b){ 
        return 1;
    } else {
       return 0;
    }   
}

int main(int argc, char *argv[]){

char *input= NULL;
if (2 != argc){
    fprintf(stdout, "give one argument string\n");
    return 1;
} else {
    input = strdup(argv[1]);
    if (NULL == input){ 
        fprintf(stderr, "memory error\n");
        return 2;   
    }       
}   
qsort(input, strlen(input), 1, char_cmp);
fprintf(stdout, "%s\n", input);
free(input);
return 0;

}
Henno Brandsma
  • 2,116
  • 11
  • 12