I'm trying to write a tic tac toe game in C++, but whenever I run it I get an error message saying:
TicTacToe.cpp: In instantiation of ‘void copy_array(T*, T*) [with T = std::basic_string<char>]’:
TicTacToe.cpp:115:25: required from here
TicTacToe.cpp:93:3: error: no match for ‘operator*’ in ‘**(new_arr + ((sizetype)(((long unsigned int)i) * 8ul)))’
It points to this function:
86 template<class T>
87 void copy_array(T old_arr[], T *new_arr)
88 {
89 int size = sizeof(old_arr)/sizeof(old_arr[0]);
90 for(int i = 0; i < size; i++)
91 {
92 *new_arr[i] = old_arr[i];
93 }
94 }
An this piece of code:
114 string copy[9];
115 copy_array(board, copy);
Could anyone please explain to me what's causing the error and how to solve it?
That error message is quite strange, it appears to be printing out a transformed version of your code, but I'm pretty sure it's referring to this line:
*new_arr[i] = old_arr[i];
Remove the * and you should be fine.
Although of course it won't function as you expect. Your argument T old_arr[] is going to act exactly like T *old_arr. Notably, sizeof(), which you're relying on to give you the full size of the array, won't.
You could use the following template to get around this:
template<class T, int N>
void copy_array(T (&old_arr)[N], T *new_arr) {
for (int i = 0; i < N; i++) {
new_arr[i] = old_arr[i];
}
}
Or, if you can use C++11, you could switch to std::array<>, which knows its size.
change this:
*new_arr[i] = old_arr[i];
for this:
new_arr[i] = old_arr[i];
when you use the brackets c++ internally dereference the pointer.
This does a safer variation of what you want:
template<typename T, size_t size>
void copy_array(T (&old_arr)[size], T (&new_arr)[size])
{
std::copy(&old_arr[0], &old_arr[0] + size, &new_arr[0]);
}
It enforces that the size of the destination is the same as the size of the source. If you end up wanting to override that, you really should reconsider your design.
Related
So I am trying to write quicksort algorithm in c++ with vectors.
template <typename T>
T qsort(vector<T> arr)
{
int mid_idx = round(arr.size() / 2);
int root_el = arr[mid_idx];
vector<T> smaller;
vector<T> bigger;
vector<T> equals;
for (T i: arr)
{
if (arr[i] > root_el)
bigger.push_back(arr[i]);
else if (arr[i] < root_el)
smaller.push_back(arr[i]);
else
equals.push_back(arr[i]);
}
return (qsort(smaller) + equals + qsort(bigger));
}
And I am getting this error:
invalid operands to binary expression ('int' and 'vector<int>') [Semantic Issue]
So can you tell me what is wrong?
There are a few problems with this C++ code.
The qsort template function clearly intends to return a vector, from the return instruction at the end. But it is declared as returning a single object of type T.
Also, the vector argument is passed by value, which is expensive for large vectors (duplication). I suggest to pass it by reference instead.
So we could change the top declaration to this:
template <typename T>
vector<T> qsort(vector<T>& arr)
{
A more fundamental problem: from the code, it seems that every call to qsort causes, recursively and unconditionally, two more calls to qsort. If the function is written that way, the program cannot terminate. Or rather, the operating system will kill it when it has exhausted stack space and thus makes some illegal memory access.
Every recursive algorithm needs some terminating condition. In our case, there is nothing to do if the size of the array is less than 2, as it is obviously already sorted.
So the beginning of the qsort function could be written this way:
#include <vector>
#include <cmath>
#include <iostream>
using std::vector;
template <typename T>
vector<T> qsort(vector<T>& arr)
{
if (arr.size() < 2)
return arr; // so small it is already sorted !
Also, in the for loop, variable i is used as an integer index, but is declared as an object of type T. The loop could be written like this instead:
for (int i = 0; i < arr.size(); i++)
{
if (arr[i] > root_el)
bigger.push_back(arr[i]);
else if (arr[i] < root_el)
smaller.push_back(arr[i]);
else
equals.push_back(arr[i]);
}
Now, we come to the final return instruction:
return (qsort(smaller) + equals + qsort(bigger));
The line of code above obviously assumes that for vectors, the “+” operator means vector concatenation. But actually this is left undefined in the C++ standard. So there is no definition for vector “+” in scope, even after including the <vector> header file.
Furthermore, if the question of standardizing “+” for vectors ever came before the international C++ standardization committee, there would be tremendous pressure, notably from the computational physics community, in favor of defining it in the traditional way as found in common math and physics textbooks.
That is, the value of [10,20,30] + [2,4,6] would have to be [12,24,36] and not [10,20,30,2,4,6] as your code seems to imply.
So we have to do this vector concatenation manually, like this for example, using the insert STL method:
auto lts = qsort(smaller);
auto gts = qsort(bigger);
// concatenate sorted vectors:
lts.insert(lts.end(), equals.begin(), equals.end());
lts.insert(lts.end(), gts.begin(), gts.end());
return lts;
Overall, the following version of the code works as expected:
template <typename T>
vector<T> qsort(vector<T>& arr)
{
if (arr.size() < 2)
return arr; // so small it is already sorted !
int mid_idx = arr.size() / 2;
T root_el = arr[mid_idx];
vector<T> smaller;
vector<T> bigger;
vector<T> equals;
for (int i = 0; i < arr.size(); i++)
{
if (arr[i] > root_el)
bigger.push_back(arr[i]);
else if (arr[i] < root_el)
smaller.push_back(arr[i]);
else
equals.push_back(arr[i]);
}
auto lts = qsort(smaller);
auto gts = qsort(bigger);
// concatenate sorted vectors:
lts.insert(lts.end(), equals.begin(), equals.end());
lts.insert(lts.end(), gts.begin(), gts.end());
return lts;
}
Testing code:
int main()
{
vector<int> v1 { 609,396,620,173, 742,996,880,125,
478,745,206,798, 998,124,960,175 };
vector<int> v2 = qsort(v1);
for (auto m : v2) {
std::cout << m << ' ';
}
std::cout << std::endl;
return EXIT_SUCCESS;
}
Program output:
$ ./q64784877.x
124 125 173 175 206 396 478 609 620 742 745 798 880 960 996 998
$
Notes on efficiency:
Your code creates a number of temporary vectors, and thus dynamically allocates a significant amount of memory. If you look at the traditional versions of Quicksort, the code does not allocate any extra memory. It does all its work within the initial array, but that makes the algorithm slightly more complex.
Also, the code aboves uses recursion to the very bottom end, stopping only when the subvectors are down to a size of 1. In practice, it is probably more efficient to switch to a non-recursive, simpler algorithm such as Insertion Sort when the subarray size is down to 10 or 15. To be tested on your platform for the exact optimal threshold value.
This is my code. I'm Trying to find max element in this. The Data_Test file is a simple txt file that have 12 data. In my case, 12 number that list one by one below to each other : 122 135 148 156 178 189 256 114 125 136 630 360. compiler says that cannot convert 'main()::str' to 'int' in initialization. How can i convert it to int?
ifstream input("Data_Test.txt");
const int NUMstr = 4;
struct str{
string Data[NUMstr];
};
str vec;
vector<str> event;
int maxElementIndex = max_element(event.begin(), event.end()) - event.begin();
int maxElement = *max_element(event.begin(), event.end());
int minElementIndex = min_element(event.begin(), event.end()) - event.begin();
int minElement = *min_element(event.begin(), event.end());
cout << "maxElementIndex:" << maxElementIndex << ", maxElement:" << maxElement;
cout << "minElementIndex:" << minElementIndex << ", minElement:" << minElement;
The first strange thing is why you are using strings when you actually have integers.
The second strange thing is why you have (effectively) a vector of arrays.
struct str{
string Data[NUMstr];
};
This is an array wrapped inside a structure. And this vector<str> is a vector of structures, each of which wraps an array. I see no reason that you need this, in your problem description you just have a list of twelve numbers.
You're also a little confused about how iterators work.
So I suspect you are just getting confused and making things way more complicated than they need to be. This code works, it's a simple vector of integers, I suspect it is all that you need.
vector<int> event;
...
int maxElementIndex = max_element(event.begin(), event.end()) - event.begin();
int maxElement = event[maxElementIndex];
You need to know the logic how you want your str struct to be converted to int. You can convert std::string to int using std::stoi, e.g.:
const int i = std::stoi("123");
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have an std::vector of struct pointers, in which I would like to remove duplicate entries. However, I would like to compare one member of the struct instead of the pointer directly. When I do it the incorrect way (comparing the pointers directly) there is no segfault; the dupes simply don't get removed. However, when I access the element in question to compare, I get a segfault.
My first guess would be that the structs are invalid/freed, but I can put that member in a char array and print it to the debug log right before without an issue, so this does not seem to be the case.
If the structs are valid (which they both seem to be and should be; I calloc every one before adding it), then I don't know why comparing their members would cause any issue.
Anyways, here is my code:
struct definition:
81 struct fp_node{
82 Tile *t;
83 unsigned int g;
84 unsigned int h;
85 unsigned int score;
86 struct fp_node *parent;
87 char type;
88 };
Accessing that member without issue
279 #ifdef DEBUG
280 for(unsigned int i = 0; i < open_list.size(); ++i){
281 char address[11];
282 snprintf(address, 11, "0x%08x", open_list[i]->t);
283 gui::log("Open list entry " + std::to_string(i) + ": " + std::string(address));
284 }
285 #endif
dupe filtering causing the issue:
291 for(unsigned int i = 0; i < open_list.size(); ++i){
292 for(unsigned int j = 0; j < open_list.size(); ++j){
293 if(i == j) continue;
294 if(open_list[i]->t == open_list[j]->t){
295 free(open_list[j]);
296 open_list.erase(open_list.begin() + j);
297 i -= 1;
298 j -= 1;
299 }
300 }
301
302 for(unsigned int j = 0; j < closed_list.size(); ++j){
303 if(open_list[i] != closed_list[j]) continue;
304 free(open_list[i]);
305 open_list.erase(open_list.begin() + i);
306 i -= 1;
307 }
308 }
Notice that in the first j for loop, I access the t member of the struct. This causes the segfault. The second j loop does simply compares the pointers. It doesn't segfault but it isn't what I want.
I tried accessing methods from the tile class, but those segfault as well, so I do think the memory is somehow being freed automatically in the meantime. I don't know why though, as everything is on the heap except for the vectors themselves, which are in a larger scope and shouldn't die.
However, when I try to access the member in only one part of the comparison (if((Tile *)open_list[i] == open_list[j]->t)), I don't get a segfault; same with the other side.
I'm completely lost here, can someone please help me?
Thanks.
Hope the sleepy in my eyes is not making my mind see spots, but something jumps out at me.
Hard to say for sure as you don't say how open_list is allocated. Since open_list is released by free() I'm going to assume it is a simple pointer allocated by malloc() or calloc() and these are C functions. Never tried mixing malloc() and size(), or new() and free(), but I would fear that array size reported by from open_list.size() would not change under free().
See http://www.cplusplus.com/reference/array/array/size/
I'm new to arduino and it's programing language. I learnt that we can't have methods returning arrays, but we can use pointers as an alternative.
So I have this method:
byte SUM(byte A, byte B, bool Cyi, byte *sum, bool *Cyo)
{
bool d0;
bool d1;
for(int i = 0; i < 8; ++i)
{
d0 = bitRead(A,i);
d1 = bitRead(B,i);
bitWrite(*sum,i,d0 ^ d1 ^ Cyi);
*Cyo = d0 && d1 || Cyi && (d0 ^ d1);
Cyi = Cyo;
}
}
I'am new to pointers but I guess the problem here is that bitWrite method does not accept a pointer? I don't know what do to next and I need some help.
Thanks in advance.
Adruino is not a programming language but a microcontroler platform for which you could write code in c.
you wrote in your code:
Cyi = Cyo;
but Cyi is of type "bool" and Cyo a type of "bool *" correct it with
Cyi = *Cyo;
Hey all, I'm trying to write a sort function but am having trouble figuring out how to initialize a value, and making this function work as a generic template. The sort works by:
Find a pair =(ii,jj)= with a minimum value = ii+jj = such at A[ii]>A[jj]
If such a pair exists, then
swap A[ii] and A[jj] else
break;
The function I have written is as follows:
template <typename T>
void sort(T *A, int size)
{
T min =453;
T temp=0;
bool swapper = false;
int index1 = 0, index2 = 0;
for (int ii = 0; ii < size-1; ii++){
for (int jj = ii + 1; jj < size; jj++){
if((min >= (A[ii]+A[jj])) && (A[ii] > A[jj])){
min = (A[ii]+A[jj]);
index1 = ii;
index2 = jj;
swapper = true;
}
}
}
if (!swapper)
return;
else
{
temp = A[index1];
A[index1] = A[index2];
A[index2] = temp;
sort(A,size);
}
}
This function will successfully sort an array of integers, but not an array of chars. I do not know how to properly initialize the min value for the start of the comparison. I tried initializing the value by simply adding the first two elements of the array together (min = A[0] + A[1]), but it looks to me like for this algorithm it will fail. I know this is sort of a strange type of sort, but it is practice for a test, so thanks for any input.
most likely reason it fails, is because char = 453 does not produce 453 but rather different number, depending what char is (signed versus unsigned). your immediate solution would be to use numerical_limits, http://www.cplusplus.com/reference/std/limits/numeric_limits/
you may also need to think about design, because char has small range, you are likely to overflow often when adding two chars.
The maximum value of any type is std::numeric_limits<T>::max(). It's defined in <limits>.
Also, consider a redesign. This is not a good algorithm. And I would make sure I knew what I was doing before calling my sort function recursively.
I haven't put too much time reading your algorithm, but as an alternative to std::numeric_limits, you can use the initial element in your array as the initial minimum value. Then you don't have to worry about what happens if you call the function with a class that doesn't specialize std::numeric_limits, and thus can't report a maximum value.