printing multiline strings horizontally

Is there a way to print the following sample code beside each other instead of on a new line?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <string>

using namespace std;

const string fiv = "+---+\n"
                   "|    \n"
                   "|    \n"
                   "+---+\n"
                   "    |\n"
                   "    |\n"
                   "+---+\n";
                 
const string zer = "+---+\n"
                   "|   |\n"
                   "|   |\n"
                   "+   +\n"
                   "|   |\n"
                   "|   |\n"
                   "+---+\n";

const string one = "    +\n"
                   "    |\n"
                   "    |\n"
                   "    +\n"
                   "    |\n"
                   "    |\n"
                   "    +\n";

int main(){
    string z = zer;
    string f = fiv;
    string o = one;
    string aa [3];
    aa[0] = z;
    aa[1] = f;
    aa[2] = o;
    
    for (int i = 0; i < 3; i++){
        cout << aa[i] ;
    }
}
Not automatically, you have to code the logic for it. Think of output as a 1-dimensional stream of characters. It's up to you to tell it when it needs to print a new line.

Here's a hint, maybe it will help: One option is to use string.substring.
https://www.geeksforgeeks.org/substring-in-cpp/

Each line, you need to loop through each block-art string in your array of strings. But only print a particular substring (row) of each block, each time.
For example,
• First row, print aa[0][0] to to aa[0][4], then aa[1][0] to aa[1][4], then aa[2][0] to aa[2][4].
• print newline.
• Second row, print aa[0][6] to to aa[0][10], then aa[1][6] to aa[1][10], then aa[2][6] to aa[2][10].
• print newline.

Increment by 6 each time, because that's the width of the block, plus the newline you have.
You might have to play around with the numbers/increments a bit, I was just doing that in my head.

my_string.substr(6, 4) will create a string of 4 characters, starting at index 6.

Edit:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
/// block_width - width, in characters, of each row of the block.
/// block height - height, in characters, of each column of the block.
/// block_stride - distance between two rows of data (e.g. set to 1 if there's a newline between each row).
void print_horizontally(string blocks[], int num_blocks, int block_width, int block_height, int block_stride)
{
    for (int j = 0; j < block_height; j++) // one row at a time
    {
        for (int i = 0; i < num_blocks; i++) // printing a row from each block string
        {
            std::cout << blocks[i].substr(j * (block_width + block_stride), block_width) << ' ';
        }
        std::cout << "\n";
    }
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int main(){  

    const string fiv = "+---+\n"
                       "|    \n"
                       "|    \n"
                       "+---+\n"
                       "    |\n"
                       "    |\n"
                       "+---+\n";
                     
    const string zer = "+---+\n"
                       "|   |\n"
                       "|   |\n"
                       "+   +\n"
                       "|   |\n"
                       "|   |\n"
                       "+---+\n";

    const string one = "    +\n"
                       "    |\n"
                       "    |\n"
                       "    +\n"
                       "    |\n"
                       "    |\n"
                       "    +\n";

    const int num_blocks = 3;
    string blocks[num_blocks] = { fiv, zer, one };
    int width = 5;
    int height = 7;
    int stride = 1;
    print_horizontally(blocks, num_blocks, width, height, stride);
}
Last edited on
while you can do it in code, your best bet would be to rewrite the code to make this operation easier to do by breaking your strings up differently.

that is, you would have the first row of each digit as a string without a new line, the second row of each digit as a row without a newline, etc. then when you print them, you would iterate..

does that make sense? you have made a lot more work for yourself by putting the end of lines in each one. There are clunky ways to do it too, you could iterate each string until you found end of line and write that much in order each time, but its ugly.
Last edited on
I agree that a better data structure would help. Here's an example. It produces the same output as yours. You can probably figure out how to make it print horizontally.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <iostream>
#include <string>
#include <array>
#include <vector>

using Digit = std::array<std::string, 7>;

const std::array<Digit, 10> digits {{
    {{"+---+",
      "|   |",
      "|   |",
      "+   +",
      "|   |",
      "|   |",
      "+---+" }},
    {{"    +",
      "    |",
      "    |",
      "    +",
      "    |",
      "    |",
      "    +" }},
    {{ }},
    {{ }},
    {{ }},
    {{"+---+",
      "|    ",
      "|    ",
      "+---+",
      "    |",
      "    |",
      "+---+"  }},
}};

int main() {
    std::vector<Digit> d {digits[0], digits[5], digits[1]};
    for (size_t i = 0; i < d.size(); i++)
        for (size_t j = 0; j < d[i].size(); j++)
            std::cout << d[i][j] << '\n';
}


Or with plain old C-style arrays:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>

const char* digits[10][7] {
    { "+---+",
      "|   |",
      "|   |",
      "+   +",
      "|   |",
      "|   |",
      "+---+" },
    { "    +",
      "    |",
      "    |",
      "    +",
      "    |",
      "    |",
      "    +" },
    { },
    { },
    { },
    { "+---+",
      "|    ",
      "|    ",
      "+---+",
      "    |",
      "    |",
      "+---+" },
};

int main() {
    const char** d[3] {digits[0], digits[5], digits[1]};
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 7; j++)
            std::cout << d[i][j] << '\n';
}

Last edited on
Heh heh heh...

This is the kind of time-wasting-nonsense that got me started programming... Making the pattern of little lights change however I want. https://xkcd.com/722/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// cl /EHsc /Ox /std:c++17 /utf-8 a.cpp
// clang++ -O3 -std=c++17 a.cpp
// g++ -O3 -std=c++17 a.cpp

#include <cctype>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>

std::vector <std::string> to_digits( const std::string& s )
{
  static const char* glyphs[3][12] = {
    { "▄▀▀▄", "▄█ ", "▄▀▀▄", "▄▀▀▄", "▄  █ ", "█▀▀▀", "▄▀▀ ", "▀▀▀█", "▄▀▀▄", "▄▀▀▄", " ", " " },
    { "█  █", " █ ", " ▄▄▀", "  ▀▄", "█▄▄█▄", "▀▀▀▄", "█▀▀▄", " ▄▀ ", "▄▀▀▄", "▀▄▄█", " ", " " },
    { "▀▄▄▀", "▄█▄", "█▄▄▄", "▀▄▄▀", "   █ ", "▀▄▄▀", "▀▄▄▀", " █  ", "▀▄▄▀", " ▄▄▀", "▄", " " },
  };
  static const std::string indices{ "0123456789. " };

  std::vector <std::string> rs( std::size( glyphs ) );

  // Transform s to every indexable glyph
  for (char c : s)
  {
    auto n = indices.find( c );
    if (n != indices.npos)
      for (int k = 0; k < std::size( glyphs ); k++)
        rs[k].append( glyphs[k][n] ).append( " " );
  }

  // Trim trailing spaces
  if (!rs[0].empty())
    for (auto& r : rs)
      r.resize( r.size() - 1 );

  return rs;
}

int main()
{
  for (auto s : to_digits( "3.141 592 653" ))
    std::cout << s << "\n";
}

Save as UTF-8.
On Windows, make sure to type chcp 65001 at your console before running the program (because your default Code Page can’t handle the awesomeness).

Exercises for the reader:
  • How would I add the comma (,) to my list of printable glyphs,
    so that I could print “12,345”?
  • How would I print this interleaved with other text, say:
      ▄█  I
       █  am
      ▄█▄ Groot!
    
?
  • What about text on the left side?

Final advice:
    When in doubt, use graph paper and a pencil.

:O)


[edit] Fixed stuff dutch mentions below
Last edited on
Nice glyphs!
You don't seem to need ciso646.
You've left a "magic" 3 where you could use std::size again.
And some people might want to replace std::size with sizeof glphys / sizeof *glphys to allow compilation as C++11.
Thanks!

I can’t tell you how many times I have written an ASCII glyph character set (or other images)... I’ve even written software to use the second character set on an EGA/VGA card for graphics in text modes...

RE: goofs

Whoops! I had typed this off the top of my head and made a few quick changes; hence the <ciso646>. I also originally had the loop as:
 
#include <duthomhas/for> 
1
2
  for (auto [r, g] : rs, glyphs)
    r.append( g[n] ).append( " " )

...but then y’all’d be asking how to make that work... I just figured I’d keep it simple, and forgot to be careful... Thanks for catching that.

As for C++11, that’s ancient stuff you can safely ignore when writing new software :D
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <string>
#include <sstream>
using namespace std;

const string zero  = "+---+\n"
                     "|   |\n"
                     "|   |\n"
                     "+   +\n"
                     "|   |\n"
                     "|   |\n"
                     "+---+\n";

const string one   = "    +\n"
                     "    |\n"
                     "    |\n"
                     "    +\n"
                     "    |\n"
                     "    |\n"
                     "    +\n";

const string two   = "+---+\n"
                     "    |\n"
                     "    |\n"
                     "+---+\n"
                     "|    \n"
                     "|    \n"
                     "+---+\n";

const string three = "+---+\n"
                     "    |\n"
                     "    |\n"
                     "+---+\n"
                     "    |\n"
                     "    |\n"
                     "+---+\n";

const string four  = "+   +\n"
                     "|   |\n"
                     "|   |\n"
                     "+---+\n"
                     "    |\n"
                     "    |\n"
                     "    +\n";

const string five  = "+---+\n"
                     "|    \n"
                     "|    \n"
                     "+---+\n"
                     "    |\n"
                     "    |\n"
                     "+---+\n";

const string six   = "+---+\n"
                     "|    \n"
                     "|    \n"
                     "+---+\n"
                     "|   |\n"
                     "|   |\n"
                     "+---+\n";

const string seven = "+---+\n"
                     "    |\n"
                     "    |\n"
                     "    +\n"
                     "    |\n"
                     "    |\n"
                     "    +\n";

const string eight = "+---+\n"
                     "|   |\n"
                     "|   |\n"
                     "+---+\n"
                     "|   |\n"
                     "|   |\n"
                     "+---+\n";

const string nine  = "+---+\n"
                     "|   |\n"
                     "|   |\n"
                     "+---+\n"
                     "    |\n"
                     "    |\n"
                     "    +\n";


string operator *( const string a, const string b )
{
   const string SPACE = "  ";
   stringstream ssa( a ), ssb( b );
   string result, parta, partb;
   while( getline( ssa, parta ) && getline( ssb, partb ) ) result += parta + SPACE + partb + '\n';
   return result;
}


int main()
{
   cout << zero * one * two * three * four * five * six * seven * eight * nine;
}


+---+      +  +---+  +---+  +   +  +---+  +---+  +---+  +---+  +---+
|   |      |      |      |  |   |  |      |          |  |   |  |   |
|   |      |      |      |  |   |  |      |          |  |   |  |   |
+   +      +  +---+  +---+  +---+  +---+  +---+      +  +---+  +---+
|   |      |  |          |      |      |  |   |      |  |   |      |
|   |      |  |          |      |      |  |   |      |  |   |      |
+---+      +  +---+  +---+      +  +---+  +---+      +  +---+      +
Last edited on
Thanks everyone. This was my question, but I couldn't remember my login from the computer I was using, so I just created another account.

I swear, every time I ask a question on here, I not only get the answer, but also about a dozen different ways of how I do things incorrectly and better ways to learn. I'll leave this open because it will take me a while to go through all that's on here.

>> Duthomhas

I am putting your exercise off a bit until I make sure I understand this.

/>>

So, adjust my code so that it prints the first line of every digit in question, then the next, so forth?
Because there's no way of just.... how to word this...
moving the cursor back to the top.

Or did I misunderstand everyone?

Appreciate all this cool info by the way.
So, adjust my code so that it prints the first line of every digit in question, then the next, so forth?
Because there's no way of just.... how to word this...
moving the cursor back to the top.

yes, but these are not standard in the console, as the console is operating system specific. windows has gotoxy, unix loves ncurses tools, etc. Its doable, of course. Its easier inside a gui window that has text, as well, but that is silly (you can just make a 50 point font or whatever there instead). These answers are for standard c++ and usually ignore the existence of 3rd party libraries unless you want to know about that approach (if so, ask).

If you move the cursor around, you should drop your end of line chars, those will still cause problems from what I remember, and print a line of the big letter, then move the cursor and write another line, etc.

the last time I did this was probably in dos, so I am a little rusty. winx may support ncurses now for all I know!
Last edited on
Why don’t you just instead make an array of strings for each number and just either out put a \n or a space with the next character’s line

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

const string zer[8] = { 
"+---+",
"|   |",
"|   |",
"+   +",
"|   |",
"|   |",
"+---+"
}

const string one[8] = {
"    +",
"    |",
"    |",
"    +",
"    |",
"    |",
"    +",
}
void outputNum(int num){
   if(num == 0){
      for(int i = 0;i < 7;i++){
         std::cout << zer[i] << std::endl;
      }
   }
}

void outputNums(std::string nums){
   int numLength = 0;
   while(nums[numLength] != '\0'){
      numLength++;
   }
   for(int i = 0;i < 8;i++){
      for(int y = 0;y < numLength;y++){
         if(nums[y] == '0'){
            cout << zer[i];
         }
         if(nums[y] == '1'){
            cout << one[i]; 
         }
      }
   }
}
int main(){

}

EDIT: right. That’s what you asked for. Sry. 😂 here’s a way anyways.
Last edited on
The real answer to “how do I print multi-line objects” is:

Create a multi-line buffer, draw your objects in that buffer, then print the buffer, line by line.

This is essentially what everyone here has done.
One other bit of advice: consider storing the glyphs in a config file that your program reads. That way, you can tweak the glyphs, add new ones etc. without having to recompile each time.
Ooo I like that. 😃
Last edited on
Depending on your needs, you are essentially looking at a sprite map. You can store this as textual strings... or more.
Registered users can post here. Sign in or register to post.