输入输出的模板(cin getline()) stringstream

在OJ时常会碰到需要输入一段甚至多段的情况,以下介绍一些常用的输入手段以及方法:

1.cin

cin 是 C++ 标准输入流对象,即 istream 类的对象。cin 主要用于从标准输入读取数据,这里的标准输入指终端键盘。

cin 可以连续从键盘读取想要的数据,以空格、tab 或换行作为分隔符,当我们从键盘输入字符串的时候需要敲一下回车键才能够将这个字符串送入到缓冲区中,那么敲入的这个回车键(\r)会被转换为一个换行符(\n),这个换行符也会被存储在 cin 的缓冲区中并且被当成一个字符来计算!比如我们在键盘上敲下了 123456 这个字符串,然后敲一下回车键(\r)将这个字符串送入了缓冲区中,那么此时缓冲区中的字节个数是 7 ,而不是 6。

当 cin>> 从缓冲区中读取数据时,若缓冲区中第一个字符是空格、tab或换行这些分隔符时,cin>> 会将其忽略并清除,继续读取下一个字符,若缓冲区为空,则继续等待。但是如果读取成功,字符后面的分隔符是残留在缓冲区的,cin>> 不做处理。

如键入

[回车][回车]i_am_test[回车]

	string str;
	cin >> str;
	cout << str << endl;

输出

i_am_test

注意此时输入缓冲区中,还存在一个换行符,以上提到cin是不做处理的,所以如果下面的输入是getline(),getline()不会忽略开头的换行符,就会将这个换行符读进去导致问题出现:
键入

[回车][回车]i_am_test[回车]

	string str, s;
	cin >> str;
	getline(cin, s);//不阻塞
	cout << "str : " << str << endl;
	cout << "s : " << s << endl;

在这里插入图片描述
cin>> 对缓冲区中的第一个换行符视而不见,采取的措施是忽略清除,继续阻塞等待缓冲区有效数据的到来。但是,getline() 读取数据时,并非像 cin>> 那样忽略第一个换行符,getline() 发现 cin 的缓冲区中有一个残留的换行符,不阻塞请求键盘输入,直接读取,送入目标字符串后,因为读取的内容为空,所以程序中的变量 test 为空串。

2.关于getchar() 与 peek()

getchar()不是一个输入方式,但是上面讲到缓冲区中残留的换行符,这个getchar()会有所帮助。C 库函数 int getchar(void) 从标准输入 stdin 获取一个字符(一个无符号字符),其函数原型为:

int getchar(void)

它会从输入缓冲区中拿出一个字符,返回字符的ASCII值,可以使用这个对缓冲区进行“清理”,也可以用来输入一串字符给数组或字符串。

#include <iostream>
#include <stdio.h>
#include <string>
using namespace std;
const int N = 50;
char c;
int main() {

	char c;
	string s;
	while ((c = getchar()) != '\n')
		s += c;
	printf("\n\n\n");
	cout << s << endl;
	return 0;
}

在这里插入图片描述

还有一个peek()函数,原型为

int peek(void)

查看缓冲区中的下一个字符,只看不拿。

3.getline()
int main() {
	string line;
	while (getline(cin, line))//该写法在VS里面是死循环,不知道在其他地方是否可以用来输入多行数据
	//用ctrl+Z 键入EOF来退出循环
		cout << line << endl;
	return 0;
}

头文件:string
这是C++引入的库函数,用来输入一段,最好使用getline()
函数原型:

istream& getline ( istream &is , string &str , char delim );

其中,istream &is 表示一个输入流,譬如cin;

string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);

char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为’\n’,也就是回车换行符(遇到回车停止读入,并将该回车符从缓冲区中删除)。

区别与cin.get()以及cin.getline(),是char型的,这两个函数原型:

//cin.get()
int get();
istream& get(char& var);
istream& get( char* s, streamsize n );
istream& get( char* s, streamsize n, char delim);

//cin.getline()
istream& getline(char* s, streamsize count); //默认以换行符结束
istream& getline(char* s, streamsize count, char delim);

streamsize在VC++中为long long 类型。

cin.get()读取一行时,遇到换行符时结束读取,但是不对换行符进行处理,换行符仍然残留在输入缓冲区。cin.getline() 读取一行字符时,默认遇到 ‘\n’ 时终止,并且将 ‘\n’ 直接从输入缓冲区中删除掉,不会影响下面的输入处理。

4.stringstream

定义了三个类:istringstream、ostringstream 和 stringstream,分别用来进行流的输入、输出和输入输出操作。本文以 stringstream 为主,介绍流的输入和输出操作。

主要用来进行数据类型转换,由于 使用 string 对象来代替字符数组(snprintf 方式),避免了缓冲区溢出的危险;而且,因为传入参数和目标对象的类型会被自动推导出来,所以不存在错误的格式化符号的问题。简单说,相比 C 编程语言库的数据类型转换, 更加安全、自动和直接。

#include <string>
#include <sstream>
#include <iostream>
#include <stdio.h>
 
using namespace std;
 
int main()
{
    stringstream sstream;
    string strResult;
    int nValue = 1000;
 
    // 将int类型的值放入输入流中
    sstream << nValue;
    // 从sstream中抽取前面插入的int类型的值,赋给string类型
    sstream >> strResult;
 
    cout << "[cout]strResult is: " << strResult << endl;
    printf("[printf]strResult is: %s\n", strResult.c_str());//string类型调用c_str(),返回类型为char *
 
    return 0;
}

在这里插入图片描述

#include <string>
#include <sstream>
#include <iostream>
 
using namespace std;
 
int main()
{
    stringstream sstream;
 
    // 将多个字符串放入 sstream 中
    sstream << "first" << " " << "string,";
    sstream << " second string";
    cout << "strResult is: " << sstream.str() << endl; //stringstram类调用.str(),返回为string类型
 														//如果要返回C类型字符串sstream.str().c_str()
    // 清空 sstream
    sstream.str("");
    sstream << "third string";
    cout << "After clear, strResult is: " << sstream.str() << endl;
 
    return 0;
}

在这里插入图片描述

  • 可以使用 str() 方法,将 stringstream 类型转换为 string 类型;
  • 可以将多个字符串放入 stringstream 中,实现字符串的拼接目的;
  • 如果想清空 stringstream,必须使用 sstream.str(“”); 方式;clear() 方法适用于进行多次数据类型转换的场景。
5.清空输入缓冲区

可以用

char c;
while ((c = getchar()) != EOF && c != '\n');//不停地使用getchar()获取缓冲中字符,直到获取的c是“\n”或文件结尾符EOF为止

使用getchar不断获取缓冲区内的内容,直到缓冲区内空为止,这种方法很有效,建议使用,C primer 上也介绍了这种方法。

例子

以下几种对应的输
入以及输出

  1. 输入一行以回车结束的数据,要得到的是int数值
    在这里插入图片描述
    输入:
	int a[N], n;
    // while (cin >> a[n]) n++;
    // 这里对上个注释进行改进,用一个peek()来检验输入流中的回车符
    //peek()是istream类函数,原型为 int peek();
    //回车符的ASCII值为10
    while(cin >> a[n]) {
		n++;
		if (cin.peek() == 10) break;
	} 
    for (int i = 0; i < n; i++) {
		//...
	}

或者用stringstream,注意包含头文件

#include<sstream>
const int N = 1010;
int n;
int h[N];
int main()
{
    string line;
    getline(cin, line); //读入一行string
    stringstream ssin(line);	// 用stringstream来转换
    while (ssin >> h[n]) n ++ ;
}

扩展:将string里面的数值装到vector容器里:

	string data
	stringstream sstr(data);
    int x;
    while (sstr >> x) d.push_back(x);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值