C++杂文(1)

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
",j,i,++j);  //函数printf从右到左压栈,然后将先读取放到栈底,最后读取的放在栈顶,处理时候是从栈顶开始的,所以我们看见的结果是,从右边开始处理的。
    printf("%d
",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
",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
",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是否为空格字符,也就是判断是否为空格(’ ‘)、定位字符(’ ‘)、CR(’ ‘)、换行(’ ‘)、垂直定位字符(’ v ‘)或翻页(’ f ')的情况。
返回值:若参数c 为空白字符,则返回非 0,否则返回 0。

#include <ctype.h>
#include<stdio.h>
main(){
    char str[] = "123c @# FD	sP[e?
";
    int i;
    for(i = 0; str[i] != 0; i++)
        if(isspace(str[i]))
            printf("str[%d] is a white-space character:%d
", 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!
", ch_tmp, ch_tmp);
    }
    if (scanf("%d", &ival2) != 1)
    {
        printf("Damn it! ival2 cannot read input!
");
    }
    for(int i=0;i<5;i++)
        scanf("%c", &ch);
    printf("ival1:%d ival2:%d ch:%c
", 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	" << sb->in_avail() << endl;// will print 0
    cin >> ival1;// 读取并忽略有效字符之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止,该空白字符仍留在输入流中
    cout << "sb->in_avail()---second	" << 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	" << sb->in_avail() << endl;// will print 0
    cin >> ival1;// 读取并忽略有效字符之前所有的空白字符,然后读取字符直至再次遇到空白字符,读取终止,该空白字符仍留在输入流中
    cout << "sb->in_avail()---second	" << 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;
}

在这里插入图片描述在这里插入图片描述

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须在文章页面给出原文链接,否则保留追究法律责任的权利。
原文地址:https://www.cnblogs.com/study-hard-forever/p/14387288.html