0

I am having trouble with using strcmp() for a const char* array inside a template specialization.

In my script I want to sort several array's from large values/length to smaller ones. It works for an integer and float array however it does not work for a const char* array. I declared 3 template functions with their definition. For the const char* array I use a specialized template function which uses the strcmp(const char*, const char*) function to sort the array.

My script is as follows (first the template declarations, second the main script, third the template function definitions):

#include <iostream>
#include <string.h>

using namespace std ;

// Template function declarations
template <class T>
void order(T& a, T& b) ;

template <class T>
void sort(T* c, int d) ;

template <class T>
void display(T* e, int f) ;

// Main
int main() {

int random[10] = {10,23,5,37,56,0,20,88,95,32} ;    // Random Array of integers

float random_fl[10] = {9.5,66.2,5.8,41.1,89.4,0.6,23.4,66.5,90.9,57.7} ;    // Random Array of floats

const char* random_char[] = {"blah", "blahblah", "string", "character", "literal", "one", "randomize", "unsigned", "red", "wolf"} ;

int length = sizeof(random)/sizeof(int) ;           // Calculating the lenght of the array
int length_fl = sizeof(random_fl)/sizeof(float) ;
int length_char = sizeof(random_char)/sizeof(const char*) ;

cout << "Initial integer Array: ";                          // Terminal message giving the initial array
for (int i = 0; i < length; ++i) {
    cout << random[i] << "  ";
}
cout << endl;

cout << "Initial float Array: ";                            
for (int i = 0; i < length_fl; ++i) {
    cout << random_fl[i] << "  ";
}
cout << endl;

cout << "Initial character Array: ";                            
for (int i = 0; i < length_char; ++i) {
    cout << random_char[i] << "  ";
}
cout << endl;


sort(random, length) ;                              // Call sort() function to sort array
sort(random_fl, length_fl) ;                        
sort(random_char, length_char) ;

display(random, length) ;                           // Call display() function to print sorted array in terminal
display(random_fl, length_fl) ;
//display(random_char, length_char) ;

return 0 ;
} 

// Template function definitions
template <class T>
void order(T& a, T& b) {                                // order function using references
T Temp = a ;
a = b ;
b = Temp ;
}

template <class T>
void sort(T* c, int d) {                            // Sorting function

     for (int i=0; i<d-1; i++) {

         for (int j=0; j<d-1-i; j++) {

            if(c[j+1] > c[j]) {
                order(c[j] , c[j+1]) ;      
            }
         }
      }
}

template<>                                          
void sort(const char* a, int b) {           // Template specialization sort function for character string

    for (int i=0; i<b-1; i++) {

         for (int j=0; j<b-1-i; j++) {

             if(strcmp(a[j+1], a[j])>0) {
                  order(a[j], a[j+1]) ;
             } 

         }
    }
}

template <class T>
void display(T* e, int f) {                         // Display function
    cout << "Sorted Array: ";
    for (int i=0; i<f; i++) {
        cout << e[i] << " ";
    }
    cout << endl ;
}

When compiling the script, I get the error saying that an invalid conversion is occurring from 'char' to 'const char*' in the strcmp(const char*, const char*) function inside my specialized template function. I am wondering why, since I have defined a const char* array with 10 string literals. So the array elements a[j+1] and a[j] should be const char* elements as well since this is what they are expected to be at the start of the specialized sort function with the definition of const char* a.

I am fairly new to c++ and have especially difficulty in understanding pointers and how to refer to array elements with pointers/references which I think is at the root of this problem.

Please don't mind my English and thank you in advance.

Edit:

Even though my if() statement to get a sorted character string is not correct yet, as pointed out by Steiner, the strcmp() is now working as intended.

I thank you all kindly for your help.

user_537
  • 161
  • 1
  • 1
  • 11
  • 2
    if `a` is `const char *`, `a[j+1]` is `char`. What did you expect? Oh, and there is a parenthesis missing around `>0` comparison. –  Apr 26 '16 at 12:25
  • 3
    Just one more reason to ditch c-strings and use `std::string`s. Then you could also use `std::sort`. – NathanOliver Apr 26 '16 at 12:25
  • @Arkadiy, yes, sorry. I see I did erase the parenthesis accidently. – user_537 Apr 26 '16 at 12:37

3 Answers3

2

As partially mentioned by @Arkadiy, you are missing a star in the specialization of sort for the const char* and the if condition is not correct :

template<>                                          
void sort(const char** a, int b) {          
    for (int i=0; i<b-1; i++) {
         for (int j=0; j<b-1-i; j++) {
           if( strcmp(a[j+1], a[j]) > 0 ) {
                  order(a[j], a[j+1]) ;
             } 
         }
    }

And this specialization must appear before the main otherwise you get a compiler error of the type: specialization after instantiation (see this question).

If you change this you get the correct output :

Initial chararacter Array: blah  blahblah  string  character  literal  one  randomize  unsigned  red  wolf  
Sorted Array: wolf unsigned string red randomize one literal character blahblah blah 
Community
  • 1
  • 1
steiner
  • 170
  • 7
0

The compiler will complain if you pass a const variable to a function the takes a non-const argument. An element of a const char* is a const char, and that is not compatible with your function order(T&, T&).

Besides that, there are a few other issues with your program, such as the parentheses of strcmp(), and the usage of strcmp() with single chars at all.

Stefan
  • 4,380
  • 2
  • 30
  • 33
  • What? Order is templated so as long as they parameters match it will compile. The OP's error is with `strcmp` and from [Arkadiy's comment](http://stackoverflow.com/questions/36864817/c-invalid-conversion-from-char-to-const-char-in-strcmp-within-a-templat#comment61296778_36864817) you can see why – NathanOliver Apr 26 '16 at 12:36
  • order() assigns to its reference arguments, so the template cannot be resolved for const variables. Nevertheless, I'm with @steiner now that the OP meant to sort an array of C strings. – Stefan Apr 26 '16 at 12:51
0

My previous answer was a nonsense, steiner answer is correct, your sort template should be:

template<>                                          
void sort(const char** a, int b) {  

and be located above its point of instantiation (i.e. above main())

marcinj
  • 48,511
  • 9
  • 79
  • 100