Hello, everyone. Welcome back to the section 19 challenge 1 solution.
I'm in the section 19 workspace.
And I'm in the challenge_1_solution project.
I hope you found this challenge challenging.
There was probably a couple of pieces that were kind of tricky,
one of them had to do with displaying the country right next to that
city, the first time around, and I'll talk about that in a second.
The other one might have been trying to center that title, so we'll go over both of those.
Here is the structures again. Here's my city,
my country and my tours. I've got this simple function called ruler,
which I'm just going to use one time at the very beginning just so we can look at our alignment.
And then I've got my
structure, which has been initialized here, exactly like I gave it to you.
So the first thing I want to do is I want to look at my data.
And I want to kind of look at the sizes of the data,
make sure that there's nothing like a city that's got 30 or 40 characters in it.
That way I can gauge what kind of field widths I want.
So that's what I did.
And what I've done here is I've decided to go with
a total width of 70. And the reason I did that was just purely console based because some
terminal windows and some DOS windows and some shell windows,
which is where we're running these programs are 80 max. So I didn't really want them
going over the 80 and then wrapping over and really making it ugly.
So what I decided to do is keep the total width of the entire report
to 70 characters. Okay. So 70 is our goal here.
And then we've got 4 fields, right. We've got the name of the country,
the name of the city, the population and the cost. And obviously, we have a title up here centered somewhere.
And I'll talk about the title in just a second. So
the way I decided to do this was to create 4 field widths.
And I'm going to make constants from all of these guys. That way I don't have to use my numbers everywhere.
And I just use these names.
And if I ever need to tweak anything, I could just come here and tweak them, and it should be good to go.
So 70 is the total width.
My first field is a width of 20. So let's say that this is my first one here.
Let's say that this is another 20 here.
And then my last 2 are 15, which were a little bit smaller.
This isn't to scale, but you get the idea. So this would be
the country's name, right. So this would say, let's say,
Columbia would display here, and then the city would be over here.
The population and both of these guys I'll just draw arrows here will be left
justified in that field width. Then I've got the population,
which is a number, which will be right justified here.
And I've got the cost which would be some number with 2 decimal points on the end,
and that's going to be right justified here as well.
Okay.
I've got a header over here, which is going to say country,
city,
population will be right justified over here, so it lines up
and over here costs will be right justified. So that's sort of
the the structure that I've got in my mind. And I can tweak this as I go.
Okay. So that's really
pretty much it. Here are my field widths that I've defined. So again,
20 20 15 15. We add them up to 70.
So I know that I'm in the ballpark. Let's deal with that title.
So I'm going to erase this real quick. And I'll scroll down just a bit.
And what we want to do is we want to display the title. Now you'll notice on line 71 down here,
I'm displaying the ruler.
That's just going to display that series of numbers so that we can line things up.
But let's talk about the title and what kind of algorithm we want.
Again, we've got 70 for our
field -- -- our total width of our report.
And suppose, I wanted to display something -- well, obviously, the center here is 35, right.
That's pretty clear.
And suppose I wanted to display something that was
10 characters wide, a string that's 10 characters wide.
The idea would be that I'd want to display
5 of those characters on this side and 5 on this side, right.
That would center that string. If the string was 20 characters wide,
I'd want to display 10 over here and I'd want to display 10 over here.
That way we know that that string is always centered.
So we've got to do the math that let's just do that.
And it's pretty straightforward. If you think about this,
notice here, if the if the string is 20 large, right,
we want 10 on this side, 10 on that side. And if 35
was the center, that means we really want to start printing that guy at 25,
at column 25.
And if the string was 10 characters big, we want to print it at
35 minus the 5, which is 30 right here.
Okay. So that's really what my algorithm is going to be.
Let me clear this because it's a little messy,
and I'll I'll do it one more time with an actual example. So here's the 70.
We know we're at 35.
And I want to display a string that's 40 characters wide.
Okay. So what do I do. How do I figure this out. Well, I want to display 20 of them
and 20 of them.
And I want to line those up, right. So 35 minus 20 gives me 15.
And that's where I want to start displaying that string.
So how do we do this. You take the total length, which is 70.
You subtract from it the length of the string that you want, which is 40.
That gives you a 30, and then you divide that by 2. That gives you the 15,
that gives you exactly where you need to start displaying the string, so it's centered.
Okay. Let's do another example. Suppose the string is 20 big.
I need 70 minus 20
divided by 2, gives me 25.
Does that make sense.
Well, let's see if it's 20, I want to do 10 on this side and 10 on this side.
35 minus the 10 is 25,
exactly right. So my algorithm makes sense,
and it's really easy to implement. Let me show you how to do it.
I'm going to scroll down just a little bit, and we'll do the header right here.
So what I'm doing here on line 72 is
I'm determining what is the length of that title string.
string. It's in tours.title.string. It's in tours.title.
I just want the length of it.
Whatever that length is, I'm going to subtract it from the total width divide it by 2.
That's where i want to start displaying tours.title.
But how do I do that. Well, it's really easy. I can set a width to that
amount and just display an empty string. Remember,
that the set width applies to the next item that's being put on the stream,
there it is. I'm not putting anything. It's just an empty string, but it's still going on the stream.
Okay So that should take care of centering that.
And then the rest is pretty easy in this context because what we're doing here is
I'm setting my field width for the country
to field 1 which is 20,
right. I'm justifying left, and I'm displaying country.
So field width one, which is 20 is going to be left justified.
And right there is what I'm putting on the stream. So country that string is going to be left justified.
Then field 2 is 20 again.
Then I've got 15 15. I'm doing the 2 left and the 2 right,just like I did before,
and then I've got a new line. So that should display the title centered
and my headers, those 4 names, right, where I want them.
The next thing I need to do is I need to do a line of dashes, right, to separate my
header from the content, and I want 70 of those dashes.
I could just say cout a big string of 70 dashes, right.
But if I ever change my total width, then I've got to change that as well.
So what I can do here is I can simply say set the field width
to the total width, that'll be 70.
Set the fill character to the dash,
and that's what I want to display,
which is just an empty string, but it doesn't really matter because it's going to
fill up everything with the dashes and then give me a new line at the end.
That's it. Let's run this, and we'll see where we're at.
And there we go. You can see tour ticket prices from Miami that's centered.
I've got my country left justified in 20,
my city left justified in 20, my population and my price
both right justified here in 15.
And if you count them, you can actually see that that's all lining up just right.
And there's my dash mind of 70.
Okay. In this case 70. If I change total width to 80, it'll do 80.
If I change it to 40, it'll do 40. That's the nice part about using those consts.
Okay. So that's it. Now we need to get into the body of the report.
Before we do that, let's do a couple of things here.
This is important right here. Let me go back to where I was.
Here we go. I want to uncomment these 2 lines out.
Let's talk about these for a second.
I want to set my fill back to blank, right.
Remember, I changed the fill right here, and that's persistent.
So I don't want to keep it that way. Otherwise, I'm going to get dashes all over the place.
So I want to set it back to a blank character,
and I want to set the precision
to 2 and fix and that's basically for this guy right here for the price.
I want to be able to make sure that I've got 2 digits to the right side of the decimal.
I only need to do that one time, and then we're good to go.
And now comes the logic for actually displaying
the data.
And this is it. This is all there really is to it.
There's a couple of tricky parts here.
And I'll talk about that in a minute, but let's just talk about the outer loop first.
Here's the outer loop. My collection is tours.countries, right.
So each time I go through there, I'm going to grab a country structure.
And each one of those country structures has city structures within it,
right. So that's the idea vector of cities. So in this case,
for each country in tours country,
I want to execute this inner loop.
And now this inner loop, we could have done this a
lot more complicated a couple of different
ways to do this. I chose to do it a simple way with jus one
standard out statement right here, one cout statement
that kind of does everything. But the only thing that's different here is -- and let me
make a little room down here so I can show you what I'm talking about.
In the report,
we could have done something like this. We could have said
Colombia
and then the cities down here, Bogota
the population, the amount and cali
and the population of the amount. I didn't want to do it that way.
I wanted to do it where this guy is down here right
there right, next to the first city.So it looks more like a report.
Here it kind of just leaves all this empty space here, which I didn't like.
But in order to achieve this, you've got to do a little bit of a extra logic to do it.
So let me show you what I did.
For each one of those cities, remember, outer loop is the country,
inner loop is we're looping through the cities vector in the country.
So each time we loop in here, we're going to get a city.
So what we're going to do is the only time that we want to display --
let me write that again, the only time that we want to display the city
and the country
is that first time, right. That very first city is going to be different.
The second city I just want to display it like this.
I don't want to display Colombia again or I don't want to display Argentina again,
makes sense.
Okay. So what we're doing here is we're looping through the cities vector.
And I've got my width set, exactly like we did before;
left, left; right, right, none of that changes.
The only difference here is this one line of code right here.
This is using the conditional operator.
Now if you remember the conditional operator, it's an if else statement
built right into an expression, which is kind of cool.
So here I'm -- I've decided to use a for loop,
not a range-based for loop, but a regular for loop because I need to know
when I'm at the first one.
The first one will be when I 0.
So notice what's happening here, when I is equal to 0,
I am displaying the country's name.
That's what I want.
When I is not equal to 0, that means that I've already displayed the country name,
I'm just displaying cities now, then I just don't want to display anything on that line,
makes sense. So the first time through, I'm displaying the country
and then the city, the population and the cost. The city, population, cost.
The next time around, I will not be equal to 0,
right. So I'm just displaying a blank. So I'm not displaying anything here,
but I am displaying these 3.
Okay. So it's just a nice little way to do this.
That way you don't have to write multiple cout statements
depending on all kinds of conditions.
Okay. So that's that first one. The rest are really simple,
right. Grab the city at I or the name of the city at I,
the population and the cost we're just looping through that vector grabbing the fields that
we want. And simple as that.
Now there's -- there are different ways to do this, and we'll learn how to do this
when we talk about the standard template library using iterators,
which is much nicer than using these loops. But when we get there we get there.
That's it. Let me run this, and we'll verify that it works.
And there you go. And you can see right here, this is exactly what we wanted.You can see Colombia's here.
Then I'm printing out that city right next to it.
And then on the second city, I'm not displaying Colombia again.
Okay. If you did it this way, great. If you didn't do it this way, you just wrote
a blank line here and then you started with the cities underneath, that's fine too.
I just think that this report looks nicer this way.
All right. So that's it. You've got a whole bunch of stuff to look at here.
Hopefully, your solution was close.
If your solution was better or quicker or more efficient or
you used a different kind of looping construct,
post it in the forums.
You'd have to post the whole program, just post this piece here, this loop right here
because that's really the interesting part. The rest of the data is all same for everybody.
Okay. So in the next video, we'll start talking about files.