Thank you very much, Hericles. Your suggestion worked perfectly!
Nathaniel10 34 Junior Poster
I would like to express a superscript and a subscript in the same vertical space. For example, consider a variable called X with a subscript 1 that is squared.
I have searched for examples of what I want to do but cannot find anything close.
X<sub>1</sub><sup>2</sup>
The above is the best I can do, but I want the 1 and the 2 aligned vertically.
Does anyone know if this is possible and, if so, how to do it?
Thanks in advance.
PS: Word processors call this overstrike, but most search hits treat overstrikes as strike throughs.
Nathaniel10 34 Junior Poster
Philippe, you were partly correct. The height of the ad columns was not the problem.
I researched the float property of CSS and discovered that it wasn't the problem either. The problem was margins.
I was able to achieved the layout I wanted by setting the left and right margins of the center column equal to the width of my left and right ad columns. The example demonstrating that solution was on a site called "communitymx (dot) com".
I am marking this thread solved.
Nathaniel10 34 Junior Poster
Well, neither of the 2 alternatives I listed in my prior posts worked. I'm stuck. :(
Nathaniel10 34 Junior Poster
Thanks for your reply, Clerisy.
I checked out those tutorials. None addressed my specific problem but I got some ideas. I think there are two possible solutions.
1.
div.container {height: whatever}
div.center {height: inherit}
div.left {height: inherit}
div.right {height: inherit}
2.
div.container {position: relative}
div.center {position: absolute}
div.left {position: absolute}
div.right {position: absolute}
I can't test either one right now because my employer blocks up/downloading of files. I will test both tonight.
What are the strengths and weaknesses of each of the possible solutions?
Nathaniel10 34 Junior Poster
I should have searched before posting. The "inherit" property seems to be the answer to my problem. I haven't found any good examples of how to use it. How can I use the "inherit" property to make the left and right columns have the same height as the center column?
Nathaniel10 34 Junior Poster
I am organizing my site to make it easier and faster to maintain. I keep a small version of my site on my laptop running Apache/PHP. I successfully organized and recoded things to the way I wanted. Upon uploading the file to my live site, I ran into several problems. One involves my layout.css file and how the formatting is being rendered in the HTML.
My pages have 3 column divisions: a center one for content, and left and right ones for ads. In my Apache laptop, the columns are rendered fine. But in the live site, the center column shifts to the left at the bottom of the ad. Playing with the height of the column helps for some pages. What I really need is a way make the left and right columns the same height as the center column. The 'auto' feature doesn't achieve that, as in
height: auto
.
Say the CSS code is as follows:
div.left {height: 250px}
div.right {height: 250px}
div.center {height: 750px}
Is there a way to extend the height of the left and right columns so they are automatically the same height as the center column? The height of the center column is determined by the amount of content.
Thanks in advance.
Nathaniel10 34 Junior Poster
I tested my site's server for sensitivity to case in the file paths. I discovered that it is. Matching the folder name EXACTLY, case included, solved the problem of not finding the layout files.
That leaves the problem of my CSS formatting is so messed up. I actually discovered why. I ask for help in another thread.
Nathaniel10 34 Junior Poster
Hielo,
Thank you for your prompt reply.
On my laptop I did check for case and found that my Apache server was case INsensitive. I have NOT checked for case sensitivity on my live site server. I will do that later today. I have upper case first letter for the folder names. I am pretty sure I used all lower case in the file paths. It has never been a problem for linking the different pages of my site.
Still, the layout is messed up. If you are correct, then I have a second problem with how my CSS layout is being rendered in HTML.
Nathaniel10 34 Junior Poster
Hi. This is not a frequently browsed category, but there is no place else for my question.
I am organizing my site to make it easier and faster to maintain. I keep a small version of my site on my laptop running Apache/PHP. I successfully organized and recoded things to the way I wanted. The root has only the homepage (index.html). I have the style.css file, image files, and header and footer files in a folder called Style. I have pages such as 'About Us' and 'Contact Us' in a folder called Fold_1.
In my aboutus.php file, I access the header and footer files using
<?php> include ('../style/header.php') ?>
In the header.php file, I access the style sheet and images using
< (...) href = "../style/style.css">
In the style.css file, I access the background image using
{background-image:url('bgimage.gif');}
This works perfectly in Apache/PHP on my laptop.
When I uploaded files coded this way to my live site, NOTHING WORKED. The pages like aboutus.php had no CSS formatting, and no code from the header or footer. It was as if the file was not locating any of the styling files. I was able to have the file find the header and footer by changing the address to
<?php> include ('http://www.sitename.com/style/header.php') ?>
However, the CSS formatting was completely off. The positions of the divisions (left, center, right) were skewed. The positions of the links in the navigation bars in the header and …
Nathaniel10 34 Junior Poster
OK, Narue. Thanks for your reply.
I think I understand the first part of it.
For line 13, the two values should be equal to each other and be 123.
For line 12, the two values should be equal to each other and be the address of variable i.
For line 11, the two values should be equal to each other and be the address of pointer p1.
For line 10, the two values should be equal to each other and be the address of pointer p2.
For the second part, I referred back to my Stroustrup book. It does discusses how the * and & operators do not function identically(?) for chars and ints. It advises the use of reinterpret_cast to deal with conversions of type. I am not at all clear on this, but fortunately, do not need that knowledge in the near future. I will read more on how types affect pointer and de-reference operators.
Nathaniel10 34 Junior Poster
Narue,
Thank you very much for your outstanding explanation of pointers. Like the OP, I am also self-learning C++. Your post has raised my understanding of pointers several levels, as the books and tutorials I read were nowhere near as clear.
I have a follow-up question. (Not to hi-jack the OP's thread, but it is very relevant.) Does nesting/recursion work for the dereferencing operator as well?
int i = 123;
int *p1 = &i;
int **p2 = &p1;
int ***p3 = &p2;
...
int &i = *p1;
int &&i = **p2;
int &&&i = ***p3;
I am suspecting not, as I can't reason through a logical pathway.
Nathaniel10 34 Junior Poster
I was going to suggest exactly what MrIdul posted above.
It may take some effort to write the loops for sine and cosine to the degree of precision you need, unless you have experience with the infinite series topic in advanced calculus.
Nathaniel10 34 Junior Poster
Thanks guys, i figured it out how to show "1000" under principal. Thanks for the help.
That was not your only error. The principal balance at the beginning of a month should be equal to the remaining balance at the end of the prior month. Your output does not show that. You have the same principal amounts at the beginning and end of the same month for the entire 24 month period.
I suggest creating a new variable called 'principalBegin' and change the 'principal' variable to 'principalEnd'. Initialize 'principalBegin' to 1,000 and change line 39 to 'principalEnd = principalBegin - principalPaid'.
Since you are a ComSci major and not a Finance major, I will only point out, and not offer any correction to, your conceptually erroneous calculations. To compute a loan amortization table (your exercise) one must use the present value interest factor of an annuity corresponding to the interest rate, payment frequency, and life of the loan. Ask a finance professor at your university about it because your C++ professor likely won't have a clue.
Nathaniel10 34 Junior Poster
I recently faced a similar issue when I was learning about page layout using CSS.
As I understand it, and I may not be understanding it fully or correctly, when you are using relative positioning, you can use negative margins. That is because the margin anchor (top left) will be that of the base element's position. If you wanted an element to be higher than or to the left of the base element, then you would use negative margin values.
Nathaniel10 34 Junior Poster
I manage a small website. I participate in forums that are relevant to our business. ALL these forums prohibit advertising in the posts. That includes links to a site that you reference in your post. They force you to buy advertising on their site.
I have also written 2 or 3 submissions to blogs. The links that you include in your post must have a "nofollow" option in the anchor reference. The Google robot ignores the link so page rank is not improved.
Off-page SEO is not easy or cut-and-dried.
Nathaniel10 34 Junior Poster
I worked on my problem and, with some help from another forum, came up with this code.
#include "../../std_lib_facilities.h"
class Goods {
protected:
double unit_labor;
double price;
double labor;
public:
double getUnit_labor(string country, string goods) {
if (country == "home" && goods == "apples") {unit_labor = 6;}
if (country == "home" && goods == "bananas") {unit_labor = 3;}
if (country == "foreign" && goods == "apples") {unit_labor = 8;}
if (country == "foreign" && goods == "bananas") {unit_labor = 12;}
return unit_labor;
}
double getLabor(string country, string goods) {
if (country == "home" && goods == "apples") {labor = 500;}
if (country == "home" && goods == "bananas") {labor = 800;}
if (country == "foreign" && goods == "apples") {labor = 300;}
if (country == "foreign" && goods == "bananas") {labor = 1000;}
return labor;
}
};
class Apples : public Goods {
public:
};
class Bananas : public Goods {
public:
};
class Country {
protected:
double labor;
double capital;
public:
double getLabor(string country, string goods) {
if (country == "home" && goods == "apples") {labor = 500;}
if (country == "home" && goods == "bananas") {labor = 800;}
if (country == "foreign" && goods == "apples") {labor = 300;}
if (country == "foreign" && goods == "bananas") {labor = 1000;}
return labor;
}
};
class Home : public Country {
public:
};
class Foreign : public Country {
public:
};
class World {
protected:
double labor;
double capital;
public:
Goods apples;
Goods bananas;
Country home;
Country foreign; …
Nathaniel10 34 Junior Poster
I am developing my own project for the practice. I am having a great deal of difficulty conceptualizing the classes I want. The scenario is that of 2 countries, each capable of producing 2 goods, using 2 factors of production.
Specifically, Lower Mongolia and Upper Mongolia have certain amounts of workers (labor) and machines (capital) with which each can produce some combination of guns and butter. Each good has a selling price, a labor use requirement, and a capital use requirement.
I made classes of the goods with their 3 members. I instantiated with the countries. I decided to use only 1 factor for simplicity. This didn't work because of duplicate variables for each good. By that I mean, the term Lower_Mongolia.price was the same for both guns and butter.
I am considered making a base class called country, having labor and capital as members, with derived classes for the goods, having price, labor use, and capital use, as members. However, I can't find good examples of how to instantiate the country names of Upper Mongolia and Lower Mongolia in the main() section. I still wind up with duplicate variables like Lower_Mongolia.price for both guns and butter.
Is there a way to achieve the organization I want using classes?
Nathaniel10 34 Junior Poster
Thank you for your comments, FP.
I have the Random class in order to use srand() outside the main() section. This was recommended by a poster on another site, as I explained in reply to Software Guy. I was under the impression that srand() needed to be called before calling rand(). As I call rand() in the first 3 function I thought I needed to call srand() before then. Is it possible for rand() above the main() to be seeded by srand() called in the main() section? If so, then you would be correct that the random class is not needed.
I had rooms[] in a class in the first versions of this program. I can still see how a class for it can be appropriate in that a constructor can initialize it and hazards[] to the values I give. I get stumped as to what objects to give them. I initially had wumpus, pit, and bat as objects for a room, but main() was even more complicated than it is now because there are 4 rooms and I was trying to loop over them. (You can take a look at a thread titled "Wumpus Hunt" from Monday or Tuesday.) How can I make classes for rooms[] and hazards[] giving them objects that don't complicate main() even more?
I tried to make main() simpler by making functions for the randomization of the room numbers and the room hazards. But those are arrays so the function would have …
Nathaniel10 34 Junior Poster
@ firstPerson,
What areas of the program/code can be made less complex and how?
Nathaniel10 34 Junior Poster
Thanks for the comment. I was using classes in earlier versions but found I was able to consolidate them by using arrays. I would not have used any classes for this version except that the compiler wouldn't accept the random number seed above the main() section. I found a suggestion on the Web that worked, which was to create a class just for the seed and initialize it in a constructor.
What other classes do you suggest? I got a tongue lashing from a poster on another forum for poorly using classes. His point, while harsh, was not without merit. There is judgment involved in deciding whether to use classes, structs, both, or neither. Judgment that I have not yet fully developed.
Nathaniel10 34 Junior Poster
I have made revisions to my program. I gave up on the idea of using functions that return arrays. That was far too complicated for the expected benefit. This latest version compiles and runs correctly with all of the provisions required by the exercise.
What remains is feedback on the efficiency and elegance of the program. What I ask is for constructive comments on how the code for this game could have been written with fewer lines, and making better use of C++ features.
Please bear in mind that I am self-teaching C++ and started in June of this year. This is my first code solving a semi-complex problem. I am not (yet) a C++ code master. (LOL)
#include "../../std_lib_facilities.h"
class Random {
public:
Random() {srand((unsigned)time(0));}
};
int rooms[4][4] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 100, 0, 0, 0}; // array of room characterics; four for each of 3 rooms (0-2) and 1 current room (3).
string hazards[3] = {"I smell the wumpus.", "I feel a breeze.", "I hear a bat."}; // array of room hazards.
double upplimit() { // set upper limit for probability range.
double limu = 40 + 40 * rand()/RAND_MAX;
return limu;
}
double lowlimit() { // set lower limit for probability range.
double liml = 60 * rand()/RAND_MAX;
return liml;
}
int room_num() { // randomize room numbers of adjacent rooms.
int rm = rand() % 1000;
return rm;
}
int player() { // validate …
Nathaniel10 34 Junior Poster
This is part of my Wumpus Hunt program. Suggestions were to clean up the main() part of the program by creating functions. I am working on that and ran into this difficulty (for me). The functions that relate to the rooms of the game need to return an array. I searched this topic and found that it is NOT AT ALL a clear and simple affair to have a function return an array in C++.
The clearest explanation I have seen so far is to create an array in heap memory and then have the function return a pointer to the first element of that array. A person said that a stack memory array can't be used because it will be destroyed when it goes out of scope at the end of the function.
This pointer business makes sense because this exercise is in the chapter on pointers, heap memory, arrays/vectors, and constructors/destructors.
Here is what was given as the correct way to return an array. Is that so?
int foo(int n){
int* ptr = new int[n];
for (int i = 0; i < n; i++) {
ptr[i] = 2*i;
}
return ptr;
}
If that is correct, my next question is will it also work for a 2 dimensional array? I am using 2D arrays in my code. Is the first element of a 2D array [0][0]? Will a pointer point to ptr[0][0] in the following example?
int foo(int n, int m){
int* ptr …
Nathaniel10 34 Junior Poster
I found my error. I am not sure what it was exactly but I suspect it was related to a conflict in types. When I made changes I think it resulted in ints mixing with doubles. After I made additional changes, the problem resolved itself.
Yes. Other have suggested using functions as well. I am working on that now.
Nathaniel10 34 Junior Poster
I was already thinking along ARKoenig's suggestion and revised my code to use arrays.
It was working pretty well until I made some minor changes. Now it loops non-stop without any prompt for the player to make a play. I am sure it is a small error, but I can't see it. I don't remember the changes I made just before it started looping continuously. I hope someone else's eyes can see it. Here is my new code. Thanks in advance. I apologize in advance for less than ideal indentation.
#include "../../std_lib_facilities.h"
int main() {
srand((unsigned)time(0));
double rands[3][4]; // array of random numbers; four for each of 3 adjacent rooms.
int rooms[4][4]; // array of room characterics; four for each of 3 adjacent rooms (0-2) and 1 current room (3).
rooms[3][0] = 100; // initialize the current room number at 100.
int flag = 0;
int play = 0;
cout << "You are safe and in room 100!" << endl;
while (flag == 0) {
for (int i = 0; i < 3; i++) { // loop for the probabilities.
rands[i][0] = 600.0 * rand()/RAND_MAX; // for the room number.
rands[i][1] = 100.0 * rand()/RAND_MAX; // for the wumpus.
rands[i][2] = 100.0 * rand()/RAND_MAX; // for the pit.
rands[i][3] = 100.0 * rand()/RAND_MAX; // for the bat.
}
for (int i = 0; i < 3; i++) { // loop for the rooms.
if (rands[i][0] >= 0.0 && rands[i][0] < 100.0) {rooms[i][0] = 120;} // randomizing of room …
Nathaniel10 34 Junior Poster
This thread is continued in one titled Wumpus Hunt 2.
Nathaniel10 34 Junior Poster
Is it possible to have an array as a class member? It is part of my Wumpus Hunt exercise.
I want to do the following:
class Room {
blah blah;
};
int main() {
for (i = 0; i < 3; i++) {
Room adjacent[i];
blah blah;
}
My compiler is not letting me do that. It warns that the variable must be constant.
Thanks in advance.
Nathaniel10 34 Junior Poster
I am marking this thread as solved. The next adjustments are major revisions. For example, I need to randomize the adjacent rooms. When I have gone as far as I can with that, I will ask for comments in a new thread.
Nathaniel10 34 Junior Poster
Stupid me! Nevermind. I just noticed that line 20 should be
while (flag == 0)
.
Nathaniel10 34 Junior Poster
I changed Room from class to struct and I call srand() just once.
The issue I have now relates to the loop I am trying to make. For testing purposes I used a for loop, but the game needs a while loop. When I try to implement a while loop using a flag to indicate when the loop should end, the program goes straight to the end. It does not enter or execute the loop at all. The flag code is commented out in this version.
I would rather that the program go directly to the "Game Over" line immediately when the flag is set to 1, but first things first.
Here is the revised code.
#include "../../std_lib_facilities.h"
struct Room {
double rand_wumpus;
double rand_pit;
double rand_bat;
bool wumpus_in_room;
bool pit_in_room;
bool bat_in_room;
int room_num;
};
int main() {
//int flag = 0;
cout << "You are safe and in room 100!" << endl;
srand((unsigned)time(0));
for (int i = 0; i < 5; i++) {
//while (flag = 0) {
Room adjacent1;
adjacent1.room_num = 120;
adjacent1.rand_wumpus = 100.0 * rand()/RAND_MAX;
adjacent1.rand_pit = 100.0 * rand()/RAND_MAX;
adjacent1.rand_bat = 100.0 * rand()/RAND_MAX;
if (adjacent1.rand_wumpus > 30.1 && adjacent1.rand_wumpus < 47.8) {
adjacent1.wumpus_in_room = true;
} else {
adjacent1.wumpus_in_room = false;
}
if (adjacent1.rand_pit > 83.1 && adjacent1.rand_pit < 95.5) {
adjacent1.pit_in_room = true;
} else {
adjacent1.pit_in_room = false;
}
if (adjacent1.rand_bat > 22.7 && adjacent1.rand_bat < 40.4) {
adjacent1.bat_in_room = true;
} else {
adjacent1.bat_in_room = false; …
Nathaniel10 34 Junior Poster
So is your problem resolved now?
No. The code is far from finished. I am having some loop difficulties. I want to get the code to a state where a major revision is the next appropriate stage. Then I will consider this thread solved and start another one.
Nathaniel10 34 Junior Poster
OK. I found my error. When a player decides to shoot the wumpus instead of move into an adjacent room, lines 159 through 178 are not executed. These are the lines in which the variables in the current room, such as current.wumpus_in_room, are determined. Lines 180 through 188 should also be by-passed but, in error, are not. When the computer tries to execute those lines, it finds that there are no values for those variables. I am going to put a conditional on them.
Nathaniel10 34 Junior Poster
This thread has been continued in "Wumpus Hunt".
Nathaniel10 34 Junior Poster
Stroustrup has an exercise in which the reader writes a program for the wumpus hunt game. A first draft of my code is below. It compiles and runs partly correctly. If you choose to move to a different room the program runs as expected. If you choose to shoot at the wumpus, I get something called run-time error #3. It seems that the room I call 'current' is being perceived as a variable. The error description is that the variable 'current' is not initialized.
I don't understand that error because the 'current' room variables are not used in the lines in question.
Here is my code. It is not a final version.
#include "../../std_lib_facilities.h"
class Room {
public:
double rand_wumpus;
double rand_pit;
double rand_bat;
bool wumpus_in_room;
bool pit_in_room;
bool bat_in_room;
int room_num;
};
int main() {
cout << "You are safe and in room 100!" << endl;
for (int i = 0; i < 5; i++) {
Room adjacent1;
srand((unsigned)time(0));
adjacent1.room_num = 120;
adjacent1.rand_wumpus = 100.0 * rand()/RAND_MAX;
adjacent1.rand_pit = 100.0 * rand()/RAND_MAX;
adjacent1.rand_bat = 100.0 * rand()/RAND_MAX;
if (adjacent1.rand_wumpus > 30.1 && adjacent1.rand_wumpus < 47.8) {
adjacent1.wumpus_in_room = true;
} else {
adjacent1.wumpus_in_room = false;
}
if (adjacent1.rand_pit > 83.1 && adjacent1.rand_pit < 95.5) {
adjacent1.pit_in_room = true;
} else {
adjacent1.pit_in_room = false;
}
if (adjacent1.rand_bat > 22.7 && adjacent1.rand_bat < 40.4) {
adjacent1.bat_in_room = true;
} else {
adjacent1.bat_in_room = false;
}
Room adjacent2;
srand((unsigned)time(0));
adjacent2.room_num = 150;
adjacent2.rand_wumpus = 100.0 * rand()/RAND_MAX;
adjacent2.rand_pit …
Nathaniel10 34 Junior Poster
Stroustrup has an exercise in which the reader makes the "Hunt the Wumpus" game. My first step was to create the starting room. This is that code:
#include "../../std_lib_facilities.h"
class Initialize {
private:
double rand_wumpus;
double rand_pit;
double rand_bat;
public:
Initialize() {
double srand((unsigned)time(0));
rand_wumpus = 100.0 * rand()/RAND_MAX;
rand_pit = 100.0 * rand()/RAND_MAX;
rand_bat = 100.0 * rand()/RAND_MAX;
}
};
class Current_room {
private:
int room_num;
bool wumpus_in_room;
bool pit_in_room;
bool bat_in_room;
public:
Current_room() {
if (rand_wumpus > 10.5 && rand_wumpus < 12.2) {
wumpus_in_room = true;
cout << "The wumpus is in the room. You are eaten!" << endl;
} else {
wumpus_in_room = false;
}
if (rand_pit > 30.1 && rand_pit < 41.8) {
pit_in_room = true;
cout << "You have fallen into a pit and died!" << endl;
} else {
pit_in_room = false;
}
if (rand_bat > 62.4 && rand_bat < 75.0) {
bat_in_room = true;
cout << "A bat has taken you to another room!" << endl;
} else {
bat_in_room = false;
}
if (wumpus_in_room == false && pit_in_room == false && bat_in_room == false) {
cout << "You are safe!" << endl;
}
}
};
int main()
{
Current_room Test;
keep_window_open();
return 0;
}
The Current_room class is not accessing the rand_wumpus, rand_pit, and rand_bat variables form the Initialize class. The suggestions are to make Initialize public, use get() functions for those variables, or make Current_room a sub-class of Initialize. I don't which is best.
Nathaniel10 34 Junior Poster
I have a difficulty I need help to overcome. I am developing a program that uses more than 1 class. Variables defined in one class are used in other classes. For example:
class X1 {
private:
int a;
int b;
public;
X1() {
a = 10;
b = 20;
}
};
class X2 {
private:
int c;
int d;
public;
X2() {
c = 5 + 2*a;
d = 10 - 4*b;
}
};
int main() {
X2 Test;
int e = 40 + 10*d;
cout << e << endl;
keep_window_open();
return 0;
}
I get a compile error that variable a and b in class X2 are not declared and initialized. I tried making X2 a sub-class of X1, hoping that X2 would inherit the variables a and b, but IO got even more compile errors.
My question: Is there a way to link the classes so that the variables of a prior class are known and usable in the subsequent classes? Or will I have to make one HUGE class?
Thanks in advance.
Nathaniel10 34 Junior Poster
For example, line 67 where the vector is created yields lines 28-39 in the output. The vector is constructed in the stack, copied to the heap, then destroyed in the stack. This happens 4 times, so the construction and destruction is occurring for each element of the vector. I had no clue that was happening!
I think I should have written that the vector is constructed in the heap, copied to the stack, and then destroyed in the heap.
Nathaniel10 34 Junior Poster
@Mike,
That was an OUTSTANDING suggestion!! I never would have thought of it on my own because I had no intention of modifying Stroustrup's code.
Executing the lines of main() one at a time yielded very interesting results. I now have a much better understanding of the default constructor, explicit constructor, copy constructor, copy assignment, and destructor. Though I have almost as many new questions as old questions were answered. For example, line 67 where the vector is created yields lines 28-39 in the output. The vector is constructed in the stack, copied to the heap, then destroyed in the stack. This happens 4 times, so the construction and destruction is occurring for each element of the vector. I had no clue that was happening!
I think this was a very advanced exercise. Stroustrup has many exercises that are too advanced for programmers new to C++. I am very grateful for your comments because I would not have gotten as much out of this exercise, nor his book as a whole, without them. Thank you very, very much.
Nathaniel10 34 Junior Poster
I managed to copy and paste the the entire output below.
004241A0->X(int):0(2)
0012FF54->X(int):-858993460(4)
0012FF48->X(X&):-858993460(4)
0012FD54->X(int):-858993460(5)
0012FF54->X::operator = ():4(5)
0012FD54->~X():5(0)
0012FD30->X(X&):702684171(5)
0012FD6C->X(X&):-858993460(5)
0012FD30->~X():5(0)
0012FF48->X::operator = ():4(5)
0012FD6C->~X():5(0)
0012FD30->X(X&):702684171(5)
0012FD10->X(X&):-858993460(5)
0012FD84->X(X&):-858993460(5)
0012FD10->~X():5(0)
0012FD30->~X():5(0)
0012FF48->X::operator = ():5(5)
0012FD84->~X():5(0)
0012FF3C->X(int):-858993460(6)
0012FD14->X(int):-858993460(7)
00345A48->X(X&):-842150451(7)
0012FD14->~X():7(0)
00345A48->~X():7(0)
0012FD14->X(int):-858993460(8)
00345A48->X(X&):-842150451(8)
0012FD14->~X():8(0)
00345A48->~X():8(0)
0012F7D8->X():-858993460(0)
00345AE0->X(X&):-842150451(0)
0012F7D8->~X():0(0)
0012F7D8->X():0(0)
00345AE4->X(X&):-842150451(0)
0012F7D8->~X():0(0)
0012F7D8->X():0(0)
00345AE8->X(X&):-842150451(0)
0012F7D8->~X():0(0)
0012F7D8->X():0(0)
00345AEC->X(X&):-842150451(0)
0012F7D8->~X():0(0)
0012FF04->X():-858993460(0)
0012FF08->X():-858993460(0)
00345B30->X(int):-842150451(9)
00345B30->~X():9(0)
00345B34->X():-842150451(0)
00345B38->X():-842150451(0)
00345B3C->X():-842150451(0)
00345B40->X():-842150451(0)
00345B44->X():-842150451(0)
00345B44->~X():0(0)
00345B40->~X():0(0)
00345B3C->~X():0(0)
00345B38->~X():0(0)
00345B34->~X():0(0)
I have thought more about the program and believe that on line 7: 'this' refers to the memory address, 's' refers to the name and type of the variable, 'val' refers to the value of the variable, I don't know what 'nv' refers to, perhaps array size.
So the when the global variable X glob(2) is created on line 36 it constructs a variable of size 2 at memory address 004241A0, name X and type int, of value 0. The address suggests to me that this variable was put in stack memory. Because it is global, it is never destroyed. That address is never written again.
I think line 37 copies 'glob(2)' to 'a', and 'a' is put into memory address 0012FF54, a heap memory address. It again has name X and is of type int. Line 38 copies 'a' to 'aa' and puts into memory address 0012FF48, again heap memory and the address is declining as heap addresses should (I think).
Am I in the ball park or way, way off?
Nathaniel10 34 Junior Poster
An exercise that Stroustrup wants the reader to do is understand the output of the following program.
#include "../../std_lib_facilities.h"
struct X {
int val;
void out(const string& s, int nv) {
cerr << this << "->" << s << ":" << val << "(" << nv << ")\n";
}
X() {
out("X()", 0);
val = 0;
}
X(int v) {
out("X(int)", v);
val = v;
}
X(const X& x) {
out("X(X&)", x.val);
val = x.val;
}
X& operator = (const X&a) {
out("X::operator = ()", a.val);
val = a.val;
return *this;
}
~X() {
out("~X()", 0);
}
};
X glob(2);
X copy(X a) {return a;}
X copy2(X a) {
X aa = a;
return aa;
}
X& ref_to(X& a) {return a;}
X* make(int i) {
X a(i);
return new X(a);
}
struct XX {
X a;
X b;
};
int main ()
{
X loc(4);
X loc2 = loc;
loc = X(5);
loc2 = copy(loc);
loc2 = copy2(loc);
X loc3(6);
X& r = ref_to(loc);
delete make(7);
delete make(8);
vector<X> v(4);
XX loc4;
X* p = new X(9);
delete p;
X* pp = new X[5];
delete[] pp;
keep_window_open();
return 0;
}
I don't understand this program. It is supposed to have different types of constructors and destructors, variables created and variables destroyed. It prints out whenever a variable is created or destroyed. I don't understand the output. It is a series of memory addresses with an X or an ~X after it. I understand the allocation of memory and the …
Nathaniel10 34 Junior Poster
OK. I answered my own question. I was printing the addresses of elements in an array, which always increase. I should have printed the addresses of different arrays. Subsequent arrays would have either higher or lower addresses. I ran a different program.
#include "../../std_lib_facilities.h"
int main ()
{
char c = ' ';
char ch0[10];
char ch1[10];
char *cha = new char[10];
char *chb = new char[10];
char *init_cha = cha;
char *init_chb = chb;
cout << "Enter characters separated by a space.\nUse the '!' to indicate the end of your entries." << endl;
int i = 0;
while (cin >> c) {
if (c == '!') {
break;
} else {
*cha = c;
*chb = c;
ch0[i] = c;
ch1[i] = c;
cha++;
chb++;
i++;
}
}
cha = init_cha;
chb = init_chb;
for (int i = 0; i < 10; i++) {
cout << *cha << " " << reinterpret_cast<void*>(cha) << endl;
cout << *chb << " " << reinterpret_cast<void*>(chb) << endl;
cout << ch0[i] << " " << reinterpret_cast<void*>(&ch0[i]) << endl;
cout << ch1[i] << " " << reinterpret_cast<void*>(&ch1[i]) << endl;
cout << endl;
cha++;
chb++;
}
cha = init_cha;
chb = init_chb;
delete[] cha;
delete[] chb;
keep_window_open();
return 0;
}
My results are as expected. The address of the first element of cha, the first heap array, is 00345A48. The address of the first element of chb, the second heap array, is 00345A90. The address increased. The address of the first element of ch0, …
Nathaniel10 34 Junior Poster
I found several different illustrations of memory layout on the Web. Some of them explicitly show the stack above the heap. But the stack addresses decline, while the heap addresses increase.
Why does my output show stack addresses increasing?
Nathaniel10 34 Junior Poster
An exercise is to write a program that shows how memory is allocated to stack variables compared to heap variables. I ran the following code.
#include "../../std_lib_facilities.h"
int main ()
{
char c = ' ';
char ch0[10];
char *ch = new char[10];
char *init_ch = ch;
cout << "Enter characters separated by a space.\nUse the '!' to indicate the end of your entries." << endl;
int i = 0;
while (cin >> c) {
if (c == '!') {
break;
} else {
*ch = c;
ch0[i] = c;
ch++;
i++;
}
}
ch = init_ch;
for (int i = 0; i < 10; i++) {
cout << *ch << " " << reinterpret_cast<void*>(ch) << endl;
cout << ch0[i] << " " << reinterpret_cast<void*>(&ch0[i]) << endl;
cout << endl;
ch++;
}
ch = init_ch;
delete[] ch;
keep_window_open();
return 0;
}
The output I get is an address of 00345A48 for the first element of the ch (heap) array, and an address of 0012FF48 for the first element of the ch0 (stack) array. The addresses of the other elements increase by 1 unit in both arrays.
The illustration in my book of the memory layout shows stack memory 'below' heap memory. I am guessing that means stack memory addresses will have smaller numbers than heap memory addresses, as my output shows.
Is that supposed to happen?
Thanks in advance for explanations.
Nathaniel10 34 Junior Poster
Your last post is better code than mine, Oliver. In any case, both were better than what the OP has. With yours, 8 lines of code does what the OP used 40 lines to do.
Nathaniel10 34 Junior Poster
@NathanOliver,
I don't see that. There are 4 categories of fees on check so there are 4 cases. I was thinking along the lines of:
double check_fees = 0.0;
char level_checks = ' ';
if (checks < 20) {level_checks = 'a';}
if (checks => 20 && checks < 40) {level_checks = 'b';}
if (checks => 40 && checks < 60) {level_checks = 'c';}
switch (level_checks) {
case 'a':
check_fees = 0.10 * checks;
break;
case 'b':
check_fees = 1.90 + 0.08 * (checks - 19);
break;
case 'c':
check_fees = 1.90 + 1.52 + 0.06 * (checks - 39);
break;
default:
check_fees = 1.90 + 1.52 + 1.14 + 0.04 * (checks - 59);
break;
}
int low_balance = 0;
if (balance < 400) {low_balance = 1;}
fee = 10.0 + check_fees + 15.0 * low_balance;
cout <<"Bank service charges for the month are $" << fee << " .\n";
Where do you see at least 60 cases?
Nathaniel10 34 Junior Poster
I would add that a switch statement is preferable to a long series of if statements.
Nathaniel10 34 Junior Poster
This is a common assignment. I'll bet if you had searched for examples of prime number generator programs, you would have found many to which you could compare your code and see where you went wrong.
Recall the definition of a prime number, one that is evenly divisible only by 1 and itself. The line where you start your inner loop, 'for (j = 2; j <= i; j++)' guarantees that a number will be divisible by itself and be output as a prime number. You can eliminate that by having instead 'for (j = 2; j < i; j++)' where the 'less than or equal to' is just 'less than'.
You can put one number per line if you cout statement is 'cout << i << endl;'
Nathaniel10 34 Junior Poster
Instead of all the else if statements, I would have used a switch statement.
Nathaniel10 34 Junior Poster
Mike,
The chapter this exercise is in does have a section on void* and casts. I didn't read it closely and thoroughly the first time. After you posted, I re-read that section more closely. Stroustrup explained why we might need to ask the compiler to deal with pointers that point to objects of different types or unknown types. He also explains that we can convert a pointer from one type to another type using 'cast'. There is a very brief explanation of static_cast, reinterpret_cast, and const_cast.
I modified my program to include your suggestion and it ran correctly. I also used static_cast and that version ran correctly as well.
Stroustrup had an extended explanation of why using casts is a very bad idea (because they are 'buggy'). He stressed that it is always preferable to redesign a program so that the use of cast can be avoided. He concedes to using them only when it is unavoidable such as if dealing with other pre-existing code.
Your explanation was very clear and I feel fortunate that I have come to have a fairly good understanding of this topic. However, I am also glad that it is not something that is highly recommended.
Nathaniel10 34 Junior Poster
@ Mike,
How would I increment the pointer correctly? I want to print out the memory address of the next element in the array. I unsuccessfully tried ch. I am out of ideas at this point.
Thanks for your explanation.