Template specialization error - C++ (C++ Primer Plus exercise) - c++

I'm currently learning C++ so I don't have much knowledge on the topic . I'm using the C++ primer plus book and here's the problem :
Write a template function maxn() that takes as its arguments an array of items of type T
and an integer representing the number of elements in the array and that returns the
largest item in the array. Test it in a program that uses the function template with an
array of six int value and an array of four double values. The program should also
include a specialization that takes an array of pointers-to-char as an argument and the
number of pointers as a second argument and that returns the address of the longest
string. If multiple strings are tied for having the longest length, the function should
return the address of the first one tied for longest. Test the specialization with an array of
five string pointers.
Here's my code :
#include <iostream>
#include <cstring>
using namespace std;
template <class T> T maxn(T arr[] , int n);
template <> char * maxn<char (*)[10]> (char (*arr)[10] , int n);
int main()
{
double array[5] = { 1.2 , 4.12 ,7.32 ,2.1 ,3.5};
cout << endl << maxn(array , 5) << endl << endl;
char strings[5][6] = { "asta" , " m" , "ta" , "taree" , "e"};
cout << maxn(strings , 5) << endl;
return 0;
}
template <class T> T maxn(T arr[] , int n)
{
T max = 0;
for (int i = 0 ; i < n ; ++i)
{
if (arr[i] > max)
max = arr[i];
}
return max;
}
template <> char * maxn<char (*)[10]> (char (*arr)[10] , int n)
{
int length = 0;
int mem = 0;
for ( int i = 0 ; i < n ; ++i)
{
if (strlen(arr[i]) > length)
{
length = strlen(arr[i]);
mem = i;
}
}
return arr[mem];
}
I'm trying to pass an array of strings . I get the following errors :
g++ -Wall -o "untitled5" "untitled5.cpp" (in directory: /home/eukristian)
untitled5.cpp:6: error: template-id ‘maxn<char (*)[10]>’ for ‘char* maxn(char (*)[10], int)’ does not match any template declaration
untitled5.cpp: In function ‘int main()’:
untitled5.cpp:14: error: no matching function for call to ‘maxn(char [5][6], int)’
untitled5.cpp: At global scope:
untitled5.cpp:31: error: template-id ‘maxn<char (*)[10]>’ for ‘char* maxn(char (*)[10], int)’ does not match any template declaration
Compilation failed.
I'm quite sure I've made some newbie mistake and I can't detect it .
Thanks .

char (*)[10] is a pointer to an array of 10 chars. char *[10] is an array of 10 char pointers.
Also you're specifying a different type for the return value than for T. I.e. if the function is supposed to return char*, the value for T should be char*, too. Your specialization should look like this:
template <> char * maxn<char *> (char *arr[] , int n);
Also your array of strings should be of type char *[5].

The program should also include a specialization that takes an array of pointers-to-char as an argument and the number of pointers as a second argument and that returns the address of the longest string.
What you have in your code is not that, it's a two-dimensional array of characters (a single block of 5 * 6 bytes of memory). Compare with array of five pointers
const char* strings[5] = {"asta" , " m" , "ta" , "taree" , "e"};
Your code is also making the assumption that 0 is the smallest value for any T.

#include <iostream>
#include <cstring>
#include <locale>
//#include <windows.h>
using namespace std;
const int maxcharval = 5;
const int maxintval = 6;
const int maxdoubleval = 4;
template <typename T>
T maxn(T* arr, int n);
template <> const char * maxn <const char *> (const char* arr[], int n);
int main(int argc, char *argv[])
{
//setlocale(LC_CTYPE, ".866");
const char * charr[] = {"qwer","qwert","qwe","qw","q"};
const int intarr[] = {1,3,2,5,3,0};
const double doublearr[] = {5.4, 2.3, 3.1, 3.2};
cout << "maxint: " << maxn(intarr, maxintval) << endl;
cout << "maxdouble: " << maxn(doublearr, maxdoubleval)
<< endl;
cout << "maxcharstring:" << maxn(charr, maxcharval)
<< endl;
//system("pause");
return 0;
}
template <typename T>
T maxn(T *arr, int n)
{
T* value = &arr[0];
for (int i = 1; i < n; i++)
{
if (*value < arr[i])
value = &arr[i];
}
return *value;
}
template <> const char * maxn <const char *>(const char* arr[], int n)
{
const char* val = arr[0];
for (int i = 1; i < n; i++)
{
if (strlen(val) < strlen(arr[i]))
val = arr[i];
}
return val;
}
It's work. Good luck!

Related

Why is my array being passed with an incorrect size? [duplicate]

This question already has answers here:
Size of an array C++ [duplicate]
(7 answers)
Closed 2 years ago.
I am just starting to learn C++ and I was playing around with functions. I am trying to pass an integer array as a parameter, and have the function print every element of the array. My issue however is that I have an array initialized to a seize of 10, but when I pass it to the function it only reads it as a size of 2. Any help would be appreciated! You can find my program below.
#include <iostream>
#include <cmath>
using namespace std;
void Max(int Arr[])
{
for (int i=0; i<sizeof(Arr)/sizeof(Arr[0]); i++)
{
cout<< Arr[i]<<endl;
}
}
int main()
{
int Arr[]={1,2,3,4,5,6,7,8,9,10};
Max(Arr);
return 0;
}
Thank you all for the help in advance!
When an array is passed by value it is implicitly converted to pointer to its first element.
On the other hand a function parameter declared as having an array type is adjusted by the compiler to pointer to the array element type.
So for example these function declarations
void Max(int Arr[]);
void Max(int Arr[1])
void Max(int Arr[10])
void Max(int Arr[100]);
declare the same function and are adjusted by the compiler to the declaration
void Max( int *Arr );
As a result within the function the parameter Arr is a pointer and this expression
sizeof(Arr)/sizeof(Arr[0])
is equivalent to
sizeof( int * ) / sizeof( int )
that yields either 1 or 2 depending on the size of the type int *.
When you passing an array by value to a function you should also pass its size explicitly.
So the function could be defined like
void Max( const int Arr[], size_t n )
{
for ( size_t i = 0; i < n; i++ )
{
cout << Arr[i] << endl;
}
}
And the function can be called like
Max(Arr, sizeof( Arr ) / sizeof( *Arr ) );
Another approach is to declare the function parameter as having a referenced type. In this case it is better to use a template function that it could be called for an array at least of any size.
template <size_t N>
void Max( const int ( &Arr )[N] )
{
for ( size_t i = 0; i < N; i++ )
{
cout << Arr[i] << endl;
}
}
Or the function could be defined like
template <typename T, size_t N>
void Max( const T ( &Arr )[N] )
{
for ( size_t i = 0; i < N; i++ )
{
cout << Arr[i] << endl;
}
}
And the both functions can be called like
Max(Arr);
Pay attention to that you could use the standard class template std::array declared in the header <array>. For example
#include <iostream>
#include <array>
const size_t N = 10;
std::ostream & Max( const std::array<int, N> &a, std::ostream &os = std::cout )
{
for ( const auto &item : a )
{
os << item << ' ';
}
return os;
}
int main()
{
std::array<int, N> a = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
Max( a ) << '\n';
return 0;
}
The program output is
1 2 3 4 5 6 7 8 9 10
void Max(int Arr[]) is equal to void Max(int* Arr).
In function Max(int Arr[]):
sizeof(Arr)/sizeof(Arr[0]) = sizeof(int*)/sizeof(int)
On x64 it is equal 2, on x86 it is equal 1
correct your code:
---------------------------------
#include <iostream>
#include <cmath>
using namespace std;
void Max(int Arr[], int len)
{
for (int i=0; i<len; i++)
{
cout<< Arr[i]<<endl;
}
}
int main()
{
int Arr[]={1,2,3,4,5,6,7,8,9,10};
Max(Arr, sizeof(Arr)/sizeof(Arr[0]));
return 0;
}

How do I make an int that is the length of an array in C++?

So basically I'm trying to write a method that returns two times the length of an array, but I cannot figure out how to make the length into an int so that it can be used. I have been trying to figure out the correct method to use since sizeof() returns the number of bytes, not the length of the array. What method should I be using and how can I fix this? Here is my code:
int main(int argc, const char * argv[]) {
int arr[] = {1,2,3,4,5};
cout << getLen(arr);
return 0;
}
int getLen( int *arr ){
int len = sizeof(arr);
return 2 * len;
}
I think this could be an XY problem. Ultimately if you want this kind of behaviour in C++ you should use an std::vector object. For example:
#include <iostream>
#include <vector> // Remember to include this
int getLen(std::vector<int> &vec) // Pass vec by reference rather than as a pointer
{
return static_cast<int>(vec.size()) * 2; // Use .size() to get the number of elements in vec
// ^^^ .size() returns a value of type size_t which is converted to an int using static_cast<int>
}
int main()
{
std::vector<int> vec = {1,2,3,4,5};
std::cout << getLen(vec);
return 0;
}
#include <iostream>
template<typename T,std::size_t n>
std::size_t get_new_len(T (&a)[n]) {
return n*2;
}
int main() {
int a[10] = {0};
std::cout << get_new_len(a) << "\n";
}
you can do it in this way, using template argument deduction.
output is 20
The result of sizeof(arr) is not the same in the main as in the function, i don't understand why , but it works like this :
int getLen(int *arr, int arrSize)
{
int len = arrSize / sizeof(int);
return len;
}
int main(int argc, const char * argv[])
{
int arr[] = { 1, 2, 3, 4, 5 };
cout << getLen(arr,sizeof(arr));
return 0;
}

Pointer to array in function in c++

I am a beginner to c++. Pointer is quite confusing to me. Especially on how to use it in functions and array. I tried to create a pointer to array in function and just output it. However it keeps giving me the address of the array instead of the value.
void testing(int* arr){
cout << arr << endl;
}
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr);
string y;
getline(cin, y);
return 0;
}
I tried using testing(&my_arr); to output value but it give me errors:
argument of type "int (*)[3]" is incompatible with parameter of type
"int *
'void testing(int *)': cannot convert argument 1 from 'int (*)[3]' to 'int *'
Thanks a lot for any help!
To print the values in an array rather than the starting address, you need to use a loop.
#include <iostream>
#include <string>
// note extra param for length of array.
void testing(int* arr, int len){
for (int i = 0; i < len; ++i)
std::cout << arr[i] << " ";
std::cout << "\n";
}
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr, 3);
return 0;
}
You can't pass testing(&my_arr) because &my_arr is of type int (*)[] as per the error message you received. That is not the same as int*.
for printing the arrays, you can either use the array index or pointers arithmetic. The test function could also be written as
void testing(int* arr, int len) {
for (int ctr = 0; ctr < len; ctr++) {
std::cout << *(arr + ctr) << std::endl;
}
}
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr, 3);
return 0;
}
In testing() you are trying to use arr element without its index.
Here arr is the only base memory address of that memory. To get value from there you have to specify index.
void testing(int* arr, int len)
{
for(int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
In main() you can pass a length of an array.
int main()
{
int my_arr[]{ 4,7,1 };
testing(my_arr, sizeof(my_arr) / sizeof(int));
return 0;
}

c++ twodimensional array passed to function

I like to pass a two dimensional array to a function to print it.
Here is my code so far. As you can see on the comment it does not compile, because of an incompatible type.
QUESTION
How can I pass the two dimensional array to printIt ?
If I adjust it to printIt(int a(*)[50][50]) I get the another error during compilation, because returning array is not allowed
using namespace std;
void printIt(int a[50][50]);
int main(int args, char *argv[])
{
int a[50][50];
int j = 0;
for (int i = 1; i < 6; i++)
{
a[i][j] = i;
// the same should be printed out inside printIt
cout << " " << a[i][j];
// not compiling
// argument of type int is incompatible with int(*)[50]
printIt(a[i][j]);
}
}
void printIt( int a[50][50] )
{
cout << " " << a[50][50];
}
Given
int a[50][50];
a[i][j] evaluates to an int.
a[i] evaluates to int [50], an array of 50 integers. If used as an argument to a function call, a[i] decays to a int* in most cases. In rare cases it converts to int (&)[50].
If used as an argument to a function call, a decays to int (*)[50] in most cases. In rare cases it converts to int (&)[50][50].
In your case, the function declaration
void printIt(int a[50][50]);
is equivalent to
void printIt(int a[][50]);
and
void printIt(int (*a)[50]);
Hence, using
printIt(a);
is the right method of calling the function.
However
Given the way you are using the argument in printIt, you probably meant to use:
void printIt(int num)
{
cout << " " << num;
}
After that, it OK to use:
printIt(a[i][j]);
in main.
Because a[i][j] in an integer, it is a value. You are passing a value not an double array Your code should look like that :
#include <iostream>
using namespace std;
void printIt(int a)
{
cout << " " << a;
}
int main(int args, char *argv[])
{
int a[50][50];
int j = 0;
for (int i = 1; i < 6; i++)
{
a[i][j] = i;
// the same should be printed out inside printIt
cout << " " << a[i][j];
// not compiling
// argument of type int is incompatible with int(*)[50]
printIt(a[i][j]);
}
}

C++ invalid conversion from 'char' to 'const char*' in strcmp() within a template specialization

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.
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
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.
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())