I'm learning exception handling in C++. Here is my code:
#include <iostream>
#include <cmath>
using namespace std;
class point{
private:
float x, y;
public:
enum Error{
negative_coordinates,
};
point();
point(float, float);
~point();
float return_x();
float return_y();
};
point::point(){
}
point::point(float a, float b){
if(x < 0 && y < 0){
throw negative_coordinates;
}
else{
x = a;
y = b;
}
}
point::~point(){
}
float point::return_x(){
return x;
}
float point::return_y(){
return y;
}
int main()
{
try{
float x, y;
cout << "Enter coordinates of some point: " << endl;
cin >> x >> y;
if(x < 0 && y < 0){
throw (0);
}
}
catch(point::Error e){
const char * message [] = {"You entered negative coordinates"};
cout << "" << message[e] << endl;
}
}
If I put two negative values I got this:
terminate called after throwing an instance of 'int'
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
Process returned 3 (0x3) execution time : 5.420 s
Press any key to continue.
Any idea?
You throw an 'int' when you enter two negative values, but you catch a point. The types of your throw and catch need to be the same. If I change: catch(point::Error e) to catch(int e), the program runs fine.
As per: http://www.cplusplus.com/doc/tutorial/exceptions/
Related
I got a problem by implementing a queue in C++. I looked for similar problems, but didn't find anything usefull.
I'm using Visual Studio 2019.
I seperated my program in a Main.cpp, a Queue.h and Queue.cpp, Patient.h and Patient.cpp.
I tried to convert the concept for this from Java to C++, but I just can't find a solution for my function getInfo().
I get an exception like this:
Unhandled exception at 0x7C0EF3BE (ucrtbased.dll) in Queue.exe: 0xC0000005: Access violation reading location 0xE8884D8D.
Would be nice if anyone could help me with my problem and explain what I did wrong.
I'm just a beginner so don't be too harsh on me pls xD
Main.cpp:
#include "Queue.h"
#include "Patient.h"
int main() {
Queue queue;
Patient patient1("Name1");
Patient patient2("Name2");
queue.add(patient1);
queue.add(patient2);
queue.getInfo();
}
Queue.h:
#pragma once
#include <iostream>
#include "Patient.h"
using namespace std;
class Queue {
private:
Patient* beginning;
Patient* end;
int amount;
public:
Queue();
void add(Patient p);
Patient remove();
void getInfo();
};
Queue.cpp:
#include "Queue.h"
Queue::Queue() {
beginning = 0;
end = 0;
amount = 0;
}
void Queue::add(Patient p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
Patient Queue::remove() {
if (amount == 0) {
cout << "You can't remove a patient. The Queue is empty!" << endl;
} else {
*beginning = beginning->getFollower();
amount--;
}
return *beginning;
}
void Queue::getInfo() {
if (amount == 0) {
cout << "The Queue is empty!" << endl;
} else {
cout << "There are " << amount << " Patients in the Queue!" << endl;
cout << "The following list provides all Patients in the Queue-order:" << endl;
beginning->getInfo();
}
}
Patient.h:
#pragma once
#include <iostream>
#include <string>
using namespace std;
class Patient {
private:
string name;
Patient* follower;
string* nameptr;
public:
Patient(string newname);
void setFollower(Patient p);
Patient getFollower();
void getInfo();
};
Patient.cpp:
#include "Patient.h"
Patient::Patient(string newname) {
name = newname;
follower = 0;
nameptr = &name;
}
void Patient::setFollower(Patient p) {
follower = &p;
}
Patient Patient::getFollower() {
return *follower;
}
void Patient::getInfo() {
cout << *nameptr << endl;
if (follower == 0) {
cout << "No follower existing!" << endl;
}
else {
follower->getInfo();
}
cin.get();
}
There are a few places where you mix up passing by value with passing by reference.
To start with, the first problem is here:
void Queue::add(Patient p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
You are passing the value of Patient p rather than a reference to the actual object. To fix this you only need to add an "&" to your functional call like this:
void Queue::add(Patient& p) {
if (amount == 0) {
beginning = &p;
end = &p;
} else {
end->setFollower(p);
end = &p;
}
amount++;
}
Note the "&" in the parameters list. Then you must also update the function header:
class Queue {
private:
Patient* beginning;
Patient* end;
int amount;
public:
Queue();
void add(Patient& p);
Patient remove();
void getInfo();
};
You must also pass by reference for your setFollower function:
void Patient::setFollower(Patient& p) {
follower = &p;
}
and in the header file:
void setFollower(Patient& p);
What you need to know going forward is that in C++ all arguments are passed by value unless you specify passing by reference in the function's parameter list. Here is an article about passing variables to functions if you'd like to read more (https://iq.opengenus.org/call-by-value-vs-call-by-reference-cpp/).
I don't know why c++'s rule says that I can't return local variable?
this simple "max" function totally has no problem;
int max(int a,int b)
{
int maxnum;
if(a>b)maxnum= a;
else maxnum= b;
return maxnum;
}
int main( int argc, char** argv )
{
cout<<max(10,30);
system("PAUSE");
return 0;
}
but, when I want to return local variable as before in opencv,it turns out wrong data
why can't I return local variable here?
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <sstream>
using namespace cv;
using namespace std;
Mat GetIntensity(Mat *pic,int y,int x)
{
float Array[6];
for(int i=0;i<6;i++)
{
Array[i]=pic[i].at<uchar>(y,x);
}
Mat Intensity(6,1,CV_32FC1,&Array);
cout<<Intensity;
return Intensity;
}
int main( int argc, char** argv )
{
stringstream ss;
string pic_name;
Mat pic[6];
for(int i=0;i<6;i++)
{
ss.clear();
ss.str(std::string());
ss<<"pic"<<i<<".bmp"<<endl;
ss>>pic_name;
pic[i] = imread(pic_name, CV_LOAD_IMAGE_GRAYSCALE);
if(! pic[i].data )
{// Check for invalid input
cout << "Could not open or find the image" << endl ;
system("pause");
return -1;
}
//namedWindow( pic_name, CV_WINDOW_AUTOSIZE );
// Create a window for display.
//imshow(pic_name, pic[i] );
}
cout<<=GetIntensity(pic,60,60);
system("PAUSE");
//waitKey(0);
return 0;
}
your construct here uses a local array to hold the values. this will get invalid, once your Mat leaves the scope:
Mat GetIntensity(Mat *pic,int y,int x)
{
float Array[6]; //problem
for(int i=0;i<6;i++)
{
Array[i]=pic[i].at<uchar>(y,x);
}
Mat Intensity(6,1,CV_32FC1,&Array); // problem
cout<<Intensity;
return Intensity;
}
better create a Mat with it's own data:
Mat GetIntensity(Mat *pic,int y,int x)
{
Mat Intensity(6,1,CV_32FC1); // no problem
for(int i=0;i<6;i++)
{
Intensity.at<float>(i) = pic[i].at<uchar>(y,x);
}
cout<<Intensity;
return Intensity;
}
I'm trying to figure out the best way to do the following using Thrust: vector A has a million floats, they have some particular order. I want to move to vector B every element x in A for which x>7.0 such that the order of elements is maintain in both vectors A and B. Importantly, only a tiny fraction of elements need be moved. Efficiency is more important for my code than elegance.
My idea was to use thrust::copy_if from A to B and then thrust::remove_if on A. But I don't know the exact number of elements to be copy, and since apparently the memory for B must be allocated in advance, another counting operation is necessary. An inelegant way to skip the counting operation is to pre-allocate "enough" memory for vector B.
Using thrust::remove_copy_if has much the same problems: you need to allocate memory for B in advance, and also it doesn't actually remove anything from A so another thrust::remove_if is required anyway.
Another idea I had was to use thrust::stable_sort with some custom-made comparison functor, to push all elements I want out to the end of A, and then somehow figure out how many there are and thrust::copy them to B. This also looks pretty inelegant...
You're on the right track with thrust::copy_if. Just allocate two more buffers of the same size as the first one. Then copy_if > 7.0f to the first one and copy_if <= 7.0f to the second one. Allocating buffers of the same size as the original buffer is fine as long as you know there's room, and 1 million floats only takes up 4MB.
Edit:
I did a performance comparison of the copy_if and stable_partition approaches. On my card, a GTX660, stable_partition took around 150% as long as copy_if for "split" values of 0.1f, 0.5f and 0.9f. I added tests to ensure that both methods are stable (maintain the order of the values).
#include <cuda.h>
#include <curand.h>
#include <thrust/device_vector.h>
#include <thrust/host_vector.h>
#include <thrust/copy.h>
#include <thrust/partition.h>
#include <iostream>
#include <cassert>
#define CHECK_CUDA_CALL(x) do { if((x)!=cudaSuccess) { \
printf("Error at %s:%d\n",__FILE__,__LINE__);\
return EXIT_FAILURE;}} while(0)
#define CHECK_CURAND_CALL(x) do { if((x)!=CURAND_STATUS_SUCCESS) { \
printf("Error at %s:%d\n",__FILE__,__LINE__);\
return EXIT_FAILURE;}} while(0)
#define SPLIT 0.1f
struct is_low
{
__host__ __device__ bool operator()(const float x)
{
return x <= SPLIT;
}
};
struct is_high
{
__host__ __device__ bool operator()(const float x)
{
return x > SPLIT;
}
};
class EventTimer {
public:
EventTimer() : mStarted(false), mStopped(false) {
cudaEventCreate(&mStart);
cudaEventCreate(&mStop);
}
~EventTimer() {
cudaEventDestroy(mStart);
cudaEventDestroy(mStop);
}
void start(cudaStream_t s = 0) {
cudaEventRecord(mStart, s);
mStarted = true;
mStopped = false;
}
void stop(cudaStream_t s = 0) {
assert(mStarted);
cudaEventRecord(mStop, s);
mStarted = false;
mStopped = true;
}
float elapsed() {
assert(mStopped);
if (!mStopped) return 0;
cudaEventSynchronize(mStop);
float elapsed = 0;
cudaEventElapsedTime(&elapsed, mStart, mStop);
return elapsed;
}
private:
bool mStarted, mStopped;
cudaEvent_t mStart, mStop;
};
int main(int argc, char *argv[])
{
const size_t n = 1024 * 1024 * 50;
// Create prng
curandGenerator_t gen;
CHECK_CURAND_CALL(curandCreateGenerator(&gen, CURAND_RNG_PSEUDO_DEFAULT));
// Set seed
CHECK_CURAND_CALL(curandSetPseudoRandomGeneratorSeed(gen, 1234ULL));
// Generate n floats on device
thrust::device_vector<float> vec_rnd_d(n);
float* ptr_rnd_d = thrust::raw_pointer_cast(vec_rnd_d.data());
CHECK_CURAND_CALL(curandGenerateUniform(gen, ptr_rnd_d, n));
thrust::device_vector<float> vec_low_d(n);
thrust::device_vector<float> vec_high_d(n);
for (int i = 0; i < 5; ++i) {
EventTimer timer;
timer.start();
thrust::device_vector<float>::iterator iter_end;
iter_end = thrust::copy_if(vec_rnd_d.begin(), vec_rnd_d.end(), vec_low_d.begin(), is_low());
thrust::copy_if(vec_rnd_d.begin(), vec_rnd_d.end(), vec_high_d.begin(), is_high());
timer.stop();
std::cout << "copy_if: " << timer.elapsed() << "ms" << std::endl;
// check result
thrust::host_vector<float> vec_rnd_h = vec_rnd_d;
thrust::host_vector<float> vec_low_h = vec_low_d;
thrust::host_vector<float> vec_high_h = vec_high_d;
thrust::host_vector<float>::iterator low_iter_h = vec_low_h.begin();
thrust::host_vector<float>::iterator high_iter_h = vec_high_h.begin();
for (thrust::host_vector<float>::iterator rnd_iter_h = vec_rnd_h.begin();
rnd_iter_h != vec_rnd_h.end(); ++rnd_iter_h) {
if (*rnd_iter_h <= SPLIT) {
assert(*low_iter_h == *rnd_iter_h);
++low_iter_h;
}
else {
assert(*high_iter_h == *rnd_iter_h);
++high_iter_h;
}
}
}
for (int i = 0; i < 5; ++i) {
thrust::device_vector<float> vec_rnd_copy = vec_rnd_d;
EventTimer timer;
timer.start();
thrust::device_vector<float>::iterator iter_split =
thrust::stable_partition(vec_rnd_copy.begin(), vec_rnd_copy.end(), is_low());
timer.stop();
size_t n_low = iter_split - vec_rnd_copy.begin();
std::cout << "stable_partition: " << timer.elapsed() << "ms" << std::endl;
// check result
thrust::host_vector<float> vec_rnd_h = vec_rnd_d;
thrust::host_vector<float> vec_partitioned_h = vec_rnd_copy;
thrust::host_vector<float>::iterator low_iter_h = vec_partitioned_h.begin();
thrust::host_vector<float>::iterator high_iter_h = vec_partitioned_h.begin() + n_low;
for (thrust::host_vector<float>::iterator rnd_iter_h = vec_rnd_h.begin();
rnd_iter_h != vec_rnd_h.end(); ++rnd_iter_h) {
if (*rnd_iter_h <= SPLIT) {
assert(*low_iter_h == *rnd_iter_h);
++low_iter_h;
}
else {
assert(*high_iter_h == *rnd_iter_h);
++high_iter_h;
}
}
}
CHECK_CURAND_CALL(curandDestroyGenerator(gen));
return EXIT_SUCCESS;
}
Output:
C:\rd\projects\cpp\test_cuda\Release>test_cuda.exe
copy_if: 40.2919ms
copy_if: 38.0157ms
copy_if: 38.5036ms
copy_if: 37.6751ms
copy_if: 38.1054ms
stable_partition: 59.5473ms
stable_partition: 61.4016ms
stable_partition: 59.1854ms
stable_partition: 61.3195ms
stable_partition: 59.1205ms
To answer my own question, I finally found thrust::stable_partition, which is more efficient and elegant than all "copy_if"-alternatives. It just moves all elements that fail to satisfy a predicate to the end of the array and returns the start of the second sequence. Pointer arithmetic gives the size of B, but in fact it's not necessary anymore:
thrust::device_vector<float>::iterator iter = thrust::stable_partition(A.begin(), A.end(), pred)
thrust::device_vector<float> B(iter, A.end())
A.erase(iter, A.end());
Please Help
I am writing a program in C++ using visual basic 2010 the program is called "Palindrome integer" I need to write two functions one that//Return the reversal of an integer. For example reverse(456) returns 654
//with header:-->
int reverse(int number)
I need to write another function that//Returns true if number is a palindrome
//with header:-->
bool isPalindrome(int number)
I need to use the reverse function to implement the function isPalindrome. A number is a palindrome if the numbers reversal is the same as itself. My program should report whether the number is a palindrome. Everything is in one file.
I think this program worked when I first wrote the code not as two functions but just directly into int main(). But I must put the code into the specified two functions and once I had done that and made the adjustments I got the following error messages and the black cout display box didn't appear. Here's a snippet of the error report followed by the full error report
: error LNK2005: "int __cdecl reverse(int)" (?reverse##YAHH#Z) already defined in Driver.obj
:fatal error LNK1169: one or more multiply defined symbols found
I'm getting the following Error Report
1>------ Build started: Project: Palindrome integer, Configuration: Debug Win32 ------
1>Build started 12/7/2013 4:54:25 PM.
1>InitializeBuildStatus:
1> Touching "Debug\Palindrome integer.unsuccessfulbuild".
1>ClCompile:
1> All outputs are up-to-date.
1>ManifestResourceCompile:
1> All outputs are up-to-date.
1>implementation.obj : error LNK2005: "int __cdecl reverse(int)" (?reverse##YAHH#Z) already defined in Driver.obj
1>c:\documents and settings\dell\my documents\visual studio 2010\Projects\Palindrome integer\Debug\Palindrome integer.exe : fatal error LNK1169: one or more multiply defined symbols found
1>
1>Build FAILED.
1>
1>Time Elapsed 00:00:02.25
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
//Bellow is my Code
#include <iostream>
#include <cmath>
#include <iomanip>
using namespace std;
//Retun reversal of an integer
int reverse(int number); //function prototype
//Return true if number is a palindrome
bool isPalindrome(int number); //function prototype
//Driver
int main()
{
int usersNumber = 456; //0; //a few lines commented tempararily for easier number testing
// cout<<"Enter a number and I'll tell you if it's a Palindrome: ";
// cin>> usersNumber;
bool palindromeToF = (isPalindrome(usersNumber));
if (palindromeToF == true)
{
cout <<"YES the number is a Palindrome";
}
else
{
cout <<"NO the number is not a Palindrome";
}
return 0;
}
//function Implementation
//Retun reversal of an integer
int reverse(int number)
{
//do while loop to count number of digits in Number
int digitsCount = 0;
double exponent1 = 1.0;
int quotient;
do
{
int tenToPower = pow( 10.0, exponent1);
// cout <<"tenToPower "<< tenToPower <<"\t ";
quotient = (number / tenToPower);
// cout <<"exponent1 "<< exponent1<<"\t ";
exponent1++;
//cout <<"quotient "<< quotient<< "\t "<<endl;
digitsCount++;
}while (!quotient == 0);
//populating array "arrDigits" with integer's digits
int *arrDigits = NULL;
arrDigits = new int[digitsCount];
double exponent2 = 0.0;
for(int i = 0; i < digitsCount; i++)
{
int powerOfTen = pow( 10.0, exponent2);
//cout <<endl<<"adding "<<((number / powerOfTen) % 10) <<" to sum";
//cout <<powerOfTen;
arrDigits[i]= ((number / powerOfTen) % 10);
exponent2++;
}
//reverse number & populate array "arrDigRevers" with reversed order number
int *arrDigRevers = NULL;
arrDigRevers = new int[digitsCount];
int j = 0;
int reversedNum = 0;
double exponent3 = 0.0;
for(int i = digitsCount-1; i >= 0; i--)
{
int powerOfTenB = pow( 10.0, exponent3);
reversedNum += (powerOfTenB * arrDigits[i]); //return of reverse func.
exponent3++;
/* //reversed integer put into array
if(j < digitsCount)
{
arrDigRevers[j] = arrDigits[i];
//cout <<"\t"<< "arrDigRevers"<<"["<< j<<"]="<< arrDigRevers[j]<<" "<< "arrDigits"<<"["<< j<<"]="<< " "<<arrDigits[j]<<" ";
j++;
}
*/
}
delete[] arrDigits;
delete[] arrDigRevers;
arrDigits = NULL;
arrDigRevers = NULL;
//cout <<endl<<"reversed number is "<< reversedNum;
return reversedNum;
}
//function Implementation
//Return true if number is a palindrome
bool isPalindrome(int number)
{
if(number == reverse(number))
{
return true;
}
else
{
return false;
}
}
The answer lies here:
1>implementation.obj : error LNK2005: "int __cdecl reverse(int)" (?reverse##YAHH#Z) already defined in Driver.obj
It appears that have defined int reverse(int number) in both implementation.cpp and Driver.cpp. You need to rename or remove one of these definitions from your project.
Related questions:
Determining exception type after the exception is caught?
How can I determine the current exception in a catch (...) block?
This question differs because I don't care about portability. I'm interested in code specifically for g++ or perhaps even specific versions of g++ (4.6.3). It will not be used in production.
I'm dealing with legacy code that has thousands of throw statements with perhaps hundreds of thrown types. This code runs on nearly 1000 machines and catches about 40 throws per day. It is not repeatable.
At the outside layer, I can do a try { /.../ } catch (...) { /* caught it */ } and see that an exception was thrown. But I have not been able to find the type of the exception, let alone the location it is thrown from.
I believe the information must be available because code like the following works and prints "Y":
#include <iostream>
using namespace std;
struct X {};
struct Y {};
struct Z {};
int main(int, char **) {
try {
//...
throw Y();
//...
} catch (...) {
cout << "Caught unknown" << endl;
try {
throw;
} catch (const X &x) {
cout << "X" << endl;
} catch (const Y &y) {
cout << "Y" << endl;
} catch (const Z &z) {
cout << "Z" << endl;
}
}
}
Are there any [non-portable|dirty|nasty|ugly]* tricks to identify the exception type under g++ in a catch (...)?
Here's what I use:
#include <cxxabi.h>
using std::string;
string deMangle(const char* const name)
{
int status = -1;
char* const dem = __cxxabiv1::__cxa_demangle(name, 0, 0, &status);
const string ret = status == 0 ? dem : name;
if (status == 0)
free(dem);
return ret;
}
string getGenericExceptionInfo()
{
const std::type_info* t = __cxxabiv1::__cxa_current_exception_type();
char const* name = t->name();
return deMangle(name);
}
Usage:
catch (...)
{
std::cerr << "caught: " << getGenericExceptionInfo() << std::endl;
}