Reputation: 13
https://developers.google.com/edu/c++/getting-started#exercises-and-projects
I'm referring to exercise #4 - Banner
I'm having a little trouble understand how this would work. I have created the different functions for each letter, "F" "R" & "E".
"F", for example:
void printF(){
cout<<"FFFFF"<<endl;
cout<<"F"<<endl;
cout<<"FFF"<<endl;
cout<<"F"<<endl;
cout<<"F"<<endl;
}
As far as I can tell, this won't work because there is no way to print something like this, and then print another right next to it. Can somebody explain conceptually or provide an example of how I could print the word "FREE"? Thank you
Upvotes: 1
Views: 151
Reputation: 435
This is what I did in this example.
First I thought to create a function like printA(), printB() just described in the question details. But I realized the same problem. Also, it would mean that we need to create more than 26 such functions for each of the letters in alphabet and symbols. So, didn't use this approach.
I considered that the letter would be of 5x5 size. We need something what dot matrix printer does. It prints 1st line of dots of each letter in the string and then second line of dots of next and so on. Instead of dots, the letter we are printing needs the same symbol. For example if we are printing H, the dots will be 'H'.
So, how to do this in minimum lines of code and less complexity? I decided to create bitflags for rows. Considering that there are 5 dots in a row, there will be 32 combinations possible. Like - 10000, 11000, 11100 etc. While implementing that, I came to know that we don't need that many to define letters in alphabet. Something like this -
const unsigned char EOne = 0x1F; // 000 11111
const unsigned char BOne = 0x1E; // 000 11110
I gave intuitive names to the bitFlags to know where they belong in the letter. Here is nice information about bitflags - http://www.learncpp.com/cpp-tutorial/3-8a-bit-flags-and-bit-masks/
Next step is to create the design for each letter in alphabet. Like -
const unsigned char A[5] = {AOne, ATwo, EOne, AFiv, AFiv};
const unsigned char B[5] = {BOne, AFiv, BOne, AFiv, BOne};
const unsigned char J[5] = {~EThr, ~BOne, ~BOne, AFiv, ~AFiv};
So, this formed the design of letters A, B, C.. Z.
In the next step, a map can be created between letters in alphabet and their design.
When the user enters string to print, in a for loop of 5 iterations, you can take - 0th letter: 0th bitflag in its design, 1st letter: 1st bitflag in its design.. nth letter: 1st bitflag in its design. Then again, 0th letter: 1st bitflag, 1st letter: 1st bitflag, nth letter: 1st bitflag.. until you print all the 5 rows.
What to do with the bitflag? I used std::bitset and tested each bit so that to print or leave blank space. lineBits is the bitflag for particular letter's design row.
std::bitset<8> bits(lineBits);
// Since we have only 5x5 letter, we start with leftmost bit (4th) to rightmost (0th)
for(int bitpos = 4; bitpos >= 0; bitpos--)
{
if(bits.test(bitpos))
{
cout << letter;
outFile << letter; // In file.
}
else
{
cout << " ";
outFile << " "; // In file.
}
}
This way, with reduced lines of code, I could print any string. Since, I used map, it was easy to print the symbol of the letter which was getting printed.
FFFFF RRRR EEEEE EEEEE ZZZZZ Y Y
F R R E E Z Y Y
FFF RRRR EEE EEE Z Y
F R R E E Z Y
F R RR EEEEE EEEEE ZZZZZ Y
Takes a while to design all the letters though. Let me know how this code can be improved.
Upvotes: 1
Reputation:
You can create your letters as an std::string
array. For consistency, it's five strings five characters long. You can use a function like get_font_letter
to select the current letter. There are better ways to do this, but if you only care about this word, it should be fine for the moment. I suggest doing something like a "font database" where you draw and index the letters in a textfile.
#include <iostream>
#include <vector>
std::string f[] = {
"FFFFF",
"F ",
"FFF ",
"F ",
"F ",
};
std::string r[] = {
"RRRRR",
"R R",
"RRRR ",
"RRR ",
"R RR",
};
std::string e[] = {
"EEEEE",
"E ",
"EEE ",
"E ",
"EEEEE",
};
std::string* get_font_letter(const char& c)
{
if (c == 'F') return f;
if (c == 'R') return r;
if (c == 'E') return e;
}
You don't need a two-dimensional std::vector
. You can just piece each row together with a single space.
int main()
{
std::string word = "FREE";
std::vector<std::string> v;
v.resize(5);
for (unsigned int i = 0; i < 5; i++)
{
std::string row = "";
for (auto it = word.begin(); it != word.end(); ++it)
{
auto letter = get_font_letter(*it);
row += letter[i] + " ";
}
v.push_back(row);
}
for (auto it = v.begin(); it != v.end(); ++it)
std::cout << *it << "\n";
}
Output:
FFFFF RRRRR EEEEE EEEEE
F R R E E
FFF RRRR EEE EEE
F RRR E E
F R RR EEEEE EEEEE
Upvotes: 2
Reputation: 7603
Without giving you the complete solution since you're obviously there to learn, that would be my strategy:
Use vector of strings(or 2-D array) to represent a letter. Then build a list of those vector to represent the string and print all vector string by string(Print 1st string of all vectors, then second, etc). The individual strings should be of constant length and provide some spacing.
Upvotes: 1