I cannot seem to get my try/catch to work correctly. When you implement a try/catch, it's suppose to "throw" whatever string you told it to, right? And if you want, let the program continue on. Well mine does not say what I want it to say, nor does it continue, instead it tells me this then aborts:
Debug Error!! Blah blah blah.exe
R6010 -abort() has been called (Press Retry to debug the app)
I want it to say: "You are trying to add more Items than are allowed. Don't. ", then continue on with the program. It's a LinkedList, it's not suppose to allow it to have more than 30 nodes. It does stop when it tries to add more than 30, just not how I want it to. I'm not sure what I'm doing wrong, help much appreciated!
Main:
Collection<int> list;
for(int count=0; count < 31; count++)
{
try
{
list.addItem(count);
cout << count << endl;
}
catch(string *exceptionString)
{
cout << exceptionString;
cout << "Error";
}
}
cout << "End of Program.\n";
Collection.h:
template<class T>
void Collection<T>::addItem(T num)
{
ListNode<T> *newNode;
ListNode<T> *nodePtr;
ListNode<T> *previousNode = NULL;
const std::string throwStr = "You are trying to add more Items than are allowed. Don't. ";
// If Collection has 30 Items, add no more.
if(size == 30)
{
throw(throwStr);
}
else
{}// Do nothing.
// Allocate a new node and store num there.
newNode = new ListNode<T>;
newNode->item = num;
++size;
// Rest of code for making new nodes/inserting in proper order
// Placing position, etc etc.
}
You're throwing a string, but trying to catch a pointer to a string.
Change your try/catch block to this:
try
{
...
}
catch( const string& exceptionString )
{
cout << exceptionString;
}
The reason you're getting that abort message is because you're not "catching" a type that is compatible with what you're throwing, so the exception is just bypassing your catch and is therefore an "uncaught exception", subject to the default underlying exception handler, which calls abort.
FYI a more standard way is to throw/catch a std::exception object. i.e.
try
{
...
}
catch( std::exception& e )
{
std::cout << e.what();
}
...
throw( std::logic_error("You are trying to add more Items than are allowed. Don't.") );
Related
Consider this program
#include <iostream>
using namespace std;
class sample
{
public:
sample()
{
cout << "consructor called" << endl;
throw 5;
}
void test()
{
cout << "Test function" << endl;
}
};
int main()
{
sample *s = nullptr;
try
{
s = new sample[5];
cout << "allocated" << endl;
}
catch(bad_alloc& ba)
{
cout << ba.what() << endl;
}
catch (const int& f)
{
cout << "catcting exception";
}
return 0;
}
I think the flow will be like this.
1. Allocate the memory for 5 object.
2. call the constructor for each object one by one.
But here while calling the constructor, i'm throwing an exception, which is handled. My doubt is why constructor is not getting called for second objects onwards??
The object creation will be in sequence, it can't create all five objects in one go. When the first object gets created your constructor will get called and as it throws exception, it will move control to exception handler block.
You exception Handler will print the appropriate message and have graceful exit.
Try your test removing throw 5;
The new simple[5] will allocate memory for the 5 simples, and then begin constructing them one by one. Since the first one does a throw 5, the other 4 do not get constructed.
I'm writing a program that creates a vector of pointer-to-objects.
How do I access the individual objects that the pointers reference from the pointer-to-objects vector?
I'm trying to call the speak() function in the class Object for each of the objects that the pointers inside the vector reference.
Thank you for your time
class Object
{
public:
void speak()
{
cout<<"Hello!"<<endl;
}
};
int main()
{
int choice;
vector<Obj*> objVector; //create empty vector of "pointer-to-object"
Object* ptrObj; //point to object
while (choice!=5)
{
cout <<"1.Create Object\n";
cout <<"2.Destroy Object\n";
cout <<"3.Print number of existing Objects\n";
cout <<"4.Tell existing Objects to say Hello\n";
cout <<"5.Quit Program"<<endl;
cout <<"Please enter your choice: ";
cin >> choice;
if (choice==5)
cout <<"\nProgram is quitting\n"<<endl;
else if (choice==1)
{
ptrObj= new Object;
ObjVector.push_back(ptrObj); //adding an Object object
}
else if (choice==2) //remove object
{
objVector.pop_back();
}
else if (choice==3)
{
cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
}
else if (choice==4)
{
for (int i=0; i<objVector.size(); i++)
{
????????????
}
}
}
return 0;
}
In your existing code, you can access the pointer exactly the way you use it elsewhere in code:
Object* obj = objVector[i];
obj->speak();
// or, simply:
objVector[i]->speak();
Using the operator -> is simply another way to say (*objVector[i]).speak().
Alternatively, the idiomatic approach to writing the loop would look like this:
for(vector<Object*>::iterator it = objVector.begin(); it != objVector.end(); ++it) {
// iterators work like another level of pointers, and need to be dereferenced:
(*it)->speak();
}
If your compiler supports C++11, you can rewrite the loop like this:
for(auto it = std::begin(objVector); it != std::end(objVector); ++it) {
(*it)->speak();
}
Or like this, using range-based for, which dereferences the iterator for you:
for(auto& obj : objVector) {
obj->speak();
}
As an aside, there are cases where you will not be sure whether objVector[i] is even in the vector at all, and accessing it may crash your program or even cause demons to fly forth from your nasal cavity.
For added safety, you can reference positions in your vector with the at function, like so:
try {
for (int i=0; i<objVector.size(); i++)
{
Object* obj = objVector.at(i);
obj->speak();
}
} catch (const std::out_of_range& ex) {
cerr << "no object at position " << i << " in objVector" << endl;
cerr << "objVector says " << ex.what() << endl;
}
Notice, though, that this is a lot slower, although it gives you a chance to handle the problem in the catch block. The try block will run the loop and stop and run the catch block if the at function throws an exception - which will be an exception of type out_of_range. Note also that using [i] will not do the same thing, because it does not throw an exception - it doesn't even bother to check if i is within the length of the vector. This happens to also be why [i] is faster than .at(i).
Finally, also notice that the loops using iterators cannot encounter this particular problem, so long as you don't try to use the iterators after adding or removing something from the vector.
The easiest way is to use *(objVector[i])
To access speak, objVector[i]->speak is just shorter.
You can dereference them with *. Like *(ObjVector[i])
But if you just need to call a method of object you can do it with ->
ObjVector[i]->speak()
Unrelated to the question, but I drop some comment to revise the program.
As others pointed out, you can call object function from pointer contained on vector with doing objVector[i]->speak().
However, as #greyfade pointed out, there is leaking memory issue. You have to delete object when the object is created by new. You can delete object by delete like this,
Object* ptr = objVector.back();
objVector.pop_back();
delete ptr;
To erase memory leaking issue, you can store Object object directly in objVector instead of Object*. In this way, you don't have to worry about deleting objects. You can do like this,
int main()
{
int choice;
vector<Object> objVector; //create empty vector of "pointer-to-object"
while (choice!=5)
{
cout <<"1.Create Object\n";
cout <<"2.Destroy Object\n";
cout <<"3.Print number of existing Objects\n";
cout <<"4.Tell existing Objects to say Hello\n";
cout <<"5.Quit Program"<<endl;
cout <<"Please enter your choice: ";
cin >> choice;
if (choice==5)
cout <<"\nProgram is quitting\n"<<endl;
else if (choice==1)
{
objVector.emplace_back(); //adding an Object object
}
else if (choice==2) //remove object
{
objVector.pop_back();
}
else if (choice==3)
{
cout <<"\nThere are " << objVector.size() <<" objects total.\n" << endl;
}
else if (choice==4)
{
for (auto& obj : objVector)
{
obj.speak();
}
}
}
return 0;
}
This code is using c++11 feature. You can add object by calling emplace_back and delete object by just calling pop_back(). Isn't this sweet?
And one more thing. You forgot some code on header. This code cannot be compiled without these headers,
#include <iostream>
#include <vector>
using namespace std;
I'd happy if this code helps you.
I want to know how to apply exception handling when the top variable reaches to a value -1 (no element left to pop). Currently, I am using cout to nofity the user about the stack underflow and returning 0, which is not a good practice. What improvement overall can be made to this pop function and how to notify user and handle the exception when stack reaches a state of underflow.
int Mystack::pop()
{
if (isEmpty())
{
std::cout << "Stack Underflow" << std::endl;
}
else
{
std::cout << "The popped element is" << A[top];
return A[top--];
}
return 0;
}
The Main Section :
case 4:
std::cout << "POP the element" << std::endl;
s1.pop();
break;
You can throw an out_of_range exception:
#include <stdexcept>
int Mystack::pop()
{
if (isEmpty())
throw std::out_of_range("Stack Underflow");
std::cout << "The popped element is" << A[top];
return A[top--];
}
On the client side:
void foo()
{
Mystack ms;
//...
try
{
ms.pop();
}
catch (const std::out_of_range& oor)
{
std::cerr << "Out of Range error: " << oor.what() << '\n';
}
}
Edit: As the comments below mentioned, you can also derive your own exception from std::exception. Here is a simple example:
#include <stdexcept>
struct myStackException : public std::exception
{
const char *what() const noexcept { return "Stack Overflow"; }
};
int Mystack::pop()
{
if (isEmpty())
throw myStackException();
std::cout << "The popped element is" << A[top];
return A[top--];
}
Live (dummy) example: http://ideone.com/ZyqiQ0
Re
” What improvement overall can be made to this pop function
You can
Make it void to make it more exception safe for other item types.
With the current design, if copying of the popped item fails, then there is no way to recover.
Remove internal output.
assert that the underflow doesn't occur, so that this can be caught in testing.
Thus,
void Mystack::pop()
{
assert( top > 0 );
--top;
}
Wow, what a simplification – and now more exception safe too!
As an alternative to the assert you can throw an exception. That's better than the original, but absolutely not better than the assert. It moves correctness issues into the runtime domain, to be handled and perhaps worked around by each caller site.
The benefit of using C++ exceptions is that error handling code can be separated from user code, alleviating the need for code to be littered with error handling code that is common in C programs. Throwing an exception also offers a solution to returning a invalid value in the error case
if( s1.pop() == 0 ){
// is this an error or not?
}
Exceptions can be added to your code like so, by taking advantage in the generic exceptions in the
#include <stdexcept>
header file.
int Mystack::pop()
{
if (isEmpty())
{
throw std::range_error("nothing to pop");
}
std::cout << "The popped element is" << A[top];
return A[top--];
}
Then you add a try/catch block to the appropriate code, perhaps with
case 4:
std::cout << "POP the element" << std::endl;
try{
s1.pop();
}
catch(const std::range_error& e)
{
std::cerr << "unable to pop!\n";
// error handling code
}
break;
Another solution, particularly appropriate when errors aren't as exceptional, such as with file I/O is more intrusive to the user code, but offers a better solution than returning an arbitrary value
int Mystack::pop(int& value)
{
if( isEmpty() )
{
return 1;
}
std::cout << "The popped element is" << A[top];
value = A[top--];
return 0
}
And then your code becomes
case 4:
std::cout << "POP the element" << std::endl;
{
int value;
if( s1.pop(value) == 1 ){
// error code
}
}
break;
I am using a library, RapidXML, but my problem is more general. The library parses xml like item->first_node("CRAP")->first_node("CRAP") Now, if I put this in an if statement it will crash. If I put this: item->first_node("CRAP") it won't.
I am a beginner in C++ and I don't know much about exceptions but:
try
{
if(item->first_node("CRAP")->first_node("CRAP"))
{
}
cout << "OK";
} catch (...)
{
cout << "CRASH";
}
The above crashes. How to check if my node exists without crashes (and without looping all the items one by one)?
You simply need to take it one step at a time:
if (item != 0) // check if item is null
{
rapidxml::xml_node<char>* node = item->first_node("CRAP"); // Try to grab first child node
if (node != 0)
{
// okay got a valid node, grab next one
rapidxml::xml_node<char>* next = node->first_node("CRAP");
if (next != 0)
{
// Okay
}
}
}
When you try it in one step, i.e. item->first_node("CRAP")->first_node("CRAP"), you never check that the first call to first_node returned a null pointer (assuming item is a valid pointer also).
Sounds like either item is NULL or item->first_node("CRAP") is returning NULL. Try this, see what output you get:
try
{
node *n; // <-- use whatever type first_node() actually returns
if (!item)
cout << "item is NULL";
else
{
n = item->first_node("CRAP");
if (!n)
cout << "first node is NULL";
else
{
n = n->first_node("CRAP");
if (!n)
cout << "second node is NULL";
else
cout << "OK";
}
}
}
catch (...)
{
cout << "CRASH";
}
Always test whether an expression is NULL before using it as part of a longer expression. Never write things like
if(item->first_node("CRAP")->first_node("CRAP"))
if first_node("CRAP") can return NULL. Instead, write something like
if(item->first_node("CRAP") && item->first_node("CRAP")->first_node("CRAP"))
This works because the '&&' (logical and) operator uses lazy evaluation: it won't bother to evaluate its second operand if the first one evaluates to false.
map<string,string>::find seems to be returning garbage iterator, since i can access neither my_it->first nor second (NB: my_it != my_map.end() is verified). VC2010 reports a debug error, and looking deeper reveals
my_it is (Bad Ptr, Bad Ptr).
The 'offending' map is a class attribute, _match, shown below in context:
class NicePCREMatch
{
private:
map<string, string, less<string> > _match;
public:
void addGroup(const string& group_name, const string& value);
string group(const string& group_name);
};
Here is the code that returns elements by key (the commented-out code works fine):
string NicePCREMatch::group(const string& group_name)
{
/*for (map<string, string, less<string> >::iterator j = _match.begin(); j != _match.end(); j++)
{
if(!strcmp(j->first.c_str(), group_name.c_str()))
{
return j->second;
}
}
throw runtime_error("runtime_error: no such group");*/
map<string, string, less<string> >::iterator i = _match.find(group_name);
if (i == _match.end())
{
throw runtime_error("runtime_error: no such group");
}
return i->second;
}
And Here is the code that inserts new elements in the map:
void NicePCREMatch::addGroup(const string& group_name, const string& value)
{
_match.insert(pair<string, string>(group_name, value));
}
Another class uses NicePCREMatch as follows:
template<class Match_t>
vector<Match_t> NicePCRE<Match_t>::match(const string& buf)
{
[snip]
Match_t m;
[snip]
m.addGroup(std::string((const char *)tabptr + 2, name_entry_size - 3), \
buf.substr(ovector[2*n], ovector[2*n+1] - ovector[2*n]));
[snip]
addMatch(m);
[snip]
return _matches;
}
Where,
template<class Match_t>
void NicePCRE<Match_t>::addMatch(const Match_t& m)
{
_matches.push_back(m);
}
Finally, client code uses NicePCRE class as follows:
void test_NicePCRE_email_match(void)
{
NicePCRE<> npcre;
npcre.compile("(?P<username>[a-zA-Z]+?)(?:%40|#)(?P<domain>[a-zA-Z]+\.[a-zA-Z]{2,6})");
vector<NicePCREMatch> matches = npcre.match("toto#yahoo.com");
assert(!matches.empty());
assert(!strcmp(matches.begin()->group("username").c_str(), "toto"));
cout << matches.begin()->group("domain").c_str() << endl;
assert(!strcmp(matches.begin()->group("domain").c_str(), "yahoo.com"));
}
BTW, this --is pretty much-- my main (the oddest TDD ever :) ):
int main()
{
int test_cnt = 0;
cout << "Running test #" << test_cnt << " .." << endl;
test_NicePCRE_email_match();
cout << "OK." << endl << endl;
test_cnt++;
SleepEx(5000, 1);
return 0;
}
What am I doing wrong here?
EDIT:
The following modification (compare with the version above) solved my problem. Viz,
void NicePCREMatch::addGroup(const string& group_name, const string& value)
{
_match.insert(pair<string, string>(group_name.c_str(), value.c_str()));
}
Client code (slightly modified) now looks like this:
void test_NicePCRE_email_match(void)
{
NicePCRE<> npcre;
npcre.compile("(?P<username>[a-zA-Z]+?)(?:%40|#)(?P<domain>[a-zA-Z]+\.[a-zA-Z]{2,6})");
vector<NicePCREMatch> matches = npcre.match("toto#yahoo.com");
assert(!matches.empty());
try
{
assert(!strcmp(matches.begin()->group("username").c_str(), "toto"));
assert(!strcmp(matches.begin()->group("domain").c_str(), "yahoo.com"));
cout << "username = " << matches.begin()->group("username") << endl;
cout << "domain = " << matches.begin()->group("domain") << endl;
}
catch (const runtime_error& e)
{
cout << "Caught: " << e.what() << endl;
assert(0x0);
}
}
This is quite bizarre. Can someone please explain. However, I consider my problem solved already.
Thanks every one.
Your issue is here
if (i == _match.end())
{
throw runtime_error("runtime_error: no such group");
}
return i->second;
Your find failed for some reason. I can't say why because I don't have the full code. But, after the failure, you are throwing an error, but there is nobody to catch outside. Please add a try catch at the point where you call the method group() and implement the logic if the match is not found.
I tried with your sample snippets (+ some changes to get the stuff compiled) and it looks like visual studio continues with the next line in the function even after a throw statement. I don't know the theory behind it. I was bit surprised at seeing such a behavior.
[To make sure that your class structure is not causing the problem, I tried with a simple global method and even the method also gave me the same behavior. If there are somebody who can explain this please feel free.]
This might be caused by three things - either you modify the map in some way after the execution of find or you have a memory coruption somewhere in your program or the debugger is simply not showing the correct values for the iterator.
Try using debug output - if the code crashes when you try to output the values, then probably the iterator is really broken.
Also make sure you do not modify the map after the execution of find. If you do, this may make the iterator invalid and so you need to move the find call immedietly before using the iterator.
If both of the above options don't help you probably have memory corruption somewhere and you need to find it. Maybe use valgrind for that. Please note this should be your last resort only when the two other options are proved impossible.