最近写了个弱智程序,找最大公约数(GCD,Greatest Common Divisor)。目前还未能分清楚数据封装和数据抽象的异同点,但是仍然可以实践。具体所作就是把类的数据(存放数字的变量)和关键成员函数(具体算法)藏起来,把构造函数和析构函数暴露出去,用于在主程序中进行操作(作为接口)。
因为这个类很简单,给它俩数,它告诉你GCD,于是不必废话,直接在构造函数中调用算法,然而在调用算法之前需要执行输入数据的检查,否则会出现意想不到的可笑错误。而主程序的主体被写在一个do while循环体中,需要在每次执行后对屏幕进行询问,根据屏幕输入的结果进行判断是否跳出循环结束主程序。
在C++中输入普遍使用标准输入流cin,在本实践中,使用到了几个常用函数来完成输入判断
cin的缓冲区
cin的输入会进入到一个缓冲区内进行存储,遵循LILO原则,而cin会以制表符,空格键和回车作为输入分隔符。
#include <iostream>
using namespace std;
int main(){
while(1){
cout << "Say something to me! " << endl;
char input[100];
cin >> input;
cout << input << endl;
}
return 0;
}
此例测试结果如下:
Say something to me!
Where is my space???
Where
Say something to me!
is
Say something to me!
my
Say something to me!
space???
Say something to me!
若要解决这个问题,可以用到cin.getline()成员函数,该函数可以读取整行输入,并且可以指定分隔符,默认为回车。
cin.fail()
cin会对输入数据与流入变量的数据类型进行检查,当出现错误时,cin.fail()会返回真。
cin.clear()
cin.clear()的功能是清除cin.fail()的错误状态。由于输入检查与重新输入往往放在一个循环体中,若不进行归位,会导致死循环。cin.fail()与cin.clear()的使用实例在下述例程中类的构造函数中展示。
在学习初期,我将cin.clear()的功能误以为是清除缓冲区数据,实则不然。这是我的第一个混淆点。
cin.ignore(1000,’\n’)
cin.ignore()的功能才是清除缓冲区数据,或者是忽略缓冲区数据。第一个参数是忽略的字节数,第二个数据是指定的忽略行为停止的字符。若输入"qwerty\n",指定忽略3个字符,则"rty\n"会流入下一次cin指定流入的变量,若指定忽略1000个字符,则忽略到’\n’后为止,不会对下一次输入行为产生影响。
在混淆cin.clear()时,我误以为这是限定下一次cin只读取前几个输入字节而忽略后续字节的意思。
例程
以下为例程:
#include <iostream>
using namespace std;
class GCD{
private:
int tempG; //较大数
int tempS; //较小数
int tempM; //余数
int num1; //存放输入数字
int num2;
int gcd; //存放最大公约数
//成员函数 计算最大公约数
void Euclidian();
//成员函数,显示计算结果
void display();
public:
GCD(void); //构造
virtual ~GCD(void); //析构
};
//构造时执行输入判断、计算以及结果输出
GCD::GCD(void){
cout << "Please enter two positive integer numbers. Seperate them using tab, space or return:" << endl;
cin >> num1 >> num2;
while ((num1 < 1) || (num2 < 1) || (cin.fail()))
{
cout << "Please enter two POSITIVE integer NUMBERS!" << endl;
cin.clear(); //清除错误状态
cin.ignore(100, '\n'); //忽略前序输入
cin >> num1 >> num2;
}
if (num1 > num2){
tempG = num1;
tempS = num2;
}
else{
tempG = num2;
tempS = num1;
}
Euclidian();
display();
}
//析构以释放内存
GCD::~GCD(void){}
//成员函数,计算最大公约数
void GCD::Euclidian(){
do{
tempM = tempG % tempS;
tempG = tempS;
tempS = tempM;
} while (tempM != 0);
gcd = tempG;
}
//成员函数,显示结果
void GCD::display(){
cout << "The greatest common divisor of " << num1 << " and " << num2 << " is: " << gcd << endl;
cout << "--------------------------------------------------------" << endl;
}
int main(){
char f;
do{
GCD obj;
obj.~obj();
cout << "Do you wish to continue? (Y/N)" << endl;
cin >> f;
int ff = 0;
do{
switch (f){
case 'Y':
ff = 0;
continue;
case 'N':
ff = 0;
continue;
default:
cout << "You are so bad! (Y/N)" << endl;
ff = 1;
//cin.clear(); 此处并未对cin.fail()进行判断,不用使用cin.clear()
cin.ignore(1000, '\n');
cin >> f;
}
} while (ff == 1);
} while ( f == 'Y');
return 0;
}
测试结果如下
Please enter two positive integer numbers. Seperate them using tab, space or return:
1232 232
The greatest common divisor of 1232 and 232 is: 8
--------------------------------------------------------
Do you wish to continue? (Y/N)
what if i mess with you //主程序中对输入的判断
You are so bad! (Y/N)
Y
Please enter two positive integer numbers. Seperate them using tab, space or return:
gs 2 //构造函数对输入的判断
Please enter two POSITIVE integer NUMBERS!
-2 7 //构造函数对输入的判断
Please enter two POSITIVE integer NUMBERS!
23232116 2322
The greatest common divisor of 23232116 and 2322 is: 2
--------------------------------------------------------
Do you wish to continue? (Y/N)
N
Press any key to continue . . .
后续问题
Please enter two positive integer numbers. Seperate them using tab, space or return:
111111111111111111111111111111111 1
Please enter two POSITIVE integer NUMBERS!
1111111111111 6
Please enter two POSITIVE integer NUMBERS!
111111111111 6
Please enter two POSITIVE integer NUMBERS!
11111111111 6
Please enter two POSITIVE integer NUMBERS!
1111111111 6
The greatest common divisor of 1111111111 and 6 is: 1
--------------------------------------------------------
Do you wish to continue? (Y/N)
Ndfsdfsdfs
Press any key to continue . . .
数据超长;无法实现对该次Y/N判断的识别。