Why does my program using cstring work while the one from the book doesn't?

  • C/C++
  • Thread starter yungman
  • Start date
  • Tags
    C++
In summary, the conversation discusses a problem with using string literals as exceptions in a C++ program. The first attempt, following a program from a book, results in a runtime error. The second attempt, using a cstring, successfully solves the problem. The issue is identified as a mismatch in types, with the exception handler expecting a char* while the throw statement is using a const char*. Adding const to the catch statement resolves the issue. The conversation also mentions difficulties with understanding the term "exceptionString" and how it relates to the throw statement.
  • #1
yungman
5,755
293
I followed the program from the book and it doesn't work. I simplified to show what's going on. I solve the problem and show in the second program. It's the good old cstring and the string literal again.

This is from the book, it doesn't work:
C++:
#include <iostream>
using namespace std;

int main() {

    try
    {
        throw "Alan";//throw a string literal as in the book
    }
    catch (char *e)
    {
        cout << "An exception occurred. Exception Nr. " << e << '\n';
    }
    return 0;
}

The error is:
Error1.jpg
I experimented and made it work, this is my program:
C++:
int main() {

    try
    {    char Cr[] = "Alan";
        throw Cr;//Using cstring works.
    }
    catch (char* e)
    {
        cout << "An exception occurred. Exception Nr. " << e << '\n';
    }
    return 0;
}

Only difference is I throw a cstring Cr that contain "Alan". It works.

This is my first day on this, I have no idea why the one in the book doesn't work and why it has to be like what I did to make it work.

Please help explain this.

Thanks
 
Technology news on Phys.org
  • #2
I haven't worked with exceptions myself, except to play with them a little when I was learning C++, but...

Remember, string literals are type const char*. I suggest changing the catch statement in your first version to catch (const char *e).

IIRC we were "caught" by this in a different situation in the last few months. I think more recent versions of C++ are stricter about const than when Gaddis wrote his book.

[added] Aha, here it is, back in September:

https://www.physicsforums.com/threads/mysterious-error.993493/#post-6391433
 
Last edited:
  • Like
Likes Jarvis323
  • #3
Now I've had a chance to experiment with your code. With my compiler, both versions (without and with const) compile.

When I run the first version (without const), I get a runtime error message:
terminating with uncaught exception of type char const*

When I run the second version (with const), I get the output that you provided:
An exception occurred. Exception Nr. Alan

So the problem in the first version is indeed the mismatch in types. Your exception handler (the catch block) expects to receive an exception of type char *. You threw an exception of type const char * (a literal string), which "fell through" without being caught.

I'll try adding a second catch block that expects to receive a const char *:

C++:
#include <iostream>

using namespace std;

int main() {

    try
    {
        throw "Alan";//throw a string literal as in the book
    }
    catch (char *e)
    {
        cout << "A char*  exception occurred. Exception Nr. " << e << '\n';
    }
    catch (const char *e2)
    {
        cout << "A const char*  exception occurred. Exception Nr. " 
             << e2 << '\n';
    }
    return 0;
}
The compiler gives me a warning:
warning: exception of type 'const char *' will be caught by earlier handler [-Wexceptions]
note: for type 'char *'


Nevertheless, it runs and produces the output generated by the second catch block:
A const char* exception occurred. Exception Nr. Alan

Next, I tried throwing a char* array as in your second version:

C++:
#include <iostream>

using namespace std;

int main() {

    char Cr[]  = "Alan";
    try
    {
        throw Cr; 
    }
    catch (char *e)
    {
        cout << "A char*  exception occurred. Exception Nr. " << e << '\n';
    }
    catch (const char *e2)
    {
        cout << "A const char*  exception occurred. Exception Nr. " 
             << e2 << '\n';
    }
    return 0;
}
I got the same compiler warning, and when I ran it, I got the output from the first catch block:
A char* exception occurred. Exception Nr. Alan

Summary: The type of the object that you throw determines which catch block receives it. If it doesn't match any catch block, it "falls through" and generates a run-time error.
 
  • Like
Likes harborsparrow, Jarvis323 and jedishrfu
  • #4
jtbell said:
I haven't worked with exceptions myself, except to play with them a little when I was learning C++, but...

Remember, string literals are type const char*. I suggest changing the catch statement in your first version to catch (const char *e).

IIRC we were "caught" by this in a different situation in the last few months. I think more recent versions of C++ are stricter about const than when Gaddis wrote his book.

[added] Aha, here it is, back in September:

https://www.physicsforums.com/threads/mysterious-error.993493/#post-6391433
Thanks so much Jtbell.

Yes, just adding const made it work. I am developing a phobia with the word const! This word tripped me more than anything else in C++.

Gaddis book is getting worst. I read through the paragraphs many times:
Book exception.jpg


It never explain "exceptionString" in the book. I looked up on line and guess it out. It is argument of the throw statement. I even type "exceptionString in C++" on line, went around in circles thinking it was a function or special word in C++. After reading some examples, then I guess it's just a name of strings and it's whatever argument of the throw.

The book is getting worst in the later chapters and is starting to hinder me in learning.

Thank you so much. I have to read your second post. I just want to reply to acknowledge you first.

Thanks
 
  • Haha
Likes harborsparrow
  • #6
jedishrfu said:
Pretty soon @yungman you’ll be writing the book.
The book is really getting worst by the chapter. You can read the page I copied, no where it said what is exceptionString is. I really thought it's a special function and went search up and down. It was until I read cplusplus( I think) used just "e". Then I started to realize it's just meant taking the argument from throw statement and use it in catch! I went back and read the book over, still I do not see anywhere taking about this.

Chapter 15 on Polymorphism was almost as bad, I went through the problems like 10 pages and still don't have any idea what it's for until people here explained it. I went back and read it later after I understood it, still it's not clear in the book.

I am starting to use The book by Ivor Horton and Peter Van Weert right now to read through it.
 
  • #7
jedishrfu said:
Pretty soon @yungman you’ll be writing the book.
I wouldn't hold my breath.
 
  • Haha
Likes jedishrfu
  • #8
Mark44 said:
I wouldn't hold my breath.
Don't worry, not interested. This is just an exercise for my brain, definitely don't have to passion for it. I don't even want to try to write a book in electronics which I am qualify and have the passion for it. For what? This is just a passing stage like music and photography. I got good, became pro and just dropped it. This is what is fun in life. I already starting to look at the next adventure, it's just not very easy to find one that is challenging and fun. Been into car fixing, gun smithing, cooking, those are just not challenging enough.
 
  • Love
  • Like
Likes fluidistic and jedishrfu
  • #9
Just the first 3 pages of the book by Ivor is a lot clearer:
Ivor1.jpg

Ivor2.jpg

Ivor3.jpg
 
  • Like
Likes harborsparrow and jedishrfu
  • #10
It's not a good idea to throw and catch pointers, partly due to the const/non-const issue you have observed. You can avoid the whole mess as follows.
C++:
#include <iostream>
#include <stdexcept>

int main() {

    try
    {
        // runtime_error can be constructed from a C-style string or a std::string
        throw std::runtime_error("Alan");
    }
    catch (const std::runtime_error& e) // works equally well without const, but I'm not modifying e, so I specify const
    {
        // e.what() gives you the string with which e was constructed
        std::cout << "An exception occurred. Exception Nr. " << e.what() << '\n';
    }
    return 0;
}
 
  • Like
Likes harborsparrow, Jarvis323 and yungman
  • #11
jbunniii said:
It's not a good idea to throw and catch pointers, partly due to the const/non-const issue you have observed. You can avoid the whole mess as follows.
C++:
#include <iostream>
#include <stdexcept>

int main() {

    try
    {
        // runtime_error can be constructed from a C-style string or a std::string
        throw std::runtime_error("Alan");
    }
    catch (const std::runtime_error& e) // works equally well without const, but I'm not modifying e, so I specify const
    {
        // e.what() gives you the string with which e was constructed
        std::cout << "An exception occurred. Exception Nr. " << e.what() << '\n';
    }
    return 0;
}
Thanks

But I have not learn runtime_error and e.what(). Must be later in the chapter.

Thanks
 
  • #12
I am starting to switch to Ivor book. I have been busy taking the book apart by chapters to make it easier to read, not having to carry the big book around. I have neck problem, I cannot sit and read, have to lie down and keep moving. So I take the book apart and stable each section together, each of about 30 pages. Here is a picture of the few I did today:
Books.jpg
Funny, I have two of the Ivor book. I bought the first one from Amazon, it got lost. After a week or so, they sent me a new book. Then 2 or 3 weeks later, the original book arrived. So I ended up have two. So I can take one apart. Actually the second book is under my laptop to prop it up to make it easier for my neck.

One thing good of Gaddis 6th edition, cplusplus actually posted the pdf file of the brief version. I printed the whole book out and stapled into small section to study. I don't have the pdf for the long book and the Ivor, so I have to take the book apart into small sections like in the picture.
 
  • Like
Likes fluidistic
  • #13
@yungman - I'm curious to know how you chose these books instead of C++ Primer by Lippman, Lajoie, and Moo. That's the one I would generally recommend for learning C++.
 
  • Like
Likes yungman
  • #14
Last edited:
  • Like
Likes harborsparrow and jbunniii
  • #15
  • #16
jbunniii said:
That link is to the 4th edition which only covers C++98. There is a 5th edition, which expands coverage to C++11 (a very different language in a lot of ways!) https://www.amazon.com/dp/0321714113/?tag=pfamazon01-20

But the 4th edition is very good if you don't care about learning the C++11 features (yet).
Thanks, I just want to learn C++, I have no plan to be expert nor looking for a job. I think it's good enough already.

Thanks
 
  • Like
Likes jbunniii
  • #17
I have been spending time with the Ivor book. I see some problems with their drawings. I want to run by you guys. The writing makes good sense, it's the diagrams. This is what I modify according to the write up.

Let's look at the first page. I red lined it said the exception object is COPIED FIRST. Then in green lined, all the local objects in the try block are DELETED. Copy has to come first then delete. Look at the fig.15.2, I have to modify the drawing to reflect the sequence. Also, block 3 has to go to the FIRST CATCH, not the Nth catch in the drawing.

Now, look at the next page. Read the line that exception thrown by fun3() passes BACK to fun1(). The diagram is just wrong. I have to modify the diagram.

I am taking back what I said about the Ivor book, the description is very good so far as you can see, it makes the whole world of sense, but the drawing are bad. Wasted me a lot of time going through just this two pages.
Ivor mod.jpg


Tell me what you think. This is very very important, I want to confirm with you guys before I mark up the book.

Thanks
 
  • Haha
Likes harborsparrow
  • #18
I went ahead and wrote down the notes as I understand from the Ivor book regarding to the last post. I hope I am right in the exception handling process:
 

Attachments

  • Ivor notes.docx
    15.4 KB · Views: 184
  • #19
Nobody have any comment?

I am in big trouble, recall in post 12, I cut the book into small section, stabled and read individually for my neck problem? I somehow put them with the dirty cloths and ran dumped into the washer and started washing! By the time I realized and took it out, they are quite ruined. I am drying them out, meaning I have nothing to read. I might have to buy another used book just to cut it apart as I don't have pdf file that I can print it out.

What a disaster.
 
  • #20
Back to the question in post 17 about whether the throw follows the path back from fun3() back to fun1() back to try, or the throw go straight from fun3() to catch. I wrote the program and step through it with f11.
C++:
#include<iostream>
using namespace std;
void fun2(int b)
{//go to line 5
    if (b > 2) throw 20;//go straight to line 21
}
void fun1(int a)
{//go to line 9
    fun2(a);//jump to line 4
}

int main()
{    int x;
    cout << " Enter an integer between 0 to 2: "; cin >> x;//enter 5
    try//go to line 17
    {
        fun1(x);//go to line line 8
        cout << " You entered: " << x << "\n\n";
    }
    catch(int e)
    {cout << " Out of range.\n\n";}//go to line 22
    cout << " Program ends.\n\n";//go to line 23
    return 0;//go to line 24
}

I put in comments where the line jump to next.

I entered 5 which is out of range. The program will go to fun1() line 9. Then jump to line 4 then line 5. Since I entered 5, I triggered a throw and jump straight to line 21.

It does NOT go back to fun1() and back to try before going to catch. It jump straight from fun2() throw straight to catch, BYPASSING fun1() and try block.

Can I conclude the writing in Ivor book is wrong and the diagram is correct?

Thanks
 
Last edited:
  • #21
Nobody have any comment?
Patient: Doc it hurts when I do this.
Doctor: Well, then don't do that.
I somehow put them with the dirty cloths and ran dumped into the washer and started washing
We can't police what goes on between you and your washing machine.
 
  • Like
  • Haha
Likes Jarvis323, Vanadium 50 and yungman
  • #22
sysprog said:
Patient: Doc it hurts when I do this.
Doctor: Well, then don't do that.

We can't police what goes on between you and your washing machine.
Ha ha!

But isn't it important to know how the program flows? Ivor book have problem. I spent half a day reading and looking at the drawings, only one of them can be right. I think my program shows the drawings is right and the description in the book is wrong. I read it over over 10 times.

You can see in the second page, I red lined it said passing onto the calling function. My stepping show it doesn't.
 
  • #23
yungman said:
I am in big trouble, recall in post 12, I cut the book into small section, stabled and read individually for my neck problem? I somehow put them with the dirty cloths and ran dumped into the washer and started washing!

To paraphrase @Mark44,

No wonder you have trouble with washing machines...
 
  • Like
  • Haha
Likes yungman and sysprog
  • #24
@yungman Do you you have a scanner? Maybe if you're going to take books apart you could scan the pages before putting them at risk? Then if something happens maybe you could resort to the scans?
 
  • #25
yungman said:
I think my program shows the drawings is right and the description in the book is wrong.
What does the computer do?
 
  • #26
sysprog said:
What does the computer do?
What I described in post 20, I traced through every step where the program jump from line to line.

I am sure it jump directly from line 5 straight to line 21 in catch. I have experience stepping VS, if it goes back to the calling function, it ALWAYS go back to the calling function before exit.

It bypass fun1() and try and jump straight to catch block.Isn't this very important to know? Gaddis say nothing about this at all.

thanks
 
  • #27
yungman said:
Ha ha!

But isn't it important to know how the program flows? Ivor book have problem. I spent half a day reading and looking at the drawings, only one of them can be right. I think my program shows the drawings is right and the description in the book is wrong. I read it over over 10 times.

You can see in the second page, I red lined it said passing onto the calling function. My stepping show it doesn't.
It looks like the book is correct.

Here is some code you can use to verify.

C:
#include<iostream>
using namespace std;

struct A
{
    ~A() {
        cout << "destroying A" << endl;
    }
};

struct E
{
    E() {}
    E( const E & other ) {
        cout << "copy constructor E" << endl;
    }
};

void fun2( int b )
{
    if (b > 2) throw E();
}
void fun1(int a)
{
    fun2(a);
}

int main()
{   
    int x = 5;

    try
    {
        A a;
        fun1( x );
        cout << "You entered: " << x << "\n\n";
    }
    catch( E e )
    {
        cout << "Out of range.\n\n";
    }
   
    cout << "Program ends.\n\n";
   
    return 0;
}

The output shows that the automatic objects in the try block (A a) are destroyed before the exception is copied to the argument of the catch block.

destroying A
copy constructor E
Out of range.

Program ends.
 
  • Like
Likes sysprog
  • #28
yungman said:
It does NOT go back to fun1() and back to try before going to catch

Why do you think it should? Throw goes to catch. It doesn't mean "try, try again".
 
  • Haha
  • Like
Likes Jarvis323 and sysprog
  • #29
Jarvis323 said:
It looks like the book is correct.

Here is some code you can use to verify.

C:
....

The output shows that the automatic objects in the try block (A a) are destroyed before the exception is copied to the argument of the catch block.

destroying A
copy constructor E
Out of range.

Program ends.
Thanks Jtbell

I ran your program step by step and label where the line jump to the next line. You can follow where the program goes. It NEVER return from fun2() back to fun1() and return back to try. That is exactly like what my program did. That's the whole point of my post 17. Here is your program with the steps added in comment:
C++:
#include<iostream>
using namespace std;

struct A
{
    ~A() {
        cout << "destroying A" << endl;// to 8
    }//to 40
};

struct E
{
    E() {}//to 21
    E(const E& other) {
        cout << "copy constructor E" << endl;// to 16
    }// to 7
};

void fun2(int b)//Never return back to fun1()
{//to 21
    if (b > 2) throw E();//to 13  to 15
}
void fun1(int a)
{//to 25
    fun2(a);//to 20
}

int main()
{
    int x = 5;// to 34

    try
    {
        A a;//to 35
        fun1(x);//to 24
        cout << "You entered: " << x << "\n\n";
    }
    catch (E e)
    {
        cout << "Out of range.\n\n";// to 41
    }// to 43

    cout << "Program ends.\n\n";// to 45

    return 0;
}

Thanks
 
  • #30
Vanadium 50 said:
Why do you think it should? Throw goes to catch. It doesn't mean "try, try again".
If you look at post 17, the right side page I labeled "Pass back to func1". You see the book twice said the throw pass back to the calling function.

Yes, My stepping program in post 20 proofed it just go directly from throw in fun2() straight to catch. I am challenge the book. You can see Figure 15.3 is correct that it bypass fun1() and jump straight to catch. The description in the book and fig.15.3 does NOT match.

Thanks
 
  • #31
Regarding the code in post #20, this is what happens after you enter a number such as 3.
  1. fun1() is called in the try block.
  2. fun1() calls fun2().
  3. Since the argument is larger than 2, it throws 20.
  4. Control is transferred to the catch block, where it prints "Out of range."
  5. Control then goes to the next line, which prints "Program ends."
  6. main() then returns.
 
  • Like
Likes yungman
  • #32
Mark44 said:
Regarding the code in post #20, this is what happens after you enter a number such as 3.
  1. fun1() is called in the try block.
  2. fun1() calls fun2().
  3. Since the argument is larger than 2, it throws 20.
  4. Control is transferred to the catch block, where it prints "Out of range."
  5. Control then goes to the next line, which prints "Program ends."
  6. main() then returns.
Yes, after I posted in post 17 and wasting my time on it, I decided this morning just write a program to proof in in post 20, it's exactly like what you layout here, it doesn't back track like the page in Ivor book page in post 17.

It doesn't matter how the program goes, it's more to find out whether I can trust the Ivor book. I read through it many times and I red line the sentences that support my assertion that the writing in the book does NOT match up to the drawings of the book. You can take a look at post 17.

thanks
 
  • #33
yungman said:
Thanks Jtbell

I ran your program step by step and label where the line jump to the next line. You can follow where the program goes. It NEVER return from fun2() back to fun1() and return back to try. That is exactly like what my program did. That's the whole point of my post 17. Here is your program with the steps added in comment:
C++:
#include<iostream>
using namespace std;

struct A
{
    ~A() {
        cout << "destroying A" << endl;// to 8
    }//to 40
};

struct E
{
    E() {}//to 21
    E(const E& other) {
        cout << "copy constructor E" << endl;// to 16
    }// to 7
};

void fun2(int b)//Never return back to fun1()
{//to 21
    if (b > 2) throw E();//to 13  to 15
}
void fun1(int a)
{//to 25
    fun2(a);//to 20
}

int main()
{
    int x = 5;// to 34

    try
    {
        A a;//to 35
        fun1(x);//to 24
        cout << "You entered: " << x << "\n\n";
    }
    catch (E e)
    {
        cout << "Out of range.\n\n";// to 41
    }// to 43

    cout << "Program ends.\n\n";// to 45

    return 0;
}

Thanks
This was about the things you claimed were wrong on the left side of the image you posted. The other thing you thought was wrong (from the right side of the image), I didn't follow exactly. I think you confused what the author was saying/showing.
 
  • #34
Jarvis323 said:
This was about the things you claimed were wrong on the left side of the image you posted. The other thing you thought was wrong (from the right side of the image), I didn't follow exactly. I think you confused what the author was saying/showing.
Oh, I have not even get to the left side yet. Let me go through that and get back to you. My book is still drying, it's not as if I have better things to do! :(

Read through the right side, I read it like 20 times. See whether I am wrong or not.
 
  • #35
yungman said:
Oh, I have not even get to the left side yet. Let me go through that and get back to you. My book is still drying, it's not as if I have better things to do! :(

Read through the right side, I read it like 20 times. See whether I am wrong or not.
I think the diagram is just a confusing diagram because of the clutter.

It says "Normal return" at the end of fun1(){} with an arrow that goes to after fun1(); is called. That means if an exception is NOT thrown, it goes there. The other arrow, says exception can be handled here, points directly from fun1() throw to the catch block.

This is the same as your program shows and as the book says, it's just easy to misread the diagram.
 

Similar threads

Replies
118
Views
8K
Replies
89
Views
5K
Replies
35
Views
3K
Replies
89
Views
5K
Replies
19
Views
1K
Replies
39
Views
4K
Replies
5
Views
2K
Back
Top