
本章内容包括:
• if语句。
• ifelse语句。
• 逻辑运算符:&&、||和!。
• cctype字符函数库。
• 条件运算符:?:。
• switch语句。
• continue和break语句。
• 读取数字的循环。
• 基本文件输入/输出。
字符函数库cctype:
#include <iostream>
#include <cctype> // prototypes for character functions
int main(){
using namespace std;
cout << "Enter text for analysis, and type @"
" to terminate input.\n";
char ch;
int whitespace = 0;
int digits = 0;
int chars = 0;
int punct = 0;
int others = 0;
cin.get(ch);
while (ch != '@') { // test for sentinel
if (isalpha(ch)) // is it an alphabetic character?
chars++;
else if (isspace(ch)) // is it a whitespace character?
whitespace++;
else if (isdigit(ch)) // is it a digit?
digits++;
else if (ispunct(ch)) // is it punctuation(标点)?
punct++;
else
others++;
cin.get(ch); // get next character
}
cout << chars << " letters, "
<< whitespace << " whitespace, "
<< digits << " digits, "
<< punct << " punctuations, "
<< others << " others.\n";
return 0;
}

| 函数名 | 返回值 |
| isalnum() |
如果参数是字母数字,即字母或数字,该函数返回true |
| isalpha() |
如果参数是字母,该函数返回true |
| iscntrl() |
如果参数是控制字符,该函数返回true |
| isdigit() |
如果参数是数字(0~9),该函数返回true |
| isgraph() |
如果参数是除空格之外的打印字符,该函数返回true |
| islower() |
如果参数是小写字母,该函数返回true |
| isprint() |
如果参数是打印字符(包括空格),该函数返回true |
| ispunct() |
如果参数是标点符号,该函数返回true |
| isspace() |
如果参数是标准空白字符,如空格、进纸、换行符、回车、水平制表符或者垂直制表符,该函数返回true |
| isupper() |
如果参数是大写字母,该函数返回true |
| isxdigit() |
如果参数是十六进制数字,即0~9、a~f或A~F,该函数返回true |
| tolower() |
如果参数是大写字符,则返回其小写,否则返回该参数 |
| toupper() |
如果参数是小写字符,则返回其大写,否则返回该参数 |
将枚举量用作标签:
#include <iostream>
// create named constants for 0 - 6
enum { red, orange, yellow, green, blue, violet, indigo };
int main() {
using namespace std;
cout << "Enter color code (0-6): ";
int code;
cin >> code;
while (code >= red && code <= indigo) {
switch (code) {
case red: cout << "Her lips were red.\n"; break;
case orange: cout << "Her hair was orange.\n"; break;
case yellow: cout << "Her shoes were yellow.\n"; break;
case green: cout << "Her nails were green.\n"; break;
case blue: cout << "Her sweatsuit was blue.\n"; break;
case violet: cout << "Her eyes were violet.\n"; break;
case indigo: cout << "Her mood was indigo.\n"; break;
}
cout << "Enter color code (0-6): ";
cin >> code;
}
cout << "Bye\n";
return 0;
}
Enter color code (0-6): |3
Her nails were green.
Enter color code (0-6): |5
Her eyes were violet.
Enter color code (0-6): |2
Her shoes were yellow.
Enter color code (0-6): |8
Bye
数字填满了,就循环结束的程序:
#include <iostream>
const int Max = 5;
int main() {
using namespace std;
int golf[Max];
cout << "Please enter your golf scores.\n";
cout << "You must enter " << Max << " rounds.\n";
int i;
for (i = 0; i < Max; i++) {
cout << "round #" << i + 1 << ": ";
while (!(cin >> golf[i])) { /* ← 专用于处理输入格式错误,注意前面!号 */
cin.clear(); /* ← 重置输入流 */
while (cin.get() != '\n')
continue; // get rid of bad input
cout << "Please enter a number: ";
}
}
double total = 0.0;
for (i = 0; i < Max; i++)
total += golf[i];
cout << total / Max << " = average score "
<< Max << " rounds\n";
return 0;
}
Please enter your golf scores.
You must enter 5 rounds.
round #1: |88
round #2: |87
round #3: |must i?
Please enter a number: |103
round #4: |94
round #5: |86
91.6 = average score 5 rounds
●关于cin.clear()与标志:
void clear(iostate flags = goodbit);
函数clear()清除与当前流相关联的标志。默认标志是goodbit,clear()清除所有标志,否则只有指定的标志被清除。
C++为标准输入和输出定义了一些格式标志, 它可以通过flags(), setf(), 和unsetf()三个函数来控制。
例如, cout.setf(ios::left); 对所有指向cout的输出进行左对齐调整。
程序中有段错误处理的关键代码:
while (!(cin >> golf[i])) {
cin.clear(); // reset input
while (cin.get() != '\n')
continue; // get rid of bad input
cout << "Please enter a number: ";
}
如果用户输入88,则cin表达式将为true,因此将一个值放到数组中;而表达式!(cin >> golf [i])为false,因此结束内部循环。然而,如果用户输入must i?,则cin表达式将为false,因此不会将任何值放到数组中;而表达式!(cin >> golf [i])将为true,因此进入内部的while循环。该循环的第一条语句使用clear()方法重置输入,如果省略这条语句,cin==false时程序将拒绝继续读取输入。接下来,程序在while循环中使用cin.get()来读取行尾之前的所有输入,从而删除这一行中的错误输入。另一种方法是读取到下一个空白字符,这样将每次删除一个单词,而不是一次删除整行。最后,程序告诉用户,应输入一个数字。
简单的文件输入/输出:
介绍一下文本I/O的概念。使用cin进行输入时,程序将输入视为一系列的字节,其中每个字节都被解释为字符编码。不管目标数据类型是什么,输入一开始都是字符数据——文本数据。然后,cin对象负责将文本转换为其他类型。
假设有如下示例输入行:
38.5 19.2
➀首先,来看使用char数据类型的情况:
char ch;
cin >> ch;
输入行中的第一个字符被赋给ch。在这里,第一个字符是数字3,其字符编码(二进制)被存储在变量ch中。输入和目标变量都是字符,因此不需要进行转换。注意,这里存储的不是数值3,而是字符3的编码。执行上述输入语句后,输入队列中的下一个字符为字符8,下一个输入操作将对其进行处理。
➁接下来看看int类型:
int n;
cin >> n;
在这种情况下,cin将不断读取,直到遇到非数字字符。如果输入的是38.5,也就是说,它将读取3和8,这样句点将成为输入队列中的下一个字符。cin通过计算发现,这两个字符对应数值38,因此将38的二进制编码复制到变量n中。
➂接下来看看double类型:
double x;
cin >> x;
在这种情况下,cin将不断读取,直到遇到第一个不属于浮点数的字符。也就是说,cin读取3、8、句点和5,使得空格成为输入队列中的下一个字符。cin通过计算发现,这四个字符对应于数值38.5,因此将38.5的二进制编码(浮点格式)复制到变量x中。
➃接下来看看char数组的情况:
char word[50];
cin >> word;
在这种情况下,cin将不断读取,直到遇到空白字符。也就是说,它读取3、8、句点和5,使得空格成为输入队列中的下一个字符。然后,cin将这4个字符的字符编码存储到数组word中,并在末尾加上一个空字符'\0'。这里不需要进行任何转换。
➄最后,来看一下另一种使用char数组来存储输入的情况:
char word[50];
cin.getline(word, 50);
在这种情况下,cin将不断读取,直到遇到换行符(示例输入行少于50个字符)。所有字符都将被存储到数组word中,并在末尾加上一个空字符。换行符被丢弃,输入队列中的下一个字符是下一行中的第一个字符。这里不需要进行任何转换。
这里的要点是,输入一开始为文本。因此,控制台输入的文件版本是文本文件,即每个字节都存储了一个字符编码的文件。并非所有的文件都是文本文件,例如,数据库和电子表格以数值格式(即二进制整数或浮点格式)来存储数值数据。另外,字处理文件中可能包含文本信息,但也可能包含用于描述格式、字体、打印机等的非文本数据。
本章讨论的文件I/O相当于控制台I/O,因此仅适用于文本文件。要创建文本文件,用于提供输入,可使用文本编译器,如DOS中的EDIT、Windows中的“记事本”和UNIX/Linux系统中的vi或emacs。
写入到文本文件中:
使用文件输出的主要步骤如下。
1.包含头文件<fstream>
2.创建一个ofstream对象
3.将该ofstream对象同一个文件关联起来
4.就像使用cout那样使用该ofstream对象
#include <fstream> // for file I/O
#include <iostream>
using namespace std;
int main() {
char automobile[50];
int year;
double a_price;
double d_price;
ofstream outFile; // create object for output
outFile.open("carinfo.txt"); // associate with a file
cout << "Enter the make and model of automobile: ";
cin.getline(automobile, 50);
cout << "Enter the model year: ";
cin >> year;
cout << "Enter the original asking price: ";
cin >> a_price;
d_price = 0.913 * a_price;
// display information on screen with cout
cout << fixed;
cout.precision(2);
cout.setf(ios_base::showpoint);
cout << "Make and model: " << automobile << endl;
cout << "Year: " << year << endl;
cout << "Was asking $" << a_price << endl;
cout << "Now asking $" << d_price << endl;
// now do exact same things using outFile instead of cout
outFile << fixed;
outFile.precision(2);
outFile.setf(ios_base::showpoint);
outFile << "Make and model: " << automobile << endl;
outFile << "Year: " << year << endl;
outFile << "Was asking $" << a_price << endl;
outFile << "Now asking $" << d_price << endl;
outFile.close(); // done with file
return 0;
}
Enter the make and model of automobile: |Flitz Perky
Enter the model year: |2009
Enter the original asking price: |13500
Make and model: Flitz Perky
Year: 2009
Was asking $13500.00
Now asking $12325.50
该程序的最后一部分与cout部分相同,只是将cout替换为outFile而已。可以看到在可执行文件目录生成了一个名为carinfo.txt文件(根据编译器的配置,该文件也可能位于其他文件夹):

outFile可使用cout可使用的任何方法。还可以使用各种格式化方法,如setf( )和precision( )。这些方法只影响调用它们的对象。
该程序运行之前,文件carinfo.txt并不存在。在这种情况下,方法open( )将新建一个名为carinfo.txt的文件。如果在此运行该程序,文件carinfo.txt将存在,此时情况将如何呢?默认情况下,open()将首先截断该文件,即将其长度截短到零——丢其原有的内容,然后将新的输出加入到该文件中。
读取文本文件:

#include <cstdlib> // support for exit()
#include <fstream> // file I/O support
#include <iostream>
const int SIZE = 60;
int main() {
using namespace std;
char filename[SIZE];
ifstream inFile;
cout << "Enter name of data file: ";
cin.getline(filename, SIZE);
inFile.open(filename);
if (!inFile.is_open()) { // failed to open file
cout << "Could not open the file " << filename << endl;
cout << "Program terminating.\n";
// cin.get(); // keep window open
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;
sum += value;
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;
}
首先在可执行目录下新建一个名为scores.txt的文件,内容如下:

Enter name of data file: |scores.txt
End of file reached.
Items read: 12
Sum: 204.5
Average: 17.0417
注:如果在scores.txt文件最后一行不输入[Enter]一个换行符,“17.5”这个数不会被统计和计算,因为没有最后的换行符时读到“17.5”就到文件结尾了inFile.good()==EOF。如果首行“18”后面有N个空格,输出也是如上;如果“18”后面空格用“#”号代替,输出结果如下:
Enter name of data file: |scores.txt
Input terminated by data mismatch.
Items read: 1
Sum: 18
Average: 18
所以,对于ifstream>>value空格和回车换行符是分隔符,读取时会直接忽略掉。
需要特别注意的是文件读取循环的正确设计。读取文件时,有几点需要检查。首先,程序读取文件时不应超过EOF。如果最后一次读取数据时遇到EOF,方法eof()将返回true。其次,程序可能遇到类型不匹配的情况。例如,程序清单中期望文件中只包含数字。如果最后一次读取操作中发生了类型不匹配的情况,方法fail()将返回true(如果遇到了EOF,该方法也将返回true)。最后,可能出现意外的问题,如文件受损或硬件故障。如果最后一次读取文件时发生了这样的问题,方法bad()将返回true。不要分别检查这些情况,一种更简单的方法是使用good()方法,该方法在没有发生任何错误时返回true,上面程序就是这样做的。
由于eof()只能判断是否到达EOF,而fail()可用于检查EOF和类型不匹配,因此上述代码首先判断是否到达EOF。这样,如果执行到了else if测试,便可排除EOF,因此,如果fail()返回true,便可断定导致循环终止的原因是类型不匹配。
其实,表达式inFile >> value的结果为inFile,而在需要一个bool值的情况下,inFile的结果为inFile.good( ),即true或false。
因此,可以对代码进行精简,将两条输入语句用一条用作循环测试的输入语句代替:
while (inFile >> value) {
...
}
C++控制流与文件I/O详解
本文深入探讨C++中的控制流语句,包括条件语句、循环语句及逻辑运算符的使用,同时详述了字符函数库cctype的函数与应用。此外,文章还介绍了C++的基本文件输入输出操作,涵盖了文件打开、关闭、读取和写入的详细过程。
2266

被折叠的 条评论
为什么被折叠?



