Horizontal, vertical lines & their alignment

Hello, I succeeded in getting to show all 255 ASCII symbols in a table, but have a couple questions. First, how I could make a vertical line appear before 0,8,16,24,32,40,48,56,64,72,80,88,96,104,112 and 120 numbers as shown for others. Second, how I could align 128, 129 in a line with 130,131,132 and so on until 135 in one row? Third, I want the table to be straight without any blanks as seen between vertical ends and horizontal lines in the middle. How to do that? Thirdly how I could get double line as seen below ASCII codes? I would like it to be two lines without any blanks as it is now(===).

Here's the code:

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
#include <iostream>
#include <fstream>
#include <windows.h>
#include <cstring>
#include <cstdio>

using namespace std;

int main()
{
    unsigned char c;
    unsigned char e = 128;
    cout << endl;
    cout << "ASCII codes: Part 1" << endl << endl;
	for(int x=1; x<=20; x++)
	{
	printf("=");
	}
	
	cout << endl << endl;
	
	cout << (char)0xDa;
	for(int i=0; i<63; ++i)
	cout << (char)0xC4;
	cout << (char)0xBF;
	for(c=0; c<=127; c++)
    {
        if(c%8 == 0)
        {
            printf("\n");
        }
        printf("%d %c \t", c, c);
        cout << (char)0xB3;
    }
    cout << endl;
    cout << (char)0xC0;
	for(int i=0; i<63; ++i)
	cout << (char)0xC4;
	cout << (char)0xD9;
	cout << '\n';
    cout << endl << endl;
    cout << "ASCII codes: Part 2" << endl << endl;
    for(int y=1; y<=20; y++)
	{
	printf("=");
	}
	cout << endl;
	cout << (char)0xDa;
	for(int i=0; i<63; ++i)
	cout << (char)0xC4;
	cout << (char)0xBF;
    while(e>=128)
    {
        printf("%d %c \t", e, e);
        cout << (char)0xB3;
        ++e;
        if(e==128)
        {
            continue;
        }
        else if(e%8 == 0)
        {
            printf("\n");
        }
    }
    cout << (char)0xC0;
	for(int i=0; i<63; ++i)
	cout << (char)0xC4;
	cout << (char)0xD9;
	cout << '\n';
    return 0;
}


Here's the output:

Last edited on
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
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>            // for isprint
using namespace std;

//======================================================================

void printRange( const char *title, int i1, int i2, int numPerLine, char unprintable )
{
  char HORZ = '-';           // Change to other characters if available
  char VERT = '|';           //
  int numW  = 3;             // Width for writing out an integer
  int charW = 1;             // Width for writing out a character
  int tableW = numPerLine * ( numW + charW + 4 ) +  1;         // allows for line + space + integer + space + char + space  per item
                                                               // plus extra line at the end
  cout << title << "\n\n";
  cout << string( tableW, HORZ ) << '\n';
  for ( int i = i1; i <= i2; i++ )
  {
    char c = i;
    if ( i < 128 && !isprint( c ) ) c = unprintable;

    cout << VERT << " " << setw( numW ) << i << " " << setw( charW ) << c << " ";

    if ( ( i - i1 + 1 ) % numPerLine == 0 ) cout << VERT << '\n';
  }
  cout << string( tableW, HORZ ) << "\n\n";
}

//======================================================================

int main()
{
  printRange( "Character set   0-127:",   0, 127, 8, ' ' );
  printRange( "Character set 128-255:", 128, 255, 8, ' ' );
}

//====================================================================== 


If you want "box" corners then you would have to change lines (15), 18, 28 ... and be able to plot those characters. Depends on your output device.

128-255 don't plot in c++ shell in my browser, but work OK in a command window.
Last edited on
Thank you lastchance, but the lines now arent homogenous at all. They are with blanks. I would prefer my example with homogenous vertical lines. I just cant make all of the lines to be homogenous with no blanks. In the problem I am given I need to make them without any blank lines. In other words I need a proper rectangular with vertical lines inside a rectangular almost as the output of my code. Also the proposed example does not have ASCII symbols from 0 to 32, which mine output has. So I hope someone can propose me how to tidy or change my code to get a tidy and nice output as it should appear (I gave an answer I need to get below).

The output I get now (from lastchance proposed code) is this:


It is far from where I need to get tho.

Any other ideas?

Here is the answer of how my table needs to show up:
Last edited on
*** Read lines 22 - 24 ***
(Warning - switch back to the other characters in C++ shell)

Please read @cubbi's comments on your other thread about the ASCII character set and its control characters. After all, how do you propose to "print" (i.e. visual output) a beep (i.e. sound)?

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
#include <iostream>
#include <iomanip>
#include <string>
#include <cctype>            // for isprint
using namespace std;

//======================================================================

string lineString( char left, char mid, char right, char horz, int wcell, int ncell )
{
   string result = "", cell = string( wcell, horz );
   result += left;
   for ( int i = 0; i < ncell - 1; i++ ) result += cell + mid;
   result += cell + right;
   return result;
}

//======================================================================

void printRange( const char *title, int i1, int i2, int numPerLine, char unprintable )
{
   // ***********************************************************************************
   // *** You WILL repeat WILL repeat WILL have to adapt the characters for your system *
   // ***********************************************************************************
// char HORZ = '-';           // Should work on all systems
// char VERT = '|';           //
// char TL   = '-';           //
// char TM   = '-';           //
// char TR   = '-';           //
// char BL   = '-';           //
// char BM   = '-';           //
// char BR   = '-';           //
   char HORZ = 196;           // May have to find the right BOX characters
   char VERT = 179;           //
   char TL   = 218;           // Top Left etc
   char TM   = 194;           //
   char TR   = 191;           //
   char BL   = 192;           //
   char BM   = 193;           //
   char BR   = 217;           //

   int numW  = 3;             // Width for writing out an integer
   int charW = 1;             // Width for writing out a character

   cout << title << "\n\n";
   cout << lineString( TL, TM, TR, HORZ, numW + charW + 3, numPerLine ) << "\n";
   for ( int i = i1; i <= i2; i++ )
   {
      char c = i;
      if ( i < 128 && !isprint( c ) ) c = unprintable;

      cout << VERT << " " << setw( numW ) << i << " " << setw( charW ) << c << " ";

      if ( ( i - i1 + 1 ) % numPerLine == 0 ) cout << VERT << '\n';
   }
   cout << lineString( BL, BM, BR, HORZ, numW + charW + 3, numPerLine ) << "\n\n";
}

//======================================================================

int main()
{
   printRange( "Character set   0-127:",   0, 127, 8, ' ' );
   printRange( "Character set 128-255:", 128, 255, 8, ' ' );
}

//====================================================================== 
Last edited on
Thank you very much lastchance. Your proposed code's output is almost excellent. However, I am curious to know why you dont get any symbols from 0 to 31? I mean I know cobbi wrote that these are blanks and it goes only until 127. So what the hell are the the so called ASCII symbols from 128 to 255 and some symbols from 0 to 31? I am also curious to know why you get different symbols (from 1 and so on) rather than from my proposed example? Is it computer specs that differentiate what you get? Anyhow, I need to get the symbols as in the given answer example (last picture) in my previous post. I almost got them with some differences (mainly lines) in my original code (first picture)!

Your output is:

Last edited on
However, I am curious to know why you dont get any symbols from 0 to 31? I mean I know cobbi wrote that these are blanks and it goes only until 127. So what the hell are the the so called ASCII symbols from 128 to 255 and some symbols from 0 to 31?

This is not exactly hard-to-find information:

http://lmgtfy.com/?q=ASCII
Last edited on
Hello Aurimas,

I suspect that you could change the line
if ( i < 128 && !isprint( c ) ) c = unprintable;
to
if ( ( i >= 7 && i <= 11 ) || i == 13 ) c = unprintable;
(maybe play around with those numbers a bit) and you will be a happy bunny.

Don't expect it to work in C++ shell, though. It is highly non-portable.
Last edited on
Thank you very much lastchance. Now it works perfectly. Could you also explain bit by bit the following part of your code:

1
2
3
4
5
6
7
8
9
10
11
12
13
cout << title << "\n\n";
   cout << lineString( TL, TM, TR, HORZ, numW + charW + 3, numPerLine ) << "\n";
   for ( int i = i1; i <= i2; i++ )
   {
      char c = i;
      if ( ( i >= 7 && i <= 11 ) || i == 13 ) c = unprintable;

      cout << VERT << " " << setw( numW ) << i << " " << setw( charW ) << c << " ";

      if ( ( i - i1 + 1 ) % numPerLine == 0 ) cout << VERT << '\n';
   }
   cout << lineString( BL, BM, BR, HORZ, numW + charW + 3, numPerLine ) << "\n\n";
}

I understand the rest just fine.
Last edited on
cout << title << "\n\n";
Writes out the title string, followed by two newlines.


cout << lineString( TL, TM, TR, HORZ, numW + charW + 3, numPerLine ) << "\n";
Outputs the string representing the top of the box, followed by a new line. The inputs to lineString() are the characters for top-left-corner (TL), middle junction (TM), top-right-corner (TR), horizontal line (HORZ); then the integer width of a cell (number, character and 3 spaces) and the number of cells (numPerLine).


for ( int i = i1; i <= i2; i++ )
Loops from character i1 to i2 as determined by the function call


char c = i;
The character with index i


if ( i < 128 && !isprint( c ) ) c = unprintable;
If I didn't think it was printable I replaced c by whatever character was passed to the argument unprintable (a blank space in this instance)


cout << VERT << " " << setw( numW ) << i << " " << setw( charW ) << c << " ";
Outputs: a vertical line character, a space, an integer in the width numW (here, 3), a space, a character in the width charW (here, 1), a space.


if ( ( i - i1 + 1 ) % numPerLine == 0 ) cout << VERT << '\n';
At the end of the line plots a final vertical line and then does a linefeed.


cout << lineString( BL, BM, BR, HORZ, numW + charW + 3, numPerLine ) << "\n\n";
Similar to the line representing the top of the box.


You should look at the use of streamed c++ output (e.g. cout) and manipulators (e.g. setw()) on the tutorial on this website. It is an alternative approach to using printf and has the advantage that it is easier to change output stream (e.g. to write to a file or a stringstream instead of the console).

Last edited on
This example is perfect for drawing lines in windows, but maybe you know how to draw lines in mac? Or maybe you could suggest me what to read to understand how to draw lines. I still have 3 problems where I have to draw lines to and not moving any closer. Still stuck:(
I don't use a Mac, so I've no idea.

What - if anything - does the following produce on your Mac system (which I have no way of testing)?

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
#include <iostream>
#include <string>
using namespace std;

int main()
{
   // Box characters; requires extended character set (chars 128-255) to be available
   char HORZ  = 196;     // HORiZontal line
   char VERT  = 179;     // VERTical line
   char CROSS = 197;     // CROSS (+)
   char TL    = 218;     // Top Left
   char TM    = 194;     // Top Middle
   char TR    = 191;     // Top Right
   char BL    = 192;     // Bottom Left
   char BM    = 193;     // Bottom Middle
   char BR    = 217;     // Bottom Right
   char LM    = 195;     // Left Middle
   char RM    = 180;     // Right Middle

   string line1 = TL + string( 15, HORZ ) + TR;
   string line2 = VERT + string( " Hello, world! " ) + VERT;
   string line3 = BL + string( 15, HORZ ) + BR;

   cout << line1 << endl;
   cout << line2 << endl;
   cout << line3 << endl;
}


Last edited on
This isn't 1992, guys

this works for me on Linux and Windows (win10, compiled with VS2017)

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
#include <iostream>
#include <string>
#ifdef _MSC_VER
#include "windows.h"
#endif
int main()
{
	const char* HORZ = u8"─";     // HORiZontal line
	const char* VERT = u8"│";     // VERTical line
	const char* TL = u8"┌";     // Top Left
	const char* TR = u8"┐";     // Top Right
	const char* BL = u8"└";     // Bottom Left
	const char* BR = u8"┘";     // Bottom Right

	std::string line1 = TL;
	std::string line3 = BL;
	for (int n = 0; n < 15; ++n) {
		line1 += HORZ;
		line3 += HORZ;
	}
	line1 += TR;
	line3 += BR;
	std::string line2 = VERT + std::string(" Hello, world! ") + VERT;
#ifdef _MSC_VER
	SetConsoleOutputCP(CP_UTF8);
#endif
	std::cout << line1 << '\n'
		<< line2 << '\n'
		<< line3 << '\n';
}

output pasted from Windows:

┌───────────────┐
│ Hello, world! │
└───────────────┘
Press any key to continue . . .

(the "u8" crutch can be dropped on Linux and on VS2017 with /utf-8 option. I hear, but can't verify at the moment, that older MSVC would also require setvbuf(stdout, nullptr, _IOFBF, 1000); to workaround a bug with UTF-8 output from C++)
Last edited on
Ah, cheers @Cubbi! The unicode version was beyond me!
Thank you lastchance and Cubbi! Unfortunately, none of the examples worked on my mac. First code gave me 11 warnings saying: "implicit conversion from from 'int' to 'char' changes value from 217 to 63 [-Wconstant-conversion]' Same for 194, 191, 192, 193, 195, 180, 218, 197, 179 and 196 integers. And the second example gave me 12 errors saying: "use of undeclared identifier 'u8' and "expected ';' at end of declaration after u8". How to solve that?
Last edited on
use of undeclared identifier 'u8'

use C++11 or newer
Or just skip u8 (as in, use const char* HORZ = "─";) - it is only needed on Windows when not compiling with /utf-8
Hello lastchance and Cubbi!
Can you also explain this part of the code? Thanks! Also what does unprintable do?

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
 
string lineString( char left, char mid, char right, char horz, int wcell, int ncell )
{
   string result = "", cell = string( wcell, horz );
   result += left;
   for ( int i = 0; i < ncell - 1; i++ ) result += cell + mid;
   result += cell + right;
   return result;
}

//======================================================================

void printRange( const char *title, int i1, int i2, int numPerLine, char unprintable )
{
   char HORZ = 196;           // Horizontal line
   char VERT = 179;           // Vertical line
   char TL   = 218;           // Top left
   char TM   = 194;           // Top middle
   char TR   = 191;           // Top right
   char BL   = 192;           // Bottomo left
   char BM   = 193;           // Bottom middle
   char BR   = 217;           // Bottom right

   int numW  = 3;             // Width for writing out an integer
   int charW = 1;             // Width for writing out a character 
Last edited on
lineString() just builds up the set of characters required to put the box edges at top and bottom of your table. This is accumulated in variable result and eventually returned.
It starts with a blank string (result = "").
It adds whatever character denotes the left, which will be either top-left or bottom-left (result += left ).
It adds lines and joiners across the next ncell-1 columns (result += cell + mid).
It adds the last cell's line and corner (result += cell + right)
If you draw this out on paper you will see what is happening.


Some characters - as has been repeatedly explained in this thread - can't be written to the console. Things won't line up properly unless something is printed, so unprintable is just whatever you have chosen to fill this spot - the most obvious being a blank space: ' '.

If you look down the fancy table of extended characters that were printed (under Windows) you will see which ones correspond to numbers 196, 179, 218 etc.

@cubbi gave you a solution in Unicode, which I couldn't manage.
Thanks lastchance for explaining! Also thanks Cobbi for finding a way how it should work on unicode based OS. It worked, while using Xcode. Now I have until tomorrow to write a code as Im going to give it in tomorrow. Thanks again!
Topic archived. No new replies allowed.