写这个源于 一道题 《1028 人口普查(20)(20 分)》
前言:在网络上 我常常会看见有人说 cin>>的效率慢 不如 scanf 。经过测试 的确是这样子。既然cin>>输入慢 为什么还要用呢?抛开很多很多的问题比如:
1.cin>>可以对类似string 类型进行直接输入。
2.cin>>可以自动转换类型,不需要像scanf写的那么麻烦。
3.等等
// 实验之前 先说下一些已知的结论 因为考虑到 可能有些人不愿意看我实验的内容,可能是因为我太水了吧。--哭~
1. string使用 scanf进行输入是这样输入的:
string s;
scanf("%s",&s[0]);
直接
scanf("%s",s); //无法完成赋值 赋值结束后字符串 s 为空
2.使用scanf给 string 直接结构体赋值后 无法传递给 下一 string的变量。
struct sn {
string t;
}K,P;
void solve() {
string s;
scanf("%s",&K.t[0]);
P = K;
s = K.t;
}
答案是:当K.t被正常赋值以后P.t 为空 s也为 空
造成这个原因的是 没有加上 resize(num);这个函数 num是正整数 表示初始化string多少空间。
接下来不想讲太多 我还要留一些下面讲 , 不想看的 可以关掉页面了。== (今天怎么啦?)(不说。。~)
//
那么问题来了 我如何使用 scanf()对string进行输入呢?又有什么不同的地方,适不适用 gets ?
这次主要做一个实验:
实验工具: VS2017 , codeblock 17,VC++6.0 不一定全部用上。因为我记得 2017里是没办法使用 gets的 ,它提供了一个叫做gets_s的安全函数 一会也会进行测试。
一般情况之下 我们对 string 类型的变量赋值的时候会使用 cin>> 赋值 两个string值之间可以 使用等于号进行赋值,这个是我们的常识:
比如:
string s,t;
cin>>s;
t = s;
那么 string 类型的数据 在输入后其实也可以像 char 类型的数组一样是一个连续的空间 那么就是因为这个特性 才能用scanf进行输入。那么输入的方法是:对空间的第一个元素所在的地址进行输入。那么我们早就知道对char 数组 或是 char* 空间数组的赋值方法是
char s1[900];
scanf("%s",s1);
scanf_s("%s",s1,sizeof(s1)); // 新版编译器 OJ 不支持
gets(s1);
gets_s(s1,sizeof(s1)); // 新版编译器 OJ 不支持
那么我们推出 使用 scanf对 string 进行输入的方法:
string s;
s.resize(10000);
scanf("%s", &s[0]);
有些人会说 s.resize(10000);这条语句我不加 也可以赋值成功啊~ 他们给我看的是这样的情况(输入NTSD)
赋值成功!! 但是 这是很危险的 我们使用更长的字符串的时候就会赋值失败 比如:
但是我们 启用 resize 的话情况就会不一样。如图:
这样才是正规的写法,但是我们今天不仅研究这个。我们来看看赋值的操作吧。
直接使用等号赋值的是成功的!!!那今天的实验到此为止么?不是 因为赋值成功还有特例 让它赋值不成功
我们来看 那个最特殊的 特例 让这种方法彻底失败。当然也是犯了一个错误所导致的 resize(num);
这个最特殊的特例就是 --- 结构体的整体赋值下。或是 结构体中的string赋值给局部(全局)变量下。
如果不加 resize(num);就会出现赋值失败的问题。
加上就会好了:
RT
由于 VS2017上没有 gets 那么我们使用 vc++6.0来看一下吧!gets也是能正常的赋值的。
然后我使用子函数 在VS2017上模拟了一下 gets
int gets(char *s) {
for (char t, *p = s; t = getchar(), s!=NULL&&t != '\n'; p++, *p = 0)
*p = t;
return s != NULL ? strlen(s) : 0;
}
也能成功赋值。我觉得这个也是一个替代方案吧 毕竟摆着 cin>>不用 用这个还是很多坑点的啊!!~~
本来想上一下反汇编的~~~但是我也不精反汇编 怕说错被笑 哈哈~~
好好学习,天天向上,加油哦~