【C++ Primer Plus】第6章 分支语句和逻辑运算符

6.1 if 语句

if 语法: if (test-condition) statement
if 测试条件将被强制转换为bool值,因此0将被转换为false,非零为true。

6.2 if else 语句

6.3 if else if else 结构

由于if else语句本身是 一条语句,所以可以放在else的后面。

// ifelseif.cpp -- using if else if else

#include <iostream>

const int Fave = 27;

int main()
{
    using namespace std;
    int n;
    cout << "Enter a number in the range 1-100 to find ";
    cout << "my favorite number: ";
    do
    {
        cin >> n;
        if (n < Fave)
            cout << "Too low -- guess again: ";
        else if (n > Fave)
            cout << "Too high -- guess again: ";
        else
            cout << Fave << " is right!\n";
    } while (n != Fave);
    return 0;
}

6.4 逻辑运算符:&&、|| 和 !

6.4.1 逻辑OR运算符:||

  1. 逻辑 || 的优先级比关系运算符低
  2. 如果原来表达式中的任何一个或全部都为true(或非零),则得到的表达式的值为true;否则,表达式的 值为false。
  3. 先修改左侧的值,再对右侧的值进行判定。(i++ < 6||i== j假设i原来的值为10,则在对i和j进行比较时,i 的值将为11。)
  4. 如果左侧的表达式为true,则C++将不会去判定右侧的表达式,因为只要一个表达式为true,则整个逻辑表达式为true。

6.4.2 逻辑AND运算符:&&

  1. 逻辑 && 的优先级比关系运算符低
  2. 逻辑AND运算符的优先级高于逻辑OR运算符。
  3. 仅当原来的两个表达式都为true时,得到的表达式的值才为true。
  4. 如果左侧为false,则整个逻 辑表达式必定为false,在这种情况下,C++将不会再对右侧进行判定。
  5. &&运算符还允许建立一系列if else if else语句,其中每种选择都对 应于一个特定的取值范围

6.4.3 逻辑NOT运算符:!

  1. ! 运算符将它后面的表达式的真值取反。
  2. ! 运算符的优先级高于所有的关系运算符和算术运算符.
// (将!运算符用于函数返回值)来筛选可 赋给int变量的数字输入。

#include <iostream>
#include <climits>      // 注意这里要加上头文件,定义了符号常量(INT_MAX和INT_MIN)

bool in_num(double n);

int main(void)
{
    using namespace std;

    cout << "Enter a number:";
    double num;     // 注意这里要定义成 double 类型的输入,取值范围比int大
    cin >> num;
    while (!in_num(num))
    {
        cout << "Enter against:";
        cin >> num;
    }
    int value = (int) num;
    cout << "you have entered the integer " << value << endl;

    return 0;
}

bool in_num(double n)
{
    if (n <= INT_MAX && n >= INT_MIN)
        return true;
    else
        return false;
}

out

Enter a number:6234128679
Enter against:135
you have entered the integer 135

6.5 cctype字符函数库

  1. 它可以简化诸如确定字符是否为大写字母、数字、标点符号等工作,这 些函数的原型是在头文件cctype(老式的风格中为ctype.h)中定义的。
  2. 例如,如果ch是一个字母,则isalpha(ch)函数返回一个非零值,否则 返回0。
  3. 同样,如果ch是标点符号(如逗号或句号),函数ispunct(ch)将返回true。
  4. 这些函数的返回类型为int,而不是bool.

使用AND和OR来测试字符ch是不是字母字符的代码: if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
使用isalpha( )来测试字符ch是不是字母字符的代码:if (isalpha(ch))
一些ctype库函数

  • isalnum() 如果参数是字母数字,即字母或数字,该函数返回true
  • isalpha() 如果参数是字母,该函数返回真
  • isblank() 如果参数是空格或水平制表符,该函数返回true
  • iscntrl() 如果参数是控制字符,该函数返回true
  • isdigit() 如果参数是数字(0~9),该函数返回true
  • isgraph() 如果参数是除空格之外的打印字符,该函数返回true
  • islower() 如果参数是小写字母,该函数返回true
  • isprint() 如果参数是打印字符(包括空格),该函数返回true
  • ispunct() 如果参数是标点符号,该函数返回true
  • isspace() 如果参数是标准空白字符,如空格、进纸、换行符、回车、水平制表符或者垂直制表符,该函数返回true
  • isupper() 如果参数是大写字母,该函数返回true
  • isxdigit() 如果参数是十六进制的数字,即0~9、af、AF,该函数返回true
  • tolower() 如果参数是大写字符,则返回其小写,否则返回该参数
  • toupper() 如果参数是小写字母,则返回其大写,否则返回该参数
// 使用isalpha( )来检 查字符是否为字母字符,
// 使用isdigits( )来测试字符是否为数字字符,如 3,
// 使用isspace( )来测试字符是否为空白,如换行符、空格和制表符,
// 使用ispunct( )来测试字符是否为标点符号。
// 该程序还复习了if else if结 构,并在一个while循环中使用了cin.get(char)。

#include <iostream>
#include <cctype>

int main(void)
{
    using namespace std;

    cout << "Enter text for analysis, and type @ to terminate input.\n";
    char ch;
    int whitespace = 0, digits = 0, chars = 0, punct = 0, others = 0;
    cin.get(ch);
    while (ch != '@')
    {
        if (isalpha(ch))
            chars++;
        else if (isspace(ch))
            whitespace++;
        else if (isdigit(ch))
            digits++;
        else if (ispunct(ch))
            punct++;
        else
            others++;
        cin.get(ch);
    }
    cout << chars << " letters, " << whitespace << " whitespace, " << digits << " digits, "
         << punct << " punctuations, " << others << " others.\n" << endl;

    return 0;
}

6.6 条件运算符:? :

语法:expression1 ? expression2 : expression3
被用来代替if else语句的运算符,是C++中唯一一个需要3个操作数的运算符。
如果expression1为true,则整个条件表达式的值为expression2的值; 否则,整个表达式的值为expression3的值。

// 条件运算符生成一个表达式,因此是一个值,可以将其赋给变量或将其放到一个更大的表达式中

#include <iostream>

int main(void)
{
    using namespace std;

    int a, b;
    cout << "Enter two int:";
    cin >> a >> b;
    int c = a>b ? a : b;    // 条件运算符生成一个表达式,因此是一个值,可以将其赋给变量或将其放到一个更大的表达式中
    cout << "c = " << c << endl;

    return 0;
}

6.7 switch语句

switch 语句格式

switch (integer-expression) {
    case label1 : statement(s)
    case label2 : statement(s)
    ...
    default : statement(s)
}
  1. 执行到switch语句时,程序将跳到使用integer-expression的值标记的 那一行。例如,如果integer-expression的值为4,则程序将执行标签为 case 4:那一行。
  2. 顾名思义,integer-expression必须是一个结果为整数值的表达式。另外,每个标签都必须是整数常量表达式。最常见的标签是 int或char常量(如1或’q’),也可以是枚举量。switch语句将int值和枚举量标签进行比较时,将枚举量提升为int。
  3. 如果integer-expression不与任何标签匹配,则程序将跳到标签为default的那一行。Default标签是可选的,如果被省略,而又没有匹配的标签,则程序将跳到switch后面的语句处执行。
  4. 程序跳到switch中特定代码行后,将依次执行之后的所有语句,除非有明确的其他指示。程序不会在执行到下一个case处自动停止,要让程序执行完一组特定语句后停止,必须使用break语句。这将导致程序跳到switch 后面的语句处执行。
// 如何使用switch和break来让用户选择简单菜单。
// 该程序使用showmenu( )函数显示一组选项,然后使用switch语句, 根据用户的反应执行相应的操作。
// 使用字符(而不是整数)作为菜单选项和switch标签,则可以为大写标签和小写标签提供相同的语句

#include <iostream>
using namespace std;

void showmenu();
void report();
void comfort();

int main(void)
{
    showmenu();
    int choice;
    cin >> choice;
    while(choice != 5)  // 当用户输入了5时,while循环结束。输入1到4将执行switch列表中 相应的操作,输入6将执行默认语句。
    {
        switch(choice)
        {
            case 1 : cout << "\a\n"; break;
            case 2 : report(); break;
            case 3 : cout << "The boss was in all day.\n"; break;
            case 4 : comfort(); break;
            default : cout << "That's not a choice.\n";
        }
        showmenu();
        cin >> choice;
    }
    cout << "Bye!\n";

    return 0;
}

void showmenu()
{
    cout << "Please enter 1, 2, 3, 4, or 5 :\n"
            "1) alarm   2) report\n"
            "3) alibi   4) comfort  5) quit\n";
}

void report()
{
    cout << "I LOVE YOU!\n";
}

void comfort()
{
    cout << "THINK YOU!\n";
}

6.8 continue和break语句

  1. break和continue语句都使程序能够跳过部分代码。
  2. 可以在switch语句或任何循环中使用break语句,使程序跳到switch或循环后面的语句处执行。
  3. continue语句用于循环中,让程序跳过循环体中余下的代码,并开始新一轮循环。
// 该程序让用户输入 一行文本。循环将回显每个字符,如果该字符为句点,则使用break结束循环。
// 这表明,可以在某种条件为true时,使用break来结束循环。
// 接下来,程序计算空格数,但不计算其他字符。当字符不为空格时,循环使用continue语句跳过计数部分。

#include <iostream>
#include <cstring>
const int ArSize = 80;

int main(void)
{
    using namespace std;

    cout << "Please enter string str:";
    char str[ArSize];
    cin.get(str, ArSize).get();
    cout << "Complete line:\n" << str << endl;
    int space = 0;
    for (int i=0; i < strlen(str); i++)
    {
        cout << str[i];
        if (str[i] == ' ')
        {
            space++;
            continue;   // 虽然continue语句导致该程序跳过循环体的剩余部分,但不会跳过循环的更新表达式
        }
        if (str[i] == '.')
            break;
    }
    cout << endl << space << " space\n";
    cout << "Done!";

    return 0;
}

C++也有goto语句:

// 下面的语句将跳到使用paris:作为标签的位置:
char ch;
cin >> ch;
if (ch == 'P')
goto paris;
cout << ...
...
paris: cout << "You've just arrived at Paris.\n";

6.9 读取数字的循环

输入错误和EOF都将导致cin返回false。clear( )方法重置错误输入标记,同时也重置文件尾。
表达式cin>>fish[i]实际上一个是cin方法函数调用,该函数返回cin。如果cin位于测试条件中,则将被转换为bool类型。如果输入成功,则转换后的值为true,否则为false。
程序发现用户输入了错误内容时,应采取3个步骤:

  1. 重置cin以接受新的输入。
  2. 删除错误输入。
  3. 提示用户再输入。
// 假设程序要求用户提供5个高尔夫得分,以计算平均成绩。如果用户输入非数字输入,程序将拒绝,并要求用户继续输入数字。
// 可以看到,可以使用cin输入表达式的值来检测输入是不是数字。

// cingolf.cpp -- non-numeric input skipped
#include <iostream>
const int Max = 5;

int main()
{
    using namespace std;
// get data
    int golf[Max];
    cout << "Please enter your golf scores.\n";
    cout << "You must enter " << Max << " rounds.\n";
    int i = 0;
    for (i = 0; i < Max; i++)
    {
        cout << "round #" << i+1 << ": ";
        while (!(cin >> golf[i]))   // 使用cin输入表达式的值来检测输入是不是数字。
        {
            cin.clear();            // reset input
            while (cin.get() != '\n')
                continue;           // get rid of bad input
            cout << "Please enter an int number:";
        }
    }
// calculate average
    double total = 0.0;
    for (i = 0; i < Max; i++)
        total += golf[i];
// report results
    cout << total / Max << " = average score " << Max << " rounds\n";
    return 0;
}

out:

Please enter your golf scores.
You must enter 5 rounds.
round #1:20
round #2:dk
Please enter an int number:30
round #3:10
round #4:50
round #5:60
34 = average score 5 rounds

6.10 基本文件输入/输出

#include // ostream->cout istream->cin
#include // ofstream ifstream
#include // support for exit()

6.10.1 cin 输入

  1. 必须包含头文件iostream。
  2. 头文件iostream定义了一个用处理输入的istream类。
  3. 头文件iostream声明了一个名为cin的istream变量(对象)。
  4. 必须指明名称空间std;例如,为引用元素cin,必须使用编译指令 using或前缀std::。
  5. 可以结合使用cin和运算符>>来读取各种类型的数据。 可以使用cin和get( )方法来读取一个字符,使用cin和getline( )来读 取一行字符。
  6. 可以结合使用cin和eof( )、fail( )方法来判断输入是否成功。
  7. 对象cin本身被用作测试条件时,如果最后一个读取操作成功,它 将被转换为布尔值true,否则被转换为false。
  8. 使用cin进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。不管目标数据类型是什么,输入一开始都是字符数据——文本数据。然后,cin对象负责将文本转换为其他类型。
38.5 19.2	// 输入,输入一开始为文本
    
char ch;
cin >> ch;	// 3  输入行中的第一个字符被赋给ch

int n;
cin >> n;	// 38  直到遇到非数字字符

double x;
cin >> x;	// 38.5  直到遇到第一个不属于浮点数的 字符

char word[50];
cin >> word;	// 38.5  直到遇到空白字符,cin将这4个字符的字符编码存储到数组word中,并在末尾加上一个空字符。

char word[50];
cin.geline(word,50);	// 直到遇到换行符,并在末尾加上一个空字符。换行符被丢弃,输入队列中的下一个字符是下一行中的第一个字符。
int number;
cin >> number;				// 写入一个数字

char ch;
cin >> ch;					// 输入一个字符,不保留空格和换行符

string str, str1[2];
getline(cin, str);			// 写入一个string
getline(cin, str1[1]);		// 写入一个string数组中的一个string变量

char ch[100];
(cin >> ch).get();         //以空白(空格、 制表符和换行符)来确定字符串的结束位置。保留换行符;把回车键生成的换行符留在了输入队列中。
cin.getline(ch, 100);      //每次读取一行字符串输入,丢弃换行符;arraySize(包括结尾字符)。
cin.get(ch, 100).get();    //每次读取一行字符串输入,保留换行符;

char ch;
cin.get(ch);
...							// 然后进行一系列操作
cin.get();					// 消除空行

6.10.2 cout 输出

  1. 必须包含头文件iostream。
  2. 头文件iostream定义了一个用处理输出的ostream类。
  3. 头文件iostream声明了一个名为cout的ostream变量(对象)。
  4. 必须指明名称空间std;例如,为引用元素cout和endl,必须使用编 译指令using或前缀std::。
  5. 可以结合使用cout和运算符<<来显示各种类型的数据。

6.10.3 文件输出/写入文件

  1. 必须包含头文件fstream。
  2. 头文件fstream定义了一个用于处理输出的ofstream类。
  3. 需要声明一个或多个ofstream变量(对象),并以自己喜欢的方式 对其进行命名,条件是遵守常用的命名规则。
  4. 必须指明名称空间std;例如,为引用元素ofstream,必须使用编译 指令using或前缀std::。
  5. 需要将ofstream对象与文件关联起来。为此,方法之一是使用open( )方法。
  6. 使用完文件后,应使用方法close( )将其关闭。
  7. 可结合使用ofstream对象和运算符<<来输出各种类型的数据。

文件输出的主要步骤:

// 1、包含头文件fstream
#include <iostream> 	// ostream->cout    istream->cin
#include <fstream>  	// ofstream         ifstream

// 2、声明自己的ofstream对象,为其命名
ofstream outFile; 		// outFile an ofstream object 
ofstream fout; 			// fout an ofstream object

// 3、将这种对象与特定的文件关联起来:
outFile.open("fish.txt"); // outFile used to write to the fish.txt file
                          // 打开已有的文件,以接受输出时,默认将它其长度截短为零,因此原来的内容将丢失。
char filename[50];
cin >> filename; 		// user specifies a name
fout.open(filename); 	// fout used to read specified file

// 4、使用cout那样使用该ofstream对象:
double wt = 125.8;
outFile << wt; 			// write a number to fish.txt
char line[81] = "Objects are closer than they appear.";
fout << line << endl; 	// write a line of text

// 5、使用close()关闭文件:
outFile.close();		// done with file
fout.close();			// 方法close( )不需要使用文件名作为参数,这是因为outFile已经同特定的文件关联起来。
                        // 如果您忘记关闭文件,程序正常终止时将自动关闭它。
// 文件输出

#include <iostream> // ostream->cout    istream->cin
#include <fstream>  // ofstream         ifstream

int main(void)
{
    using namespace std;

    char automoblie[50];
    int year;
    double a_price, d_price;

    ofstream outFile;   // 2、创建对象
    outFile.open("carinfo.txt");    // 3、关联文件,创建文件

    cout << "Enter the make and model of automobile:";
    cin.getline(automoblie, 50);
    cout << "Enter the model year:";
    cin >> year;
    cout << "Enter the origional asking price:";
    cin >> a_price;
    d_price = 0.913 * a_price;

    cout << fixed;        // 不要以科学计数法显示
    cout.precision(2);    // 显示输出精度到小数点后两位
    cout.setf(ios_base::showpoint); // 即使小数点后面为零也显示出来
    cout << "Make and model:" << automoblie << endl;    // 屏幕输出是使用cout的结果
    cout << "Year: " << year << endl;
    cout << "Was asking $" << a_price << endl;
    cout << "Now asking $" << d_price << endl;

    outFile << fixed;
    outFile.precision(2);
    outFile.setf(ios_base::showpoint);
    outFile << "Make and model: " << automoblie << endl;    // 和 cout 使用方法一样,在文本输出
    outFile << "Year: " << year << endl;    // outFile将cout显示到屏幕上的内容写入到了文件 carinfo.txt中
    outFile << "Was asking $" << a_price << endl;
    outFile << "Now asking $" << d_price << endl;

    outFile.close();    // 方法close( )不需要使用文件名作为参数,这是因为outFile已经同特定的文件关联起来。
                        // 如果您忘记关闭文件,程序正常终止时将自动关闭它。

    return 0;
}

out:
image.png

6.10.4 文件输入/读取文件

  1. 必须包含头文件fstream。
  2. 头文件fstream定义了一个用于处理输入的ifstream类。
  3. 需要声明一个或多个ifstream变量(对象),并以自己喜欢的方式 对其进行命名,条件是遵守常用的命名规则。
  4. 必须指明名称空间std;例如,为引用元素ifstream,必须使用编译 指令using或前缀std::。
  5. 需要将ifstream对象与文件关联起来。为此,方法之一是使用open( ) 方法。
  6. 使用完文件后,应使用close( )方法将其关闭。
  7. 可结合使用ifstream对象和运算符>>来读取各种类型的数据。
  8. 可以使用ifstream对象和get( )方法来读取一个字符,使用ifstream对 象和getline( )来读取一行字符。
  9. 可以结合使用ifstream和eof( )、fail( )等方法来判断输入是否成功。
  10. ifstream对象本身被用作测试条件时,如果最后一个读取操作成 功,它将被转换为布尔值true,否则被转换为false。

文件输入的主要步骤:

// 1、包含头文件fstream
#include <iostream> 	// ostream->cout    istream->cin
#include <fstream>  	// ofstream         ifstream
#include <cstdlib> 		// support for exit()

// 2、声明ifstream对象,为其命名
ifstream inFile; // inFile an ifstream object
ifstream fin; // fin an ifstream object

// 3、将ifstream对象与特定的文件关联起来
inFile.open("bowling.txt"); // inFile used to read bowling.txt file
char filename[50];			
cin.getline(filename, 50); 	
fin.open(filename); 		// fin used to read specified file
// 方法2-1:string filename;
// 方法2-2:getline(cin, filename);

// 4、检查文件是否被成功打开的首先方法是使用方法is_open( )
inFile.open("bowling.txt");
if (!inFile.is_open())
{
exit(EXIT_FAILURE);
}
// 如果文件被成功地打开,方法is_open( )将返回true;因此如果文件 没有被打开,表达式!inFile.isopen( )将为true。
// 函数exit( )的原型是在头 文件cstdlib中定义的,在该头文件中,还定义了一个用于同操作系统通 信的参数值EXIT_FAILURE。函数exit( )终止程序。

// 5、使用cin那样使用ifstream对象
double wt;
inFile >> wt; // read a number from bowling.txt
char line[81];
fin.getline(line, 81); // read a line of text

// 6、使用close()关闭文件:
inFile.close();

检查文件是否被成功打开:is_open( )

如果试图打开一个不存在的文件用于输入,情况将如何呢?这种错 误将导致后面使用ifstream对象进行输入时失败。
检查文件是否被成功打开的首先方法是使用方法is_open( ):

  1. 如果文件被成功地打开,方法is_open( )将返回true;因此如果文件 没有被打开,表达式!inFile.isopen( )将为true。
  2. 函数exit( )的原型是在头 文件cstdlib中定义的,在该头文件中,还定义了一个用于同操作系统通 信的参数值EXIT_FAILURE。函数exit( )终止程序。
inFile.open("bowling.txt");
if (!inFile.is_open())
{
	exit(EXIT_FAILURE);
}

检查文件是否出错

  1. 首先,程序读取文件时不应超过EOF。如果最后一次读取数据时遇到EOF,方法eof( )将返回true。
  2. 如果最后一 次读取操作中发生了类型不匹配的情况,方法fail( )将返回true(如果遇到了EOF,该方法也将返回true)
  3. 文件受损或硬件故障,bad( )将返回true。
if (inFile.eof())
    cout << "End of file reached.\n";
else if (inFile.fail())
    cout << "Input terminated by data mismatch.\n";
else
    cout << "Input terminated for unknown reason.\n";
  1. good( )方法,该方法在没有发生任何错误时返回true:
while (inFile.good()) // while input good and not at EOF
{
...
}

// 表达式inFile >> value的 结果为inFile,而在需要一个bool值的情况下,inFile的结果为 inFile.good( ),即true或false。
inFile >> value; // get first value
while (inFile.good()) // while input good and not at EOF
{
// loop body goes here
inFile >> value; // get next value
}

// 将两条输入语句用一条用作循环测试的输入语句代替。
// 要计算表达 式inFile >> value的值,程序必须首先试图将一个数字读取到value中。
while (inFile >> value) // read and test for success
{
// loop body goes here
// omit end-of-loop input
}
// 打开用户指定的文件,读取其中的数字,然后指出文件中包含多少个值以及它们的和与平均值。
// 首先必须创建一个包含数字的文本文件。
// sumafile.cpp -- functions with an array argument

#include <iostream>
#include <fstream>      // file I/O support
#include <cstdlib>      // support for exit()
const int SIZE = 100;
int main()
{
    using namespace std;
    char filename[SIZE];
    ifstream inFile;        // object for handling file input
    cout << "Enter name of data file:";
    cin.getline(filename, SIZE);    // 通常,除非在输入的文件名中包含路径,否则程序将在可执行文件所属的文件夹中查找。
    inFile.open(filename);  // associate inFile with a file
    if (!inFile.is_open())  // failed to open file
    {
        cout << "Could not open the file " << filename << endl;
        cout << "Program terminating.\n";
        exit(EXIT_FAILURE);
    }
    double value;
    double sum = 0.0;
    int count = 0;          // number of items read
    inFile >> value;        // get first value
    while (inFile.good())   // while input good and not at EOF
    {
        ++count;            // one more item read
        sum += value;       // calculate running total
        inFile >> value;    // get next value
    }
    if (inFile.eof())
        cout << "End of file reached.\n";
    else if (inFile.fail())
        cout << "Input terminated by data mismatch.\n";
    else
        cout << "Input terminated for unknown reason.\n";
    if (count == 0)
        cout << "No data processed.\n";
    else
    {
        cout << "Items read: " << count << endl;
        cout << "Sum: " << sum << endl;
        cout << "Average: " << sum / count << endl;
    }
    inFile.close(); 		// finished with the file
    return 0;
}

image.png
out:
image.png

6.11 总结

  1. C++提供了if语句、if else语句和switch语句来管理选项。if语句使程序有条件地执行语句或语句块,也就是说,如果满足特定的条件,程序将执行特定的语句或语句块。if else语句程序选择执行两个语句或语句块之一。可以在这条语句后再加上if else,以提供一系列的选项。switch语句引导程序执行一系列选项之一。
  2. C++还提供了帮助决策的运算符。第5章讨论了关系表达式,这种表达式对两个值进行比较。if和if else语句通常使用关系表达式作为测试 条件。通过使用逻辑运算符(&&、||和!),可以组合或修改关系表达式,创建更细致的测试。条件运算符(?:)提供了一种选择两个值之一 的简洁方式。
  3. cctype字符函数库提供了一组方便的、功能强大的工具,可用于分析字符输入。
  4. 对于文件I/O来说,循环和选择语句是很有用的工具;文件I/O与控制台I/O极其相似。声明 ifstream 和 ofstream 对象,并将它们同文件关联起来后,便可以像使用cin和cout那样使用这些对象。
  5. 使用循环和决策语句,便可以编写有趣的、智能的、功能强大的程序。

6.12 复习题

5、在C++中,!!x 是否与 x 相同呢?
不一定。例如:如果 x=10,则 !x=0,!!x=1。然而,如果 x 为bool变量,则 !!x 为 x。

8、与使用数字相比,使用字符(如a和c)表示菜单选项和case标签有何优点呢?
如果使用整数标签,而用户输入了非整数(如 q),则程序将因为整数输入不能处理字符而挂起。但是,如果使用字符标签,而用户输入了整数(如5),则字符输入将5作为字符处理。然后,switch语句的default部分将提示输入另一个字符。

6.13 编程练习

// 2
// 编写一个程序,最多将10个donation值读入到一个double数组中(如果您愿意,也可使用模板类array)。
// 程序遇到非数字输入时将结束输入,并报告这些数字的平均值以及数组中有多少个数字大于平均值。

#include <iostream>
#include <array>

const int ArSize = 10;

int main(void)
{
    using namespace std;

    array<double, ArSize> donation;
    double sum = 0.0, average = 0.0;
    int count = 0, bigger = 0;

    cout << "Please enter the double numerial:";

    // ***判断值读入到一个double数组中***
    while ((cin >> donation[count])
    {
        if (++count == ArSize)
            break;
        cout << "Please enter the double numerial:";
    }

    for (int i=0; i < count; i++)
        sum += donation[i];

    average = sum/count;

    for (int i=0; i < count; i++)
        if (donation[i] > average)
            bigger++;

    cout << average << " number's average." << endl;
    cout << bigger << " numbers are bigger than average." << endl;

    return 0;
}

           
// 3
// 编写一个菜单驱动程序的雏形。该程序显示一个提供4个选项的菜单——每个选项用一个字母标记。
// 如果用户使用有效选项之外的字母 进行响应,程序将提示用户输入一个有效的字母,直到用户这样做为止。
// 然后,该程序使用一条switch语句,根据用户的选择执行一个简单操作。

#include <iostream>

using namespace std;

void menu(void);

int main(void)
{
    menu();
    char ch;
    cin.get(ch);

    while (ch != 'c' && ch != 'p' && ch != 't' && ch != 'g')
    {
        cin.get();
        cout << "Please enter c, p, t or g :";
        cin.get(ch);
    }

    switch (ch)
    {
        case 'c' : cout << "cccccccc\n";break;
        case 'p' : cout << "pppppppp\n";break;
        case 't' : cout << "tttttttt\n";break;
        case 'g' : cout << "gggggggg\n";break;
    }

    return 0;
}

void menu(void)
{
    cout << "Please enter one of the following choices:\n"
            "c) carnivore \tp) pianist\n"
            "t) tree      \tg) game\n";
}
           

// 4
// 加入Benevolent Order of Programmer后,在BOP大会上,人们便可以通过加入者的真实姓名、头衔或秘密BOP姓名来了解他(她)。
// 请编写一个程序,可以使用真实姓名、头衔、秘密姓名或成员偏好来列出成员。编写该程序时,请使用下面的结构:

#include <iostream>

void menu(void);
void display(char ch);

using namespace std;

const int strsize = 40;
const int usersize = 5;

// Benevolent Order of Programmers name structure
struct bop {
    char fullname[strsize];     // real name
    char title[strsize];        // job title
    char bopname[strsize];      // secret BOP name
    int preference;             // 0 = fullname, 1 = title, 2 = bopname
};

bop user[usersize] =
        {
                {"Wimp Macho", "AA", "AAA", 0},
                {"Raki Rhodes", "BB", "BBB", 1},
                {"Celia Laiter", "CC", "CCC", 2},
                {"Hoppy Hipman", "DD", "DDD", 0},
                {"Pat Hand", "EE", "EEE", 1}
        };

int main(void)
{
    menu();
    char input;
    cin.get(input);
    while (input != 'q')
    {
        display(input);
        cin.get();  // 消耗回车
        cin.get(input);
    }
    cout << "Bye!" << endl;

    return 0;
}

void menu(void)
{
    cout << "a. display by name    \tb. display by title\n"
            "c. display by bopname \td. display by preference\n"
            "q. quit\n";
}

void display(char ch)
{
    switch (ch)
    {
        case 'a' :
            for (int i=0; i<usersize; i++)
                cout << user[i].fullname << endl;
            break;
        case 'b' :
            for (int i=0; i<usersize; i++)
                cout << user[i].title << endl;
            break;
        case 'c' :
            for (int i=0; i<usersize; i++)
                cout << user[i].bopname << endl;
            break;
        case 'd' :
            for (int i=0; i<usersize; i++)
            {
                if (user[i].preference==0)
                    cout << user[i].fullname << endl;
                else if (user[i].preference==1)
                    cout << user[i].title << endl;
                else if (user[i].preference==2)
                    cout << user[i].bopname << endl;
            }
            break;
        default :
            if (ch == 'a' || ch == 'b' || ch == 'c' || ch == 'd')
                cout << "Next choice:";
            else
                cout << "Please enter character a, b, c, d or q :";
    }
}
           
// 5000 tvarps:不收税
// 5001~15000 tvarps:10%
// 15001~35000 tvarps:15%
// 35000 tvarps以上:20%
// 例如,收入为38000 tvarps时,所得税为5000 0.00 + 10000 0.10 + 20000 0.15 + 3000 0.20,即4600 tvarps。
// 请编写一个程序,使用循环来 要求用户输入收入,并报告所得税。当用户输入负数或非数字时,循环将结束。

#include <iostream>

using namespace std;

int main(void)
{
    float tvarps, tax;
    cout << "Please enter tvarps:";
    while ((cin >> tvarps) && (tvarps >= 0))
    {
        if (tvarps <= 5000)
            tax = 0;
        else if (tvarps > 5000 && tvarps <= 15000)
            tax = (tvarps-5000) * 0.1;
        else if (tvarps > 15000 && tvarps <= 35000)
            tax = 10000 * 0.10 + (tvarps-15000) * 0.15;
        else
            tax = 10000 * 0.10 + 20000 * 0.15 + (tvarps-35000) * 0.2;
        cout << tax << endl;
        cout << tvarps-tax << endl;
    }

    return 0;
}
// 6
// 编写一个程序,记录捐助给“维护合法权利团体”的资金。
// 该程序要求用户输入捐献者数目,然后要求用户输入每一个捐献者的姓名和款项。
// 这些信息被储存在一个动态分配的结构数组中。每个结构有两个成员:用来储存姓名的字符数组(或string对象)和用来存储款项的 double成员。
// 读取所有的数据后,程序将显示所有捐款超过10000的捐款者的姓名及其捐款数额。该列表前应包含一个标题,指出下面的捐款者是重要捐款人(Grand Patrons)。
// 然后,程序将列出其他的捐款者,该列表要以Patrons开头。
// 如果某种类别没有捐款者,则程序将打印单词“none”。该程序只显示这两种类别,而不进行排序。

#include <iostream>
#include <cstring>

using namespace std;

const int namesize = 20;

struct donation
{
    string name;
    double money;
};

int main(void)
{
    int number = 0;
    cout << "Please enter number:";
    cin >> number;
    cin.get();

    donation *ps = new donation[namesize];
    for (int i=0; i < number; i++)
    {
        cout << "donor #" << i+1 << ": \n";
        cout << "Enter name :";
        getline(cin, ps[i].name);
        cout << "Enter money :";
        cin >> ps[i].money;
        cin.get();
    }

    bool empty = true;

    cout << "Grand Patrons :" << endl;
    for (int i=0; i < number; i++)
    {
        if (ps[i].money > 10000)
        {
            cout << ps[i].name << "\t" << ps[i].money << endl;
            empty = false;
        }
    }
    if (empty == true)
        cout << "None.\n";

    empty = true;
    cout << "Patrons :" << endl;
    for (int i=0; i < number; i++)
    {
        if (ps[i].money <= 10000)
        {
            cout << ps[i].name << "\t" << ps[i].money << endl;
            empty = false;
        }
    }
    if (empty == true)
        cout << "None.\n";

    delete [] ps;

    return 0;
}
// 7
// 编写一个程序,它每次读取一个单词,直到用户只输入q。
// 然后,该程序指出有多少个单词以元音打头,有多少个单词以辅音打头,还有多少个单词不属于这两类。
// 为此,方法之一是,使用isalpha( )来区分以字母和其他字符打头的单词,
// 然后对于通过了isalpha( )测试的单词,使用if或switch语句来确定哪些以元音打头。

#include <iostream>
#include <cctype>
#include <cstring>

int main(void)
{
    using namespace std;

    int vowels = 0, consonants = 0, others = 0;
    string words;
    cout << "Enter words (q to quit):";

    while ((cin >> words) && (words != "q"))    // string 用双引号
    {
        if (isalpha(words[0]))
        {
            switch (words[0])   // char 用单引号
            {
                case 'a' : case 'e' : case 'i' : case 'o' : case 'u' :
                case 'A' : case 'E' : case 'I' : case 'O' : case 'U' : vowels++;
                default : consonants++;
            }
        }
        else
            others++;
    }

    cout << vowels << " words beginning with vowels" << endl;
    cout << consonants << " words beginning with consonants\n";
    cout << others << " others\n";

    return 0;
}
// 8
// 编写一个程序,它打开一个文件文件,逐个字符地读取该文件,直到到达文件末尾,然后指出该文件中包含多少个字符。

#include <iostream> 	// ostream->cout    istream->cin
#include <fstream>  	// ofstream         ifstream
#include <cstdlib> 		// support for exit()

int main(void)
{
    using namespace std;

    char ch;
    int count;
    char filename[50];

    ifstream inFile;            // inFile an ifstream object

    cout << "Please enter the file name:";
    cin.getline(filename, 50);      // user specifies a name
    inFile.open(filename);      // inFile used to read specified file

    if (!inFile.is_open())      // 检查文件是否被成功打开的首先方法是使用方法is_open( )
    {
        cout << "Filed to open the file." << endl;
        exit(EXIT_FAILURE);
    }

    while (!inFile.eof())
    {
        inFile >> ch;
        count++;
    }

    cout << filename << " havs " << count << " characters." << endl;

    inFile.close();

    return 0;
}
// 完成编程练习6,但从文件中读取所需的信息。该文件的第一项 应为捐款人数,余下的内容应为成对的行。
// 在每一对中,第一行为捐款 人姓名,第二行为捐款数额。即该文件类似于下面:

#include <fstream>
#include <iostream>
#include <cstring>
#include <cstdlib>      // support for exit()

using namespace std;

const int namesize = 20;

struct donation
{
    string name;
    double money;
};

int main(void)
{
    ifstream inFile;

    char filename[50];
    cout << "Please enter the file name:";
    cin.getline(filename, 50);  // user specifies a name
    inFile.open(filename);      // inFile used to read specified file

    if (!inFile.is_open())      // 检查文件是否被成功打开的首先方法是使用方法is_open( )
    {
        cout << "Filed to open the file." << endl;
        exit(EXIT_FAILURE);
    }

    int number = 0;
    inFile >> number;
    if (number <= 0)
        exit(EXIT_FAILURE);
    cout << "number:" << number << endl;
    inFile.get();

    donation *ps = new donation[namesize];

    int i = 0;
    while ((!inFile.eof()) && (i < number))
    {
        cout << "donor #" << i+1 << ": \n";
        getline(inFile, ps[i].name);
        cout << "Read name:" << ps[i].name << endl;
        inFile >> ps[i].money;
        cout << "Read money:" << ps[i].money << endl;
        i++;
        inFile.get();   // 再读取一次然后,判断是否到文件末尾
    }

    bool empty = true;

    cout << "Grand Patrons :" << endl;
    for (int i=0; i < number; i++)
    {
        if (ps[i].money > 10000)
        {
            cout << ps[i].name << "\t" << ps[i].money << endl;
            empty = false;
        }
    }
    if (empty == true)
        cout << "None.\n";

    empty = true;
    cout << "Patrons :" << endl;
    for (int i=0; i < number; i++)
    {
        if (ps[i].money <= 10000)
        {
            cout << ps[i].name << "\t" << ps[i].money << endl;
            empty = false;
        }
    }
    if (empty == true)
        cout << "None.\n";

    delete [] ps;

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值