Related
I am trying to write a function that swap two arrays in O(1) time complexity. However, when i try to write the function parameters, I get the error:
error: cannot convert ‘int (*)[4]’ to ‘int**’
Here is my code:
#include <iostream>
using namespace std;
void swap_array_by_ptr(int* a[], int* b[]) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr[] = {1,2,3,4};
int rv[] = {4,3,2,1};
swap_array_by_ptr(&fr, &rv);
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
}
However, when i tried to define the arrays with 'new' command, this works as expected as below:
#include <iostream>
using namespace std;
void swap_array_by_ptr(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr = new int[4]{1,2,3,4};
int rv = new int[4]{4,3,2,1};
swap_array_by_ptr(&fr, &rv);
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
}
Is there any way that i can define the arrays with [] method and swap the arrays by sending these arrays with '&array' method ?
As I believe, there must be a way to do that, I only achieve this when I'm trying to do with 'new' method. However, is there any way to swap two arrays in O(1) complexity with sending parameters as
swap_array_by_ptr(&fr, &rv);
?
Thanks for help.
You can not swap two arrays with O( 1 ). You need to swap each pairs of corresponding elements of two arrays.
In the first program
int fr[] = {1,2,3,4};
int rv[] = {4,3,2,1};
swap_array_by_ptr(&fr, &rv);
the expressions &fr and &rv have type int( * )[4] while the corresponding function parameters in fact has the type int **
void swap_array_by_ptr(int* a[], int* b[]) {
after adjusting the parameters having array types to pointers to the array element types by the compiler.
So the compiler issues an error.
You could use standard function std::swap declared in the header <utility> the following way
std::swap( fr, rv );
But in any case its complexity is O( n ).
In the second program there are at least typos. Instead of
int fr = new int[4]{1,2,3,4};
int rv = new int[4]{4,3,2,1};
you have to write
int *fr = new int[4]{1,2,3,4};
int *rv = new int[4]{4,3,2,1};
In this case you are not swapping arrays themselves. That is the arrays will still store their initial values. You are swapping pointers that point to the dynamically allocated arrays.
To be sure that arrays are not swapped consider the following demonstration program.
#include <iostream>
using namespace std;
void swap_array_by_ptr(int** a, int** b) {
int* temp = *a;
*a = *b;
*b = temp;
}
int main()
{
int fr[] = { 1,2,3,4};
int rv[] = {4,3,2,1};
int *p1 = fr;
int *p2 = rv;
swap_array_by_ptr( &p1, &p2 );
for (int i = 0; i < 4 ; i++) {
cout << p1[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << p2[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << fr[i] << " ";
}
cout << endl;
for (int i = 0; i < 4 ; i++) {
cout << rv[i] << " ";
}
cout << endl;
}
It is a syntactic quirk inherited from C that a declaration of a function parameter as an array is automatically converted to a declaration as a corresponding pointer. This is not as odd as it might first seem, however, because it dovetails with the automatic conversion of function arguments of array type to corresponding pointers, also inherited from C.*
Thus, this declaration ...
void swap_array_by_ptr(int* a[], int* b[]) {
... is equivalent to this one:
void swap_array_by_ptr(int **a, int **b) {
. But the arguments you are passing do not match. This, for example,
int fr[] = {1,2,3,4};
declares fr as an array of 4 int. If it were passed as a function argument, it would be automatically converted to a pointer to the first element, thus of type int *. Types int * and int ** are not compatible.
On the other hand, what you actually try to pass, &fr is the address of an array 4 int, of type int(*)[4]. This also is incompatible with int **, because arrays are not pointers.
You could write your function like this:
void swap_array_by_ptr(int (*a)[4], int (*b)[4]) {
int temp[4];
memcpy(temp, a, sizeof(a));
memcpy(a, b, sizeof(b));
memcpy(b, temp, sizeof(temp));
}
That would be compatible with the call in your code. Do note, however, that that is specific to array size 4, and you're not really gaining anything useful from that. You could, however, convert it to a template:
template<class T, std::size_t n>
void swap_array(T (*a)[n], T (*b)[n]) {
T temp[n];
memcpy(temp, a, sizeof(a));
memcpy(a, b, sizeof(b));
memcpy(b, temp, sizeof(temp));
}
That handles arrays of any element type and size,** as long as the sizes match. Of course, it scales as O(N) with array size, in both time and auxiliary space.
Such time scaling is unavoidable. To swap two objects you need to read each at least once and write each at least once, and that requires time proportional to the size of the objects. But you could reduce the space overhead to O(1) by swapping the arrays element by element in a loop. That would very likely be slower, but the time complexity would still be O(N).
Of course, you can also use std::swap() on arrays. It is quite similar to the template above, but uses references to the arrays instead of pointers to them.
*This is a specific case of a much more general behavior.
**So long as the temporary array does not turn out to be too large for the stack.
Change the swap_array_by_ptr function from 'swap_array_by_ptr(int** a, int** b)'
to 'swap_array_by_ptr(int* a, int* b)'.
void swap_array_by_ptr(int* a, int* b) {
int* temp = *a;
*a = *b;
*b = temp;
}
here's a link to a similar question: Swapping 2 arrays in C
I'm trying to write some functions to handle C++ arrays (for the purposes of this assignment, I'm not allowed to use std::vector - only iostream, algorithm, string, and array).
However, when I run this code, I get two error messages.
in.cpp:15:25: error: cannot convert ‘int ()[5]’ to ‘int’ in initialization
int* PointsToArray = &myArray;
This happens when I try to initialize a pointer to myArray. I guess there must be an issue with my pointer/reference declaration syntax, but I've tried "int *PointsToArray" and "int * PointsToArray" and various other ways of spacing around the asterisk, and I can't figure out what's wrong.
The other one is this.
main.cpp:22:15: error: ‘arr’, 'begin', 'end' was not declared in this scope
for(int i : arr)
I borrowed the for(int i : arr) syntax in order to iterate through an array with an unknown number of elements from here. The loop worked fine until I added the searchPointer() function; then it threw this error message.
My code is below, please help.
#include <iostream>
#include <array>
using namespace std;
int searchArray(int array[], int targetInt);
//Iterates through an array & returns index of an element identical to target
int* searchPointer(int* arr, int targetInt);
//Returns a pointer to an element that matches the target
int main() {
int targetInt = 4;
int myArray[5] = {1, 2, 3, 4, 5};
int* PointsToArray = &myArray;
searchArray(myArray, targetInt);
searchPointer(PointsToArray, targetInt);
}
int searchArray(int array[], int targetInt) {
for(int i : arr) {
if (i == targetInt) {
int* x = find (std::begin(arr), std::end(arr), targetInt);
cout << "Your target " << targetInt << " found at index " << x << "\n";
}
}
return 0;
}
int* searchPointer(int* arr, int targetInt) {
for (int i : arr) {
if (i == targetInt) {
std::cout << "Target located at " << &targetInt << " in memory\n";
}
}
}
the name of the array is the address of the first element i think u have to write it like this
int* PointsToArray = myArray;
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;
}
I have a problem. The statement says that the results at a contest are read from standard input and I have to print to the screen the final standings in decreasing order by the number of solved problems. Here is my code.
#include <cstdio>
#include <vector>
#include <cstdlib>
using namespace std;
struct results
{
unsigned int id; //id of the team
unsigned int m; //number of solved problems
};
int comparare(const void * i, const void * j) //compare function for qsort()
{
return -( *(unsigned int*)i - *(unsigned int*)j );
}
int main()
{
unsigned int n;
vector<results> standings; //initializing an array of structs
scanf("%u", &n); //the size of the vector
for(unsigned int i=0; i<n; ++i)
{
scanf("%u%u", &standings[i].id, &standings[i].m); //reading the elements
standings.push_back(results());
}
qsort(standings, n, sizeof(results), comparare); //sorting the array
for(unsigned int i=0; i<n; ++i)
printf("%u %u\n", standings[i].id, standings[i].m); //print the sorted array
return 0;
}
When I want to compile the code, the compiler finds the error
cannot convert 'std::vector' to 'void*' for argument '1' to 'void qsort(void*, size_t, size_t, __compar_fn_t)'
in the line qsort(standings, n, sizeof(results), comparare);
What I have to do to repair this?
If you absolutely must use qsort on a vector (and you don't. And shouldn't), then you have to pass it like this:
qsort(standings.data(), standings.size(), sizeof(results), comparare);
vector::data fetches a pointer to the array stored in the vector. Simply passing a pointer to the vector itself will not help.
Note that vector::data requires C++11; use &vector[0] if data is not available to you.
But really, just use std::sort:
std::sort(standings.begin(), standings.end(), [](const results &lhs, const results &rhs) {return lhs.id < rhs.id;});
Obviously the lambda requires C++11; feel free to use a namespace-declared struct for earlier C++ versions.
You're using C constructs, but should be using more C++ constructs. std::sort is faster than qsort generally and it's usage is much more intuitive. Here's how you can rewrite it without C++11.
#include <iostream>
#include <vector>
#include <algorithm>
struct results {
unsigned int id; //id of the team
unsigned int m; //number of solved problems
};
// I guess you're trying to sort on number of solved problems. If not, change `.m` to `.id`
bool comparare(const results lhs, const results rhs) {
return lhs.m > rhs.m;
}
int main() {
size_t n;
std::cout << "Enter number of results: " << std::endl;
std::cin >> n;
std::vector<results> standings(n); // Creates std::vector of results with n elements
// read in id and number of problems solved
for(size_t i=0; i < n; ++i) {
std::cin >> standings[i].id >> standings[i].m;
}
// sort the array
std::sort(standings.begin(), standings.end(), comparare);
// output the sorted array's id
for(size_t i = 0; i < standings.size(); ++i) {
std::cout << "In " << i+1 << " place: " << standings[i].id << " with " << standings[i].m << " problems solved." << std::endl;
}
return 0;
}
Here's the ideone with an example.
Your comparison function comparare is not appropriate if the values can exceed INT_MAX. For example comparing UINT_MAX and 0 will cause an overflow when returning UINT_MAX - 0 as an int. It is undefined behavior and on common platforms it will actually be negative.
Use this comparison function instead:
//compare function for qsort()
int comparare(const void *i, const void *j) {
unsigned int ni = *(unsigned int*)i;
unsigned int nj = *(unsigned int*)j;
return (ni > nj) - (ni < nj);
}
It returns -1, 0 or 1 if *i is respectively smaller than, equal to or greater than *j.
In C++ there are other more idiomatic ways to sort an array.
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!