1 某些场景整数流不是空格分割,如用逗号分割
例如,下面的输入,要求每行是一个数组,一共两行测试输入
1,2,3,4
5,6,7,8
下面的代码就可以很好的解决问题。
vector<int> w;
int temp;
while (cin >> temp){
w.push_back(temp);
if (cin.get() == '\n') break;
}
2 先谈谈cin
cin会根据数据的类型
以及分隔符
自动对数据进行输入。
-
数据的类型
:两个常见的类型,如字符串string、数(int、short、float、double)
-
分隔符--delimiter
:isblack()
即空格
和TAB
两个
- cin允许分隔符多次出现,比如两数中间可以有多个空格、TAB相连
因此常见的数据输入是空格作为分隔符。
- cin会自动
忽略分隔符
和回车换行‘\n’
自动忽略
:不是足够智能发现它就不读取,而且读取后丢弃了!!!,可用通过cin.unsetf(ios::skipws)让cin都读取不丢弃
3 理解上面的代码
到这里就很清晰了,代码通过cin.get()
从缓存中读取一个字节,这样就扩充了cin只能用空格
和TAB
两个作为分隔符。这很精巧。发现是’\n’就知道一行结束了
案例
1/6*4556-123 /**<OK */
1/6*4556- 123 /**<OK,cin会自动忽略空格 */
192.168..1 /**<ERROR-上面的代码只能忽略一个空格,连续两个,,会触发cin.fail的错误 */
下面是一个IP地址的读取,很容易达到目标
5 多行读取
上面的代码只能读取一行,有些不足,因为到底输入多少行是未知的,利用cin.good
实现多行读取
int number;
while (cin.good()) {
vector<int> ip_mask;
while (cin >> number) {
ip_mask.push_back(number);
if (cin.get() == '\n')
break;
}
if (!cin.good())
break;
/**<do something */
}
注意:循环次数是行数+1,会多一次循环,是为了触发读取失败。
流状态有 3 个标志位:eofbit,badbit 和 failbit。
- 当 cin 操作到达文件末尾时,eofbit 置 1。
- 当流被破坏时,badbit 置 1。例如:试图读取不可访问的文件、写入写保护的磁盘、写入的设备剩余空间不足等。
- cin 操作未能读取到预期的字符时 failbit 会置 1。例如:要输入到一个整型变量中,输入的却是字符时 failbit 置 1。I/O 失败时 failbit 也可能置 1。
- 如果 3 个状态位都为 0 表示一切顺利。good
5 BUG
考虑如下输入
1,2,3,4,
5,6,7,8
在4的后面添加一个逗号,这是就不能达到预期目标,实际上是一个数组,因为读完4后,cin.get()把逗号读走,cin接着读取’\n’当然自动忽略,也就连在一起了
6 字符串的流分割
如果是字符串,就不能简单的处理了,需要配合istringstream
xxx,xxx,xxx
下面是经典的处理方式,istringstream
配合getline
的字符切割方式。
vector<int> w;
vector<int> v;
string wstr;
string vstr;
cin >> wstr;
cin >> vstr;
istringstream iss(wstr);
string word;
while (getline(iss, word, ',')) {
w.push_back(stoi(word));
}
iss.clear();
iss.str(vstr);
while (getline(iss, word, ',')) {
v.push_back(stoi(word));
}