第六天(分支语句和逻辑操作符)

本文探讨了C++中的输入输出技术,包括文件I/O的基本操作及异常处理方法。详细解析了cin与cout的高级用法,如数据验证、错误处理及精度控制。同时介绍了如何实现文件的读写,并提供了完整的示例代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    今天时间上传时间有点晚,原因是理解书中其中程序费了不小时间。这一章后面又是关于文件的简单输出输入,学C的时候这一部分没多大学,所以是完全是陌生的,也费了点时间。


2011-10-04(Branching Statements and Logical Operations)
1、value == variable和variable == value。以前看到过在优快云论坛java板块上有个帖子问这两种形式有什么区别。理论上,二者没任何区别,前提是你书写正确。假设把“==”误写成“=”,当然这个假设有点无理:在写错的情况下,什么事情都有可能发生,能把所有的后果都讨论完,然后说有什么区别?好了,再来看这个假设,前者value = variable编译器是报错的,后者variable = value返回的是等号左边的值。C++中,如果value等于零,恒为false;如果value不等于零,恒为true,这往往与程序员的愿意相反,比如:

int num = 3;
if(num == 4)cout << "true";
else cout << "false";
“==”情况下,正常。而如果写成“=”,那么,无论num等于什么,总是打印true,而编译器是不会报错的。所以在C++环境下,还是采用value == variable的形式,为自己可能的粗心提个醒。java环境下,两者形式皆好,根据习惯,因为if语句里面不允许除boolean型数据外的其他类型。
2、逻辑操作符的一些事项。
OR和AND运算优先级都低于关系操作符;
②NOT优先级高于所有关系操作符合算术操作符;
③AND优先级高于OR。不过为了清晰明了,必要的时候加上括号;
④从左往右计算逻辑表达式,如此某些情况下可以减少运算次数;
⑤在有头文件
ciso646 情况下,可用 and or not 代替 &&、|| !
3、输入异常处理。试想,如果一个程序要你输入整型,你却输入了一个字符,会发生错误。如果要避免这种情况,一般的做法是将输入的数据进行判断,确定为所要类型后再使用。这个方法有两个问题:①判断是有判断的对象,这个对象就是储存了数据的变量。好,既然可能是出现多种类型,程序应该拿什么类型的变量接收数据以适应所以可能的类型呢?②判断的准则不清。也就是说:
typeName temp;        //What is the typeName?
cin >> temp;
if(test-expression)   //What is the test-expression
{    /*show error info */}
幸运的是,以 cin 为中心的输入函数在输入数据不正确的情况下,可以返回一个 bool 型数据:输入数据格式正确,可返回 true ,否则为 false
I、输入类型测试。现已学的的输入函数有:

                         cin >> variable;          //接收各种类型数据
                         cin.get()或cin.get(char); //接收单个字符、字符串
                         cin.getline();            //接收字符串
                         getline(cin,string);      //string对象接收字符串
可以借助下列测试程序测试:
#include <iostream>

int main()
{
    using namespace std;
    int a ; //a可以是任意类型 
    if(!(cin >> a))
        cout << "Wrong data\n";
    else
        cout << "Right data: " << a << endl;
    return 0;
}
下面是测试结果(约定:( int,float )=1表示,a的类型是,float是输入类型或者是具体数据,1表示输入数据正确,0表示不正确):
①如果a是整型或浮点,只要输入数据不是字符(非数字类型字符)、字符串(没有数字前缀)、EOF或超过该类型可储存的最大值,打印Right data。如(
int, char )=0,( int, string )=0,( int, "56aba" )=1,( int, double )=1,( unsigned int, -2 )=1,后面两种情况数据会丢失:前者,小数部分被截去;后者, a = INT_MAX - 2 - 1
②如果a是
char、string或char[] ,除EOF外的任何数据都打印Right data。对于 char 型,总是取输入数据的头个字符。如( char, 5.6 ),a='5';( char, "abc" ),a='a';
③如表:
函数\类型
int
float
char
string
EOF(CTRL+Z)
cin.get()
Right data
Right data
Right data
Right data
Wrong data
cin.getline()
Right data
Right data
Right data
Right data
Wrong data
getline(cin,string)
Right data
Right data
Right data
Right data
Wrong data
结果基本上可以猜到,因为任何数据都可以看作字符串。比较特别的是EOF,任何输入函数都会显示数据错误。
上述结论中用得最多的是:(
int, char )和( int, int )之间的关系,以及(anyType, EOF)=0。
II、实例(来自教材)。功能是输入5个
int 值,并输入平均值。如果输入的有字符串,即要求重新输入。
#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');
            cout << "Please enter a 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;
}
一次输入输出如下:
                   Please enter your golf scores.
                   You must enter 5 rounds.
                   round #1: 89
                   round #2: 90
                   round #3: 76
                   round #4: right?
                   Please enter a number: 90
                   round #5: 80
                   85 = average score 5 rounds
由于 while(!(cin >> golf[i])) 中的条件语句是顺序点,必须完成条件语句中的所有表达式才能进行判断。在输入 int 型的情况下, !(cin >> golf[i])=false ,循环不执行。输入的是字符串(或者字符)执行循环,循环的第一条语句是 cin.clear() ,其作用是恢复 cin 正常输入功能,即 cin 在读取输入流中非正常数据后,“安抚” cin 受伤的心灵,让她重新投入读取工作。
第十六行:
while(cin.get() != '\n') ;是关键,作用是去除错误数据。比如此例。非正常数据是:'r''i''g''h''t''?'这五个字符通过循环做一定次数(次数由'\n'决定)地字符读取操作 cin.get() ,使垃圾数据从输入流中消失(字符被 cin.get() 读取即视为消失)。
当然这个程序还有不足之处,如果输入的是浮点或是56ac等有数字前缀的字符串时,会发生错误:

                  Please enter your golf scores.
                  You must enter 5 rounds.
                  round #1: 56.5
                  round #2: Please enter a number: 56abc
                  round #3: Please enter a number: 56
                  round #4: 56
                  round #5: 56
                  56 = average score 5 rounds
原因是, cin >> glof[i] 读取56.6或56abc都是正常,没有执行循环语句。但golf[i]只读取了一部分,剩下的(56.6剩下".6";56abc剩下"abc")留给了 cin >> golf[i+1] ,数据不合法,执行循环,把不合法数据去除,之后执行第17行。也就是说 “round #2:” 和 “56abc”之间已经在后台执行循环了,当然这个循环并没有为golf数组输入数据,只留下一句话,对后面的平均值无影响。从程序的健壮性来说,"56.6"、"56abc"都是非法数据,应该被去除而不是被程序读取。
III、总结。从前面
cin 表现的一些性质看, cin 是个千方百计使得数据合法的家伙。就算要的是整型,而输入的是浮点,它都要把"点"和"小数"留在输入流中,自己只读取整数部分。以后在解释一些现象的时候要以这个为原则。
4、cout的关于精度新参数。就像
cout << hex 一样,可以通过相应的设置控制浮点型数据的现实。从网上看到一篇介绍,挺好,复制粘贴过来了:
#include <iostream>
#include <iomanip>
using namespace std;
int main( void )
{
    const double value = 12.3456789;

    cout << value << endl;                             // 默认以6精度,所以输出为 12.3457
    cout << setprecision(4) << value << endl;          // 改成4精度,所以输出为12.35
    cout << setprecision(8) << value << endl;          // 改成8精度,所以输出为12.345679
    cout << fixed << setprecision(4) << value << endl; // 加了fixed意味着是固定点方式显示,所以这里的精度指的是小数位,输出为12.3457
    cout << value << endl;                             // fixed和setprecision的作用还在,依然显示12.3457
    cout.unsetf( ios::fixed );                         // 去掉了fixed,所以精度恢复成整个数值的有效位数,显示为12.35
    cout << value << endl;
    cout.precision( 6 );                               // 恢复成原来的样子,输出为12.3457
    cout << value << endl;
}
地址:戳之
5、简单的文件I/O。文件的输出和输入与
cout cin 对应。
I、输出。先给一个例子:
#include <iostream>
#include <fstream>

int main()
{
    using namespace std;
    ofstream outFile;
    char path[10] = "test.txt";
    outFile.open(path);         //or outFile.open("test.txt")
    outFile << "离散数学\n";
    outFile << "計算機圖形學";
    outFile.close();
    return 0;
}
结果是在当前文件夹创建了test.txt文件,并有相应内容。
步骤:
①包含头文件
fstream (第2行);
②创建一个
ofstream 对象(第7行,所创建的对象相等于 cout ,同样需要名称空间std);
③将该
ofstream 对象同一个文件关联起来(第9行)。通常使用 open() 。函数 open() 接收一个字符串,可以字符数组,也可以是 string 对象;
④像使用
cout 一样使用 ofstream 对象(第10-11行)。
II。输入。输入对应于cin,与输出一样需要创建一个
ifstream 对象,而后对这个对象进行与cin相似的操作。输入涉及到多个问题:所要打开文件是否存在、所读取数据是否合法、什么时候停止读取等。
①检验文件是否存在用is_
open() 方法,文件不存在时,返回 false
②检验数据的合法性:使用
good() 方法,配合 fail() 使用。
③检验文件末尾:
eof() 或者 fail()
假设文件test.txt包含数据:45 55 89 45 ch 60
#include <iostream>
#include <fstream>
#include <cstdlib> 
#include <string>

int main()
{
    using namespace std;
    int count = 0, value, sum = 0;
    ifstream inFile;
    string path = "test.txt";
    inFile.open(path);
    if(!inFile.is_open())
    {
        cout << "Could not open the file " << path << endl;
        cout << "Program terminating.\n";
        exit(EXIT_FAILURE);
    }
    inFile >> value;
    while(inFile.good())
    {
        count++;
        sum += value;
        inFile >> value;
    }
    if(inFile.eof())cout << "End-Of-File\n";
    else if(inFile.fail()) cout << "Data Not Match\n";
    else cout << "Unknow Reason of stopping reanding\n";
    cout << "The number of data in this file: " << count << endl;
    cout << "Sum: " << sum << endl;
    cout << "Average: " << double(sum)/count << endl;
    inFile.close();
    return 0;
}
输出:
                     Data Not Match
                     The number of data in this file: 4
                     Sum: 234
                     Average: 58.5
①头文件 cstdlib 用于支持程序的第17行,当 is_open() 返回 true 时,执行 exit(EXIT_FAILURE) ,退出程序;
②第20行,
good() 用于读取数据是否正常;
③26、27行,
eof() 只能判断是否达到EOF, fail() 可以检查EOF和类型不匹配。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值