當 cin 無法把輸入的資料成功的轉換成你所設定的類型是, cin 內部設為錯誤狀態, 而無法轉換的資料還在 input buffer 裡.
當讀取資料時, 應該檢查 cin 的 state, 並在有錯誤時處理:
#include <iostream>
#include <limits>
using namespace std;
int ReadInteger(void)
{
int i;
cout << "Enter integer: " << endl;
while (!(cin >> i))
{
cout << "Input non-integer, try again" << endl;
cin.clear(); /* 必須先清除錯誤狀態 */
/* 把還在 buffer 裡, 但無法轉換的資料 "吃掉" */
cin.ignore(numeric_limits<streamsize>::max(), '\n');
}
return i;
}
int main(void)
{
cout << ReadInteger() << endl;
return 0;
}
istream::ignore() 的作用是把 input stream 的 character(s) 讀進來再丟掉. 也就是把 input stream 的一個或多個字元 (characters) 消滅掉.
istream::ignore() 有三個 overload. 第三個是:
istream::ignore(streamsize count, int delim)
第一個參數告訴 ignore 最多要消滅掉幾個字元.
第二個參數告訴 ignore 何時停止消滅字元的工作.
當 ignore 讀到 'delim' 所設定的字元後, 或是達到 'count' 所設定的數目時, ignore 就會 return. 'delim' 所設定的字元也會丟掉.
'count' 的型態是 'steamsize', 這是一個 typedef. 它的最大值可以用以下的方法來找:
std::numeric_limits<streamsize>::max()
整個
cin.ignore(numeric_limits<streamsize>::max(), '\n');
的意思就是: 把從現在起, 以後整行的 input 都丟棄掉.
建議你看這本書:
"The C++ Standard Library - A tutorial and Reference"
By Nicolai M. Josuttis
Felix 發表在 痞客邦 留言(0) 人氣(6,098)
vector 亦可作為函數的參數例如
void test(const vector<int> &v)
您可以使用vector來替代陣列,並使用陣列型式(Array idiom)的方式來操作vector,要使用vector,必須含入vector表頭檔:
#include <vector>
要建立vector型態的物件(Object),您必須提供元素型態與長度資訊,例如下例中建立int元素的vector,並擁有10個元素:
Felix 發表在 痞客邦 留言(0) 人氣(3,275)
一.计算机中随机数的产生
现在,在计算机,用来产生随机数的算法是"线性同余"法。所谓线性同余,其实就是下面两个式子。假设I就是一个随机数的序列,Ij+1与Ij的关系如下:
Ij+1 =Ij * a+c (mod m)
或是Ij+1 =Ij *a (mod m),
其中,不妨取a=16807,m=2147483647,以为一常数。写个简单的程序就是:
Felix 發表在 痞客邦 留言(0) 人氣(1,129)
一般人看到【取亂數不重複】..很直接的想法就是一直取,每次取完之後再跟之前的比較..
其實這樣的效率極差!取N個不重複的亂數需要做N階乘次比對..
有學過資料結構的應該都知道.在複雜度裡面..N階乘算是【極差】
取亂數可以使用洗牌法..
意思就是說..
Felix 發表在 痞客邦 留言(1) 人氣(10,468)
所谓的“伪随机数”指的并不是假的随机数,这里的“伪”是有规律的意思。其实绝对的随机数只是一种理想状态的随机数,计算机只能生成相对的随机数即伪随机数。计算机生成的伪随机数既是随机的又是有规律的 —— 一部份遵守一定的规律,一部份则不遵守任何规律。比如“世上没有两片形状完全相同的树叶”,这正点到了事物的特性 —— 规律性;但是每种树的叶子都有近似的形状,这正是事物的共性 —— 规律性。从这个角度讲,我们就可以接受这样的事实了:计算机只能产生伪随机数而不是绝对的随机数。
C++中的标准库<cstdlib>(包含在<iostream>中)提供两个帮助生成伪随机数的函数:rand()和srand()。
函数一:int rand(void);
从srand(seed)中指定seed开始,返回一个范围介于[seed,RAND_MAX(0x7fff))的随机整数
Felix 發表在 痞客邦 留言(0) 人氣(25,417)
●英中繁简编程术语对照
英文 台湾惯用术语 大陆惯用术语
---------------------------------------------------------------------------------------
abstract 抽象的 抽象的
Felix 發表在 痞客邦 留言(0) 人氣(327)
在使用C++编程时,经常要用到不同数据类型之间的类型转换,可能大家对C语言的类型强制转换比较熟悉,就是在表达时前面加一个“(强制转换类型)”。在 C++中仍然可以用C方式的对不同类之间数据类型转换,但是,C++提供了更好的数据类型转换方式,就是利用关键字“dynamic_cast”来完成对 不同类之间数据类型之间的转换。
dynamic_cast的使用格式是:
dynamic_cast <T> (ptr)
Felix 發表在 痞客邦 留言(0) 人氣(217)
C++預設函數成員都不是虛擬函數,如果要將某個函數成員宣告為虛擬函數,則要加上"virtual"關鍵 字,然而C++提供一種語法定義「純虛擬函數」(Pure virtual function),指明某個函數只是提供一個介面,要求繼承的子類別必須重新定義該函數,定義純虛擬函數除了使用關鍵字"virtual"之外,要在函 數定義之后緊跟着'='并加上一個0,例如: Felix 發表在 痞客邦 留言(0) 人氣(4,346)
const int * pOne;
int * const pTwo;
const int * const pThree;
pOne 是一個指向整型常量的指針。它指向的值是不能修改的。
pTwo 是一個指向整常的常量指針。它指向的值可以修改,但pTwo不能指向其他變量。
Felix 發表在 痞客邦 留言(0) 人氣(1,841)
如果我们对一个非字符的指针进行操作,方法是这样的: 定义:int a=7; int *p=&a; 或者 int a=7; int *p; p=&a; 或者 int a=7; int *p; *p=a; 这样定义的原因是因为等号两边的类型必须匹配,int *p=&a; 等号左边定义的是一个指针,指针的内容是地址,所以等号右边也应该是地址,&a就是取空间a的地址,第二种情况 int *p; p=&a; 为什么不是 *p=&a 而是 p=&a; 因为在定义的时候“*”只是说明p是一个指针,而p也是一个变量,不过是储存地址的一种特殊的变量,对于变量使用,我们都是直接使用它的名字,就好象,我们定义个常量 const a=7; 我们要调用它的时候直接使用a就可以了,并不需要带上 const 修饰,这里也一样,用指针变量时并不需要带上“*”,而第三种情况中的“*”和第二种里面是不同的,这里的“*”是取内容符,与之相反的是取地址符“&”,分析一下,第三种情况中,等号左边是*p表示对指针p取内容,它的内容指向内存中的某个已经在开始通过 int *p; 定义好的空间里(比较确切一点的说法是,p在定义的时候,其内容里的地址指向内存中某个未知的空白区域,即未占用,不受保护的内存空间),这个空间里存放的数据类型是整型,所以等号的右边也应该是整型才能匹配,所以是 *p=a; 这里的“*”和定义时候的是不同的,这一点很重要。 其实上面的都是些题外话,我要说的其实是关于指针的输出的一些问题。我们利用上面定义好的进行输出操作。 输出指针的内容(即所指向空间的地址):cout<<p<<endl; 输出指针所指的内容(即指针内容所描述地址空间中的内容):cout<<*p<<endl; 指针对于字符的处理却有些特殊,和前面的非字符的指针输出处理要分开理解。 比如,我们定义一个 char a='A'; char *p=&a; 如果我们调用上面非字符指针的输出方式,结果如下: 方式1 cout<<p<<endl; 结果 A####(#表示乱码,不可识别) 并不是地址 方式2 cout<<*p<<endl; 结果 A 这和非字符的指针情况一样,输出指针指向的内容 而且我们直接操作 cout<<&a<<endl; 结果和方式1的结果是完全相同的 为什么方式1输出的不是地址呢?这里有一个特殊的处理,虽然这里的p的内容确确实实是一个地址,但是cout操作字符指针的话,它遇到地址,就会直接去寻找这个地址所指向的内容,并把它的空间里的机器数按照字符的规则转化成字符输出,直到遇到“\0”这个操作符才停止。所以我们直接输出p的时候,它先输出‘A’然后再继续读取后面的内存空间知道遇到“\0”,显示结果是“A+乱码”。 你肯定会说,为什么要这样呢,这样多不方便呀,其实这么做是有目的的,而且恰恰就是为了方便才这么设置的。因为这样就可以很容易的处理字符串了,而处理字符串是我们在计算机中用得很多的操作。 比如我们第一个字符串数组 char a[]="mantou"; a[]在内存中在7个字节,而不是6个,因为在mantou字符串后面还隐藏有一个“\0”,这时我们用 char *p=a; (这里不用&a是因为,a[]是一个数组,数组名a本身就是一个指针常量) 输出操作 cout<<p<<endl; 这里就不会输出地址,而是直接输出整个mantou字符串,很方便哈,如果我们 cout<<*p<<endl; 结果显示的是m,因为p是指向数组的首元素的地址的,就是指向这里的储存m的空间的地址,所以取p的内容(*p),只能输出一个m哦。 虽然通常情况下我们是不需要了解我们的数据地址的,但我也顺便说说,怎么得到字符指针的地址,也可以方便大家对内存地址的分配再做更深入的研究。 char a='A'; 如果这里直接输出 cout<<&a<<endl; 当然是不能输出地址的,原理上面已经说过了,cout遇到字符型地址就会转换成字符输出。我们可以用指针p先取得a的地址(char *p=&a;),但是这样用 cout<<p<<endl; 也并不能得到地址呀,做个小技巧,首先我们知道p中的内容本身就是地址,但是因为它是字符串,我们又不能直接输出它,所以呀,我们可以把指针里的内容(记载的是一个地址数据)强制转化成整型再输出 cout<<(int)p<<endl; 呵呵,这样就得到了这个指针里的内容——十进制型的地址,而我们知道,地址是用十六进制表示的,形式是 0x######## 0x后面加8位十六进制数,我们把我们先得到的十进制地址按照地址的表示形式用流操作转化成十六进制就可以了。代码如下: cout<<"0x"<<setfill('0')<<setw(8)<<setiosflags(ios::uppercase)<<hex<<(int)p<<dec<<setfill(' ')<<endl; //流控制实现十六进制地址输出 注意不要忘了 #include<iomanip.h> 这个头文件哦
|
| |
文章来源:http://blog.sina.com.cn/s/blog_4a48684701000c5x.html
Felix 發表在 痞客邦 留言(0) 人氣(133)