CS253: Software Development with C++

Fall 2019

Pet Peeves

Show Lecture.PetPeeves as a slide show.

CS253 Pet Peeves

made at imgflip.com

void main()

made at imgflip.com

endl vs. '\n'

cout << "Scarecrow" << endl;
cout << "Tin Man" << endl;
cout << "Cowardly Lion" << endl;
Scarecrow
Tin Man
Cowardly Lion

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

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

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

cout << 5280*12;
63360

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';
140727972190084

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

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