Show Lecture.PetPeeves as a slide show.
CS253 Pet Peeves
- In ANSI C++,
main()
returns an int
. Period.
- Some compilers accept
void
main()
as a non-standard extension.
- However,
int
main()
is standard, so it works everywhere.
- It’s shorter, too.
- This ain’t Java.
endl
vs. '\n'
cout << "Scarecrow" << endl;
cout << "Tin Man" << endl;
cout << "Cowardly Lion" << endl;
Scarecrow
Tin Man
Cowardly Lion
endl
and '\n'
are not the same.
endl
means emit '\n'
and then flush the output.
- Don’t flush the output every time—it’s inefficient, and confuses
the reader. “Why is the program flushing now?”
- Output automatically gets flushed when the stream is closed.
This is nearly always good enough.
endl
alternatives
cout << "Scarecrow" << '\n'
<< "Tin Man" << '\n'
<< "Cowardly Lion" << '\n';
Scarecrow
Tin Man
Cowardly Lion
cout << "Scarecrow\n"
<< "Tin Man\n"
<< "Cowardly Lion\n";
Scarecrow
Tin Man
Cowardly Lion
cout << "Scarecrow\n"
"Tin Man\n"
"Cowardly Lion\n";
Scarecrow
Tin Man
Cowardly Lion
cout << "Scarecrow\nTin Man\nCowardly Lion\n";
Scarecrow
Tin Man
Cowardly Lion
- Which is faster? Smaller? More readable?
- What is most important?
ASCII constants
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
- Which is easier to understand & modify?
- Besides, who says that all computers use ASCII?
Doing work for the computer
Doing work for the computer is like cleaning up for the maid.
I see code like this:
inches = miles * 63370;
When I ask the student, “How’d you come up with that number?”,
they say “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—it will
do the multiplication at compile-time, not during program execution.
Pants on Fire
- 5280 × 12 is not 63370.
- I lied, to simulate a typo.
- Did anybody notice?
- How many years would that bug have lain waiting in the code?
cout << 5280*12;
63360
- I wish that the USA would use the metric system.
Indentation
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
Casting is not magic.
char buf[] = "123";
long n = (long) buf;
cout << n << '\n';
140725766945972
If you use casting, then something is wrong. Think again.
vector/string methods
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 need error checking in that code?
Could i
get out of range?
Similarly, for strings:
string s = "Jack Applin";
cout << "My initials are " << s[0] << s[5] << '\n';
My initials are JA
Not everything is a reference
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
eof() does not predict
$ 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
Boolean is hard!
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 easy
return
is not a function, so parentheses are not required:
int main() {
cout << "Hello\n";
return 0; // Note lack of parens
}
Hello
throw
throw
is not equivalent to “produce an error”.
- The compiler does not throw errors.
- Dividing by zero does not throw anything (but it could).
- Dereferencing a null pointer doesn’t throw (it could).
- On the other hand, this is defined to throw an error:
string s = "foo";
cout << s.at(9);
terminate called after throwing an instance of 'std::out_of_range'
what(): basic_string::at: __n (which is 9) >= this->size() (which is 3)
SIGABRT: Aborted