文章目录
-
-
-
-
- 1、不能使用int x,y=0;方式来定义x和y都为0的情况。(这种定义只是给y赋值为0,而x是随机数。)
- 2、print()函数的压栈处理:
- 3、父类容器是可以容纳子类对象的,只不过定义vector< A >(父类)时,只调用父类的函数,即只保留父类(基类)函数的作用
- 4、分别定义bool,char类型的变量各一个,并依次输出它们的存储空间大小(单位:字节)。实践表明都为1个字节。
- 5、输入n个数,计算最大值与最小值之差(while(scanf("%d",&x)!=EOF))
- 6、输出1-500以内的所有完数(纯C语言)
- 7、& 按位与, | 按位或, ^ 按位异或, ~按位取反, <<左移运算符, >>右移运算符等
- 8、对于cin与scanf以及输入缓冲区的简要比较:
-
-
-
1、不能使用int x,y=0;方式来定义x和y都为0的情况。(这种定义只是给y赋值为0,而x是随机数。)
#include <iostream>
#include<stdio.h>
using namespace std;
int main()
{
int x,y=0;
cout<<x<<" "<<y<<endl;
//result: 4354304 0 //因此定义x,y同时为0不能那么定义
return 0;
}
2、print()函数的压栈处理:
//printf()函数:
#include<stdio.h>
main(){
int i=9;
int j=3;
printf("%d\n",j,i,++j); //函数printf从右到左压栈,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的,所以我们看见的结果是,从右边开始处理的。
printf("%d\n",i,--i);
}
3、父类容器是可以容纳子类对象的,只不过定义vector< A >(父类)时,只调用父类的函数,即只保留父类(基类)函数的作用
//父类容器是可以容纳子类对象的,只不过定义vector<A>(父类)时,只调用父类的函数,即只保留父类(基类)函数的作用
#include <iostream>
#include<vector>
using namespace std;
class A{
protected:
int a;
int b;
public:
A(){
};
A(int a,int b):a(a),b(b){
}
void get(){
cout<<a<<" "<<b<<endl;
}
};
class B:public A{
int c;
public:
B(){
};
B(int a,int b,int c){
//构造函数内赋值应该用this->
this->a=a;
this->b=b;
this->c=c;
}
//定义vector<A>时,只调用父类的get()函数,即该函数不会被调用
void get(){
cout<<a<<" "<<b<<" "<<c<<endl;
}
};
int main(){
vector<A>obj;
A a(1,2);
B b(2,3,4);
obj.push_back(a);
obj.push_back(b);
for(int i=0;i<obj.size();i++)
{
//此处只调用父类的get()函数
obj[i].get();
}
}
result:
4、分别定义bool,char类型的变量各一个,并依次输出它们的存储空间大小(单位:字节)。实践表明都为1个字节。
//分别定义bool,char类型的变量各一个,并依次输出它们的存储空间大小(单位:字节)。
#include<stdio.h>
main()
{
bool a;
char b;
printf("%d %d",sizeof(a),sizeof(b));
}
5、输入n个数,计算最大值与最小值之差(while(scanf("%d",&x)!=EOF))
//输入n个数,计算最大值与最小值之差
#include <stdio.h>
int main()
{
int n,i,x,min,max;
//scanf("%d",&n);
scanf("%d",&x);
min=x;
max=x;
//for(i=1;i<=n-1;i++)
while(scanf("%d",&x)!=EOF) //scanf("%d",&x)!=EOF 按^Z停止
{
//scanf("%d",&x);
if(max<x)max=x;
if(min>x)min=x;
}
printf("%d\n",max-min);
return 0;
}
6、输出1-500以内的所有完数(纯C语言)
注意内容:
在重新赋值时若令s=1; 则输出2^n,原因是正好符合等比公式求和公式,详见解释。
cout<< (-3)%1<< endl; //输出值为0(对于任意整数,对1取余均为0)。
//输出1-500以内的所有完数(纯C语言)
//完数(Perfect number),又称完美数或完备数,是一些特殊的自然数。
//它所有的真因子(即除了自身以外的约数)(故1不是完数)的和(即因子函数),恰好等于它本身。如果一个数恰好等于它的因子之和,则称该数为“完数”。
#include <stdio.h>
//注释掉C++写法:
//#include<iostream>
//using namespace std;
int main()
{
int a,i,s=0;
for(i=2; i<=500; i++)
{
for(a=1; a<i; a++)
{
if(i%a==0) //找出真因子
s=s+a;
}
if(i==s)
printf("%d\n",i);
//cout<<i<<endl;
s=0;
//s=1; //当s=1;时输出2^n 解释:
/* 因为对于每一个2^n来说,2^n的真因子(不包含其自身)就是2^1...到2^(n-1)次,而2^1...到2^(n-1)次求和+1正好等于2^n次(可以由等比公式求和公式推出) 对于等比公式求和公式Sn,将a1=1,q=2代入Sn+1得Sn+1=q^n(仅在a1=1,q=2情况下成立) 故有此结果2^n 等比公式资料来自百度百科:https://baike.baidu.com/item/%E7%AD%89%E6%AF%94%E6%95%B0%E5%88%97 */
}
//cout<<(-3)%1<<endl; //对于任意整数,对1取余均为0
return 0;
}
7、& 按位与, | 按位或, ^ 按位异或, ~按位取反, <<左移运算符, >>右移运算符等
//https://blog.csdn.net/weixin_42837024/article/details/98736834
#include <iostream>
int main()
{
//& 按位与 | 按位或 ^ 按位异或 ~按位取反 <<左移运算符 >>右移运算符等
auto a = 1, b = 2;
auto i1 = 10; //2进制:1010 , 10进制:10
auto i2 = 20; //2进制:10100 , 10进制:20
auto i3 = 11;
auto i = 11; //2进制: 1011 ,10进制:11
//& 按位与:
std::cout << (i1 & i2)<<std::endl; //2进制00000 10进制:0
/* 步骤: 当两个都为1时,才为1 1 0 1 0 1 0 1 0 0 --------- 0 0 0 0 0 */
std::cout << (i1 & i3); //2进制:1010 10进制:10
/* 步骤: 当两个都为1时,才为1 1 0 1 0 1 0 1 1 --------- 1 0 1 0 */
system("pause");
//| 按位或:
std::cout << (i1 | i2) << std::endl; //2进制11110 10进制:30
/* 步骤: 当有一个为1时,就为1 1 0 1 0 1 0 1 0 0 --------- 1 1 1 1 0 */
std::cout << (i1 | i3)<< std::endl; //2进制:1011 10进制:11
/* 步骤: 当有一个为1时,就为1 1 0 1 0 1 0 1 1 --------- 1 0 1 1 */
system("pause");
//^按位异或:
std::cout << (i1 ^ i2) << std::endl; //2进制11110 10进制:30
/* 步骤: 当前位的两个二进制表示不同则为1相同则为0 1 0 1 0 1 0 1 0 0 --------- 1 1 1 1 0 */
std::cout << (i1 ^ i3)<<std::endl; //2进制:1011 10进制:1
/* 步骤: 当前位的两个二进制表示不同则为1相同则为0 1 0 1 0 1 0 1 1 --------- 0 0 0 1 */
//按位取反~
//这里涉及到补码与原码的转换问题:https://zhidao.baidu.com/question/181720031.html
//https://www.cnblogs.com/zhgyki/p/9452637.html
auto x = 9; //二进制表示为0 1001,按位取反为1 0110,即符号位为负数,
//在计算机内部存储形式都是以补码形式存储,补码等于原码取反+1(符号位不变),即1 1001+1 即1 1010,即十进制表示为-10
std::cout<<(~x);
system("pause");
//<<左移运算符 >>右移运算符:
i = i << 1; //左移1位
std::cout << i << std::endl; //2进制: 10110 ,10进制:22
i = i << 1; //继续左移1位
std::cout << i << std::endl; //2进制: 101100 ,10进制:44
i3 = i3 >> 1; //右移
std::cout << i3 << std::endl; //2进制: 101 ,10进制:5
i3 = i3 >> 1; //继续右移一位
std::cout << i3 << std::endl; //2进制: 10 , 10进制:2
}
8、对于cin与scanf以及输入缓冲区的简要比较:
关于这一部分内容可参考以下博客:
C语言scanf输入时缓冲区问题
ios_base sync_with_stdio(false)引发的一些思考
关于ios::sync_with_stdio(false);和 cin.tie(0)加速c++输入输出流
scanf 与 cin 的区别
C语言isspace()函数:判断字符是否为空白字符
例:
头文件:#include <ctype.h>
定义函数:int isspace(int c);
函数说明:检查参数c是否为空格字符,也就是判断是否为空格(’ ‘)、定位字符(’ \t ‘)、CR(’ \r ‘)、换行(’ \n ‘)、垂直定位字符(’ \v ‘)或翻页(’ \f ')的情况。
返回值:若参数c 为空白字符,则返回非 0,否则返回 0。
#include <ctype.h>
#include<stdio.h>
main(){
char str[] = "123c @# FD\tsP[e?\n";
int i;
for(i = 0; str[i] != 0; i++)
if(isspace(str[i]))
printf("str[%d] is a white-space character:%d\n", i, str[i]); //这里对字符型的输出用%d格式,即将字符转换为ASCII码格式进行输出
}
reslut:
简要说明:
ios::sync_with_stdio(false);
c中的标准输入输出流sacanf ,printf,与c++中的cin ,cout有所不同。
cin、cout是输入输出流效率稍低但是书写方便,cin、cout输入输出效率比较低的原因是它们都需要先将内容存入缓存区,
用std::ios::sync_with_stdio(fasle)可以取消与stdio同步,不再存入缓存区,提高输入输出效率
若不加 ios_base::sync_with_stdio 则默认为true。
true的时候,iostream 和 stdio 共享缓冲区。
false的时候,iostream 和 stdio 分别有独立的缓冲区。
cin的问题主要是对每一个变量都要调用一次操作符函数,而scanf不用。
但是scanf要解析格式串,但是解析复杂度是线性的。
如果你只有一个变量 比如 cin>>a[i] // scanf("%d", a+i) 这种应该是cin比较快吧,从这个角度。
如果你有很多东西 比如要scanf("%u-%u-%u-%u", &a, &b, &c, &d); 这种,应该是scanf快吧。
在100000的情况下,关闭同步的cin比scanf慢0.5s左右。
一、scanf输入缓冲区测试:
#include <cstdio>
#include <cstdlib>
#include <cctype>
int main()
{
int ival1 = 0, ival2 = 0;
char ch = 't';
char ch_tmp;
scanf("%d", &ival1);
scanf("%c", &ch_tmp);
if (isspace(ch_tmp))
{
printf("%d is a whitespace right ? %d is the newline character!\n", ch_tmp, ch_tmp);
}
if (scanf("%d", &ival2) != 1)
{
printf("Damn it! ival2 cannot read input!\n");
}
for(int i=0;i<5;i++)
scanf("%c", &ch);
printf("ival1:%d ival2:%d ch:%c\n", ival1, ival2, ch);
system("pause");
return 0;
}
不加for循环进行一次输入时的测试:
加入for循环进行循环输入以便观察缓冲区内读取数据的变化:
二、cin输入缓冲区测试:
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
int ival1 = 0, ival2 = 0;
char ch = 't';
char ch_tmp;
streambuf* sb;
sb = cin.rdbuf();
cout << "sb->in_avail()---first\t" << sb->in_avail() << endl;// will print 0
cin >> ival1;// 读取并忽略有效字符之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止,该空白字符仍留在输入流中
cout << "sb->in_avail()---second\t" << sb->in_avail() << endl;// will print 1 证明空白字符'/n' 确实留在输入缓冲区中
cin >> ch_tmp;// 注意:这里与scanf的区别,此处将空白字符忽略,而不是作为有效字符
if (isspace(ch_tmp))
{
cout << ch_tmp << " is a whitespace right ?" << ch_tmp << " is the newline character!" << endl;
}
cin >> ival2;
if (! cin)
{
cout << "Damn it! ival2 cannot read input!" << endl;
}
cin >> ch;
cout << ival1 << " " << ival2 << " " << ch<<endl;
system("pause");
return 0;
}
加入for循环后进行测试:
三、可以得出结论:
scanf输入缓冲区内读取数据时如果格式不匹配,不一致的话下次scanf读取依然会从该位置进行读取,直到遇到格式匹配时进行赋值(读取输出),不会终止读取。但是cin缓冲区内如果格式不匹配则终止读取,结束缓冲区,不再从缓冲区内读取任何内容,可认为缓冲区失效了。
加入ios::sync_with_stdio(false);语句后再次进行测试:
未加入ios::sync_with_stdio(false);语句时,此时scanf缓冲区与cin缓冲区同步,cin缓冲区输入导致错误,则scanf输入输出也受到影响,故障。
加入ios::sync_with_stdio(false);语句使得scanf与cin有独立的缓冲区,则cin缓冲区故障后scanf缓冲区仍然可以输入和读取。
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
ios::sync_with_stdio(false);
int ival1 = 0, ival2 = 0;
char ch = 't';
char ch_tmp;
streambuf* sb;
sb = cin.rdbuf();
cout << "sb->in_avail()---first\t" << sb->in_avail() << endl;// will print 0
cin >> ival1;// 读取并忽略有效字符之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止,该空白字符仍留在输入流中
cout << "sb->in_avail()---second\t" << sb->in_avail() << endl;// will print 1 证明空白字符'/n' 确实留在输入缓冲区中
cin >> ch_tmp;// 注意:这里与scanf的区别,此处将空白字符忽略,而不是作为有效字符
if (isspace(ch_tmp))
{
cout << ch_tmp << " is a whitespace right ?" << ch_tmp << " is the newline character!" << endl;
}
cin >> ival2;
if (! cin)
{
cout << "Damn it! ival2 cannot read input!" << endl;
}
for(int i=0;i<5;i++)
cin >> ch;
cout << ival1 << " " << ival2 << " " << ch<<endl;
int a=3;
scanf("%d",&a);
for(int i=0;i<5;i++)
cout<<i<<endl;
cout<<"a: "<<a<<endl;
system("pause");
return 0;
}