void main()
main
returns an int
. Period.
void main
as a non-standard extension.
int main
is standard, so it works everywhere.
endl
vs. '\n'
cout << "just" << endl; cout << "kill" << endl; cout << "me" << endl; cout << "now" << endl;
just kill me now
endl
and '\n'
are not the same.
endl
means emit '\n'
and then flush the output.
endl
vs. '\n'
Here’s a better way:
cout << "just" << '\n' << "kill" << '\n' << "me" << '\n' << "now" << '\n';
just kill me now
Or, perhaps:
cout << "just\n" << "kill\n" << "me\n" << "now\n";
just kill me now
There is no benefit to memorizing the ASCII table, at the cost of program readability.
char c1 = 65; // Sure, this works. char c2 = 'A'; // But so does this. cout << c1 << c2;
AA
Doing work for the computer is like cleaning up for the maid. I see code like this:
inches = miles * 63360; // 63,360 inches in a mile
When I ask the student, “How’d you come up with that number?”, I often hear “I multiplied 5280 by 12 on a calculator.” Gosh—that sounds like something that the computer should be doing:
inches = miles * 5280 * 12; // 5280 feet/mile, 12 inches/foot
The compiler will fold the constant multiplication for you.
Indentation is often regarded as useless. As long as the program works, that’s all that matters!
Those of us who have to read and maintain your code disagree.
Casting is not magic.
char buf[] = "123"; long n = (long) buf; cout << n << '\n';
140736895442964
If you use casting, then something is wrong. Think again.
Java programmers love .at()
, and refuse to learn about []
. .at()
does error checking, []
usually doesn’t.
vector<int> v = {11,22,33}; for (size_t i=0; i<v.size(); i++) cout << v.at(i) << ' '; for (size_t i=0; i<v.size(); i++) cout << v[i] << ' ';
11 22 33 11 22 33
Do we really need error checking in that code?
Do we suspect that i
may get out of range?
Similarly, for strings:
string s = "Jack Applin"; cout << "My initials are " << s[0] << s[5] << '\n';
My initials are JA
You do not have to use new
to create an object:
string s; s.push_back('C'); s += 'S'; s += "U"; cout << s << '\n';
CSU
$ wc -l /etc/resolv.conf 4 /etc/resolv.conf
eof()
does not mean “Will the next read fail?”.
ifstream in("/etc/resolv.conf"); while (!in.eof()) { string s; getline(in, s); cout << "** " << s << '\n'; }
** search cs.colostate edu colostate.edu ** nameserver 129.82.45.181 ** nameserver 129.82.103.78 ** nameserver 129.82.103.79 **
eof()
means “Did the previous read fail?”.
ifstream in("/etc/resolv.conf"); string s; while (getline(in, s)) cout << "** " << s << '\n';
** search cs.colostate edu colostate.edu ** nameserver 129.82.45.181 ** nameserver 129.82.103.78 ** nameserver 129.82.103.79
It’s ok to use boolean values as values, not just in if
and while
:
char c = 'a'; bool vowel; if (c=='a' || c=='e' || c=='i' || c=='o' || c=='u') vowel=true; else vowel=false; cout << boolalpha << vowel << '\n';
true
char c = 'a'; bool vowel = (c=='a' || c=='e' || c=='i' || c=='o' || c=='u'); cout << boolalpha << vowel << '\n';
true
return
is not a function, so parentheses are not required:
int main() { cout << "Hello\n"; return 0; // Note lack of parens }
Hello
throw
is not equivalent to “produce an error”.
string s = "bonehead"; cout << s.at(12);
terminate called after throwing an instance of 'std::out_of_range' what(): basic_string::at: __n (which is 12) >= this->size() (which is 8) SIGABRT: Aborted