Please send questions to
st10@humboldt.edu .
CIS 130 - Week 15, Monday, May 3, 2010
* C++ provides the general while loop, usable for
just about any kind of repetition situation,
as well as the more-specialized for loop,
especially good for the special repetition case
of count-controlled loops;
* C++ provides the general if statement, usable
for just about any kind of branching situation,
as well as a more-specialized branching statement,
the switch statement
* Let's say I have letter grades expressed as char's.
and I want a function that expects such a letter grade
and produces a string message corresponding to that
grade:
'A' or 'B' ---> "High pass"
'C' or 'D' ---> "Pass"
'F' or 'I' ---> "Try again"
anything else ---> "Huh?"
contract: grade_msg: char -> string
purpose:
expects a char corresponding to a letter grade,
and produces the appropriate string for that grade,
according to the following:
'A' or 'B' ---> "High pass"
'C' or 'D' ---> "Pass"
'F' or 'I' ---> "Try again"
anything else ---> "Huh?"
string grade_msg(char grade)
examples:
grade_msg('A') == "High pass"
grade_msg('D') == "Pass"
grade_msg('F') == "Try again"
grade_msg('Q') == "Huh?"
string grade_msg(char grade)
{
if ( (grade == 'A') || (grade == 'B') )
return "High pass";
else if ( (grade == 'C') || (grade == 'D') )
return "Pass";
else if ( (grade == 'F') || (grade == 'I') )
return "Try again";
else
return "Huh?";
}
* when a switch may be a good choice:
* when you are making exactly 1 of 3 or more choices
* your choices can be represented as either int, char,
bool, or other "integral" (integer-based) types
* syntax: things in [] are OPTIONAL below...
switch(int_or_char_or_bool_expr)
{
case int_or_char_or_bool_value1:
statement;
...
[break;]
case int_or_char_or_bool_value2:
statement;
...
[break;]
...
[default:
statement;
...]
}
* semantics: the switch's expression is evaluated,
and compared to each case's value,
and as soon as one matches, execution begins at the statement
following that case,
and merrily KEEPS GOING through all the statements
until you either hit a break or the end of the
switch statement;
...then you continue after the switch statement
string desired_msg;
if ( (grade == 'A') || (grade == 'B') )
desired_msg = "High pass";
else if ( (grade == 'C') || (grade == 'D') )
desired_msg = "Pass";
else if ( (grade == 'F') || (grade == 'I') )
desired_msg = "Try again";
else
desired_msg = "Huh?";
return desired_msg;
string desired_msg;
switch(grade)
{
case 'A':
case 'B':
desired_msg = "High pass";
break;
case 'C':
case 'D':
desired_msg = "Pass";
break;
case 'F':
case 'I':
desired_msg = "Try again";
break;
default:
desired_msg = "Huh?";
}
return desired_msg;
* CAREFUL -- if you leave out a break, you "fall through" to the
remaining cases' actions!
* NOTE: a switch is a BRANCHING statement -- it is not a loop!
(it can go IN a loop, though -- often quite usefully!)
it is a SYNTAX error to use a non-integer-based switch
expression (int, bool, char are all integer-based)
it is a LOGIC/SEMANTIC error to leave out needed breaks
you'll get SOME kind of error -- sometimes syntax, sometimes
logic/semantic -- if you try to stick a bool condition as
the case value...
File input/output
* One of the ways of doing file input/output in C++ is with
the help of the fstream C++ standard library;
We've been using cin and cout from the C++ iostream standard
library to do interactive input/output;
We can use fstream to do a similar style of input from files
and output to files
* Here's how you do it:
#include <fstream>
// fun fact: fstream includes iostream! So you don't HAVE to #include
// <iostream> when you #include <fstream> ... it's OK if you do, though,
// because #ifndef keeps that from being problematic...
* IF you want to read from a file,
you need to set up an INPUT file stream:
ifstream my_infile_stream_name;
If you want to WRITE to a file,
you need to set up an OUTPUT file stream:
ofstream my_outfile_stream_name;
* then, you CONNECT these "logical" file streams to "physical"
files in your operating system (on your computer)
by using an open *method*
(oh! Preview of CIS 230 -- these are OBJECTS, and we are
calling their open method -- like a function for an object...)
<name_of_logical_file_stream>.open("string name of file to open");
for our streams above,
// this tries to open the file infile.txt in the current
// directory (where this C++ program is running)
// for reading...
// (I THINK you get a run-time error if this file doesn't
// exist or isn't allowed to be read)
my_infile_stream_name.open("infile.txt");
// this tries to open the file outfile.txt in the current
// directory -- if outfile.txt doesn't exist, it will
// create it. (If it already exists, its current contents
// are NUKED -- look up opening an output stream for appending
// if you want to add to the end of a file...)
my_outfile_stream_name.open("outfile.txt");
* once these are open --
read from an input file stream like you read from cin!
my_infile_stream_name >> data1 >> data2;
write to an output file stream like you write to cout!
my_outfile_stream_name << "something" << spiciness_level(10000) << endl;
* when you are done reading/writing, it is considered GOOD STYLE
(and sometimes it is quite important!!) to CLOSE your file
stream using its close method:
my_infile_stream_name.close();
my_outfile_stream_name.close();
* say we want a function that expects a string and simply
writes it to a file named "looky.txt"
(yes, it is a little silly)
contract: write_to_looky: string -> void
purpose: expects a string, and returns nothing,
but it has the side-effect of writing that
string to the file in the current working
directory named looky.txt (nuking whatever
previous contents it had)
void write_to_looky(string msg)
examples:
If I call:
write_to_looky("Hi there! Lookit me!!");
...this should have the side effect of causing the
file in the current directory named looky.txt to
contain:
Hi there! Lookit me!!
#include <fstream>
using namespace std;
void write_to_looky(string msg)
{
// create an output file stream
ofstream outstream;
// open it for writing, to a file named looky.txt
outstream.open("looky.txt");
// write the desired message to that file using outstream
// (I'm choosing to add a newline to the end of the message)
outstream << msg << endl;
// close the output file stream when you're done
outstream.close();
}
(after-class note)
* see posted example sum_from_file for an example of reading from a
file
* aha -- the ifstream and ofstream open method expects an
old-style char* string!!
* BUT: string has a method c_str() that returns that string
in char* form!
* So, for a string name,
name.c_str()
...is an expression of type char*, containing the char* string
equivalent to the new-style string in name
* I've posted two examples of simple C++ formatting, also:
* these require you to include the iomanip standard library
ALONG WITH iostream:
#include <iostream>
#include <iomanip>
using namespace std;
* setw(int) --- when put into an output stream, causes the
NEXT value to be right-justified in a field at least that
wide (if the value is wider, though, it does not TRUNCATE it)
example: setw_play
* to format a double to, say, 3 fractional places,
here is Savitch's "magic formula" (pp. 56-57) for getting all
doubles displayed using cout to format to a fixed number
of fractional places (it does NOT affect int values, note!)
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(3); // or however many fractional places you want
// should stay in effect, IN THAT FUNCTION, until you set
// it precision to some other value -- I think! 8-)
example: precision_play
* note: this does NOT actually change those values! It just
DISPLAYS them to that precision;