/* A program that writes to the two default output streams: - cout to standard output - cerr to standard error. */ #include <iostream> using namespace std; int main() { cout << "Writing this to cout.\n"; cerr << "Writing this to cerr.\n"; return 0; } |
By default both standard output and standard error go to the terminal, so running this without any file redirection results in both lines going to the terminal:
UNIX> bin/coutcerr Writing this to cout. Writing this to cerr. UNIX>However, if you redirect standard output to a file, you see that standard error still goes to the terminal. This is nice because you can alert the user to erroneous conditions even he or she is redirecting standard output to a file:
UNIX> bin/coutcerr > output.txt Writing this to cerr. UNIX> cat output.txt Writing this to cout. UNIX>Shells differ on how to redirect both standard output and standard error to a file. to a file with ">&":
UNIX> bin/coutcerr >& output.txt UNIX> cat output.txt Writing this to cout. Writing this to cerr. UNIX>
/* This program uses printf() instead of cout to print hello world. */ #include <cstdio> int main() { printf("Hello world\n"); return 0; } |
You'll note that I included <cstdio> instead of <iostream>, because printf() is defined in the C stdio library. I also omitted the "using namespace std", because the only thing I'm using in this program is printf(), and it is part of C and not C++. Typically, though, you use so much from the "std" namespace that you have to include the "using namespace std" statement. The output of this program is pretty obvious:
UNIX> bin/hwpf Hello world UNIX>You may specify that printf() print additional arguments by putting a percent sign in the formatting string with more special formatting commands. For example, putting "%d" in the formatting string specifies to print the next parameter as an integer. The program src/ints1.cpp shows a for() loop where each printf() statement prints three integers, i, i2, and 2i:
/* Use printf() to print out each number, i, from 0 to 10, along with its square and its double. */ #include <cstdio> using namespace std; int main() { int i, j; for (i = 0; i <= 10; i++) { j = i*i; printf("I is %d - i*i is %d - i*2 is %d\n", i, j, i*2); } return 0; } |
The output is straightforward:
UNIX> bin/ints1 I is 0 - i*i is 0 - i*2 is 0 I is 1 - i*i is 1 - i*2 is 2 I is 2 - i*i is 4 - i*2 is 4 I is 3 - i*i is 9 - i*2 is 6 I is 4 - i*i is 16 - i*2 is 8 I is 5 - i*i is 25 - i*2 is 10 I is 6 - i*i is 36 - i*2 is 12 I is 7 - i*i is 49 - i*2 is 14 I is 8 - i*i is 64 - i*2 is 16 I is 9 - i*i is 81 - i*2 is 18 I is 10 - i*i is 100 - i*2 is 20 UNIX>However, it is ugly. It's nicer if you can make sure that all those ints print with the same number of characters so that they line up. You do that by putting a width specification in front of the 'd' in "%d" (in src/ints2.cpp):
/* This is the same as ints1.cpp, except: - We print i and 2*i with a field width of two characters. - We print i*i with a field width of three characters. In that way, they all line up in nice, neat columns. */ #include <cstdio> using namespace std; int main() { int i, j; for (i = 0; i <= 10; i++) { j = i*i; printf("I is %2d - i*i is %3d - i*2 is %2d\n", i, j, i*2); // ^^^ ^^^ ^^^ } return 0; } |
This output is much nicer:
UNIX> bin/ints2 I is 0 - i*i is 0 - i*2 is 0 I is 1 - i*i is 1 - i*2 is 2 I is 2 - i*i is 4 - i*2 is 4 I is 3 - i*i is 9 - i*2 is 6 I is 4 - i*i is 16 - i*2 is 8 I is 5 - i*i is 25 - i*2 is 10 I is 6 - i*i is 36 - i*2 is 12 I is 7 - i*i is 49 - i*2 is 14 I is 8 - i*i is 64 - i*2 is 16 I is 9 - i*i is 81 - i*2 is 18 I is 10 - i*i is 100 - i*2 is 20 UNIX>Each integer is printed with a given number of characters, right justified. Printing doubles is more problematic. (Oh, by the way, we don't use float's in this class. They are too prone to round-off error.) You specify a float with "%lf". By default, that prints the double to six decimal digits. If you want to specify widths, as we did with int's above, you use "%t.dlf", where t is the total width and d is the number of decimal digits. For example, the following program (src/pieln10.cpp) prints pi, e and the natual log of 10, each of which will have seven total digits, five after the decimal point:
/* Print pi, e, and the natual log of 10, each with 7 total digits, 5 after the decimal point. */ #include <cmath> #include <cstdio> using namespace std; int main() { double pi, e, ln10; pi = acos(-1.0); // I figure at this point, you might enjoy some high school math. e = exp(1.0); // exp(x) returns e to the x-th power ln10 = log(10.0); // The poorly named log(x) returns the natural log of x. printf("pi: %7.5lf\n", pi); printf("e: %7.5lf\n", e); printf("ln10: %7.5lf\n", ln10); return 0; } |
Here's the output:
UNIX> bin/pieln10 pi: 3.14159 e: 2.71828 ln10: 2.30259 UNIX>How did I know what those math functions were? They are part of the math library of C, which is defined there in <cmath>. You can see a listing of the functions at https://en.wikipedia.org/wiki/C_mathematical_functions.
Charlie Crossway 286-50-9109 Molly Needham 825-03-8649 Molly Nashville 543-73-8293 Cindy Endgame 003-12-8676 Tamika Marty 230-97-5641 John Scar 724-14-6244 Lazar Argive 258-28-8603 Blanche Subterfuge 790-84-5341 Raynoch Sarsaparilla 151-05-7446 Baine Junta 761-03-0452 |
And suppose you want to print it more nicely, so that first names, last names, and SSN's are in their own columns. Here's some code to do it (src/ssn-reader.cpp):
/* This program reads three words at a time -- first name, last name, and social security number (as a string, not as a number). It then prints them, each in its own column. */ #include <iostream> #include <cstdio> using namespace std; int main() { string fn, ln, ssn; while (cin >> fn >> ln >> ssn) { printf("%-10s %-13s %11s\n", fn.c_str(), ln.c_str(), ssn.c_str()); } return 0; } |
With the width specification, I use negative numbers to left-justify the strings, and pad them to 10, 13 and 11 characters respectively:
UNIX> bin/ssn-reader < data/info-file.txt Charlie Crossway 286-50-9109 Molly Needham 825-03-8649 Molly Nashville 543-73-8293 Cindy Endgame 003-12-8676 Tamika Marty 230-97-5641 John Scar 724-14-6244 Lazar Argive 258-28-8603 Blanche Subterfuge 790-84-5341 Raynoch Sarsaparilla 151-05-7446 Baine Junta 761-03-0452 UNIX>
/* Print the character values of numbers from 32 to 127, in eight columns. */ #include <iostream> #include <cstdio> using namespace std; int main() { int i, j; for (i = 32; i < 128; i += 8) { for (j = 0; j < 8; j++) { printf("%3d: '%c' ", i+j, i+j); } printf("\n"); } return 0; } |
Observe that i is an int and not a char, but the code works fine. The reason it works is because "%c" prints the character based on the ASCII value of a number, and char's and int's are both numbers.
Here's the output:
UNIX> bin/printchars 32: ' ' 33: '!' 34: '"' 35: '#' 36: '$' 37: '%' 38: '&' 39: ''' 40: '(' 41: ')' 42: '*' 43: '+' 44: ',' 45: '-' 46: '.' 47: '/' 48: '0' 49: '1' 50: '2' 51: '3' 52: '4' 53: '5' 54: '6' 55: '7' 56: '8' 57: '9' 58: ':' 59: ';' 60: '<' 61: '=' 62: '>' 63: '?' 64: '@' 65: 'A' 66: 'B' 67: 'C' 68: 'D' 69: 'E' 70: 'F' 71: 'G' 72: 'H' 73: 'I' 74: 'J' 75: 'K' 76: 'L' 77: 'M' 78: 'N' 79: 'O' 80: 'P' 81: 'Q' 82: 'R' 83: 'S' 84: 'T' 85: 'U' 86: 'V' 87: 'W' 88: 'X' 89: 'Y' 90: 'Z' 91: '[' 92: '\' 93: ']' 94: '^' 95: '_' 96: '`' 97: 'a' 98: 'b' 99: 'c' 100: 'd' 101: 'e' 102: 'f' 103: 'g' 104: 'h' 105: 'i' 106: 'j' 107: 'k' 108: 'l' 109: 'm' 110: 'n' 111: 'o' 112: 'p' 113: 'q' 114: 'r' 115: 's' 116: 't' 117: 'u' 118: 'v' 119: 'w' 120: 'x' 121: 'y' 122: 'z' 123: '{' 124: '|' 125: '}' 126: '~' 127: '' UNIX>One nice thing about ASCII is that the upper case, lower case and decimal characters are all contiguously numbered. Therefore, you can do math on the numbers with logical results. For example, if i is a lower case letter, you can convert it to an upper case letter with: i + ('A'-'a').
When you specify a character, such as 'A' in a program, the compiler simply turns it into its ASCII integer. Thus, 'A' really equals 65. It's just easier to read it as 'A'.
The lower ASCII values are some of the weirder characters, like TAB, BACKSPACE and NEWLINE.
There are two other ways to print out integers -- as octal with "%o", and as hexadecimal with "%x". By convention, when you specify an integer with a preceding '0', the C++ compiler treats it as octal, or base eight. When you specify an integer with a preceding "0x", the C++ compiler treats it as hexadecimal, or base sixteen, with the characters 'a' through 'f' corresponding to the digits from 10 through 15.
Look at an example program in src/weirdints.cpp:
/* This program demonstrates octal and hexadecimal numbers, both as literals in C++, and when printed with printf(). */ #include <iostream> #include <cstdio> using namespace std; int main() { int i, j; printf(" 010 is equal to: %2d 0%02o 0x%02x\n", 010, 010, 010); printf("0x10 is equal to: %2d 0%02o 0x%02x\n", 0x10, 0x10, 0x10); printf("\n"); /* Print the numbers from 0 to 31 in octal and in hex. Print four numbers per row. */ for (i = 0; i < 32; i++) { printf(" %2d 0%02o 0x%02x", i, i, i); if (i%4 == 3) printf("\n"); } return 0; } |
The first line shows that "010" is interpreted by the C++ compiler as 10 in octal, which is equal to 8 in decimal, and 0x8 in hexadecimal. The second line shows that "0x10" is interpreted as 10 in hexadecimal, which is 16 in decimal, and 20 in octal. The remaining lines show the values from 0 to 31 in decimal, octal and hexadecimal:
UNIX> bin/weirdints 010 is equal to: 8 010 0x08 0x10 is equal to: 16 020 0x10 0 000 0x00 1 001 0x01 2 002 0x02 3 003 0x03 4 004 0x04 5 005 0x05 6 006 0x06 7 007 0x07 8 010 0x08 9 011 0x09 10 012 0x0a 11 013 0x0b 12 014 0x0c 13 015 0x0d 14 016 0x0e 15 017 0x0f 16 020 0x10 17 021 0x11 18 022 0x12 19 023 0x13 20 024 0x14 21 025 0x15 22 026 0x16 23 027 0x17 24 030 0x18 25 031 0x19 26 032 0x1a 27 033 0x1b 28 034 0x1c 29 035 0x1d 30 036 0x1e 31 037 0x1f UNIX>Octal is useful as a way to show bits in groups of three. For example, 0644 is equal to 110 100 100 in binary. Sometimes that is convenient.
Hexadecimal is much more convenient, because 16 = 24, which means that you can represent a byte with exactly two digits in hexadecimal. For that reason, hexadecimal is used to represent pointers in programs (You'll see more of that later in your career). As another example, sometimes computer routers are identified by six-byte ID numbers. Often you see these id's represented by bytes in hexadecimal separated by colons, such as "00:19:e3:d8:5c:64". The hexadecimal makes reading the bytes convenient.
A final detail of src/weirdints.cpp -- the printf() statement is:
printf(" %2d 0%02o 0x%02x", i, i, i); |
When you put a zero in front of a width specification, that says to pad the number to the given number of digits, and put in leading zeros instead of spaces. Without that specification, the number zero would have been printed as "0x 0" instead of "0x00".