C++ 入门

来源:互联网 发布:上海杰游网络 编辑:程序博客网 时间:2024/06/05 15:13

  • 读入一组数据文件中每行第一个数代表要读的数目n后面的n个数就是要读入的数
  • 设置精确到小数点后三位
  • 计算精度控制
  • 补码 以及输出整数内部32位二进制内码
  • 右对齐输出setw
  • 十二转换
  • 利用getline来一次性输入
  • 引用作为函数参数
  • 引用作为函数返回值
  • 计算程序运行时间
  • 输入数据加上scanfn避免segmentation fault
  • VS2013 消除_CRT_SECURE_NO_WARNINGS

读入一组数据,文件中每行第一个数代表要读的数目n,后面的n个数就是要读入的数

    #include<iostream>    #include<fstream>    using namespace std;    int main(){        ifstream cin("pr1030F.txt");        cout.precision(3);        int n;        while(cin>>n){//读入n            float sum=0;            for(int i=1,a;i<=n&&cin>>a;i++){//读入n个数字                sum+=a;            }            cout<<fixed<<sum/n<<endl;        }    }

设置精确到小数点后三位

    int sum;    cout.precision(3);    cout<<fixed<<sum<<endl;

计算精度控制

    #include<cmath>    abs(x)>1e-6;

补码, 以及输出整数内部32位二进制内码

求负整数的补码,将其对应正数二进制表示所有位取反(包括符号位,0变1,1变0)后加1。

        for(int i=31;i>=0;i--){ //method 1            cout<<(n>>i&1)? 1:0;        }        //方法一:将二进制首位移到最低位与1比较。        for(int i=0;i<=31;i++){  //method 2            cout<<(n<<i <0);        }        //方法二:将二进制要输出的位移到首位与0比较,如果是1则首位会是负的(补码性质),0则这个数是正的。

注:有符号数右移会补充最高位,左移会补零。

右对齐输出setw()

setw()是给紧跟着后面的数据预定一个空间,如果该数据小于这个空间,在左边用0补齐;setw()只对紧跟在他后面的数据有效

cout<<setw(11)<<n<<(n<0? "-->-":"-->")+s+"\n";

十二转换

//用string 除二取余    string s;    for(int a=n;a;a/=2){        s+=(a%2)? '1':'0';    }    reverse(s.begin(),s.end());    cout<<setw(11)<<n<<(n<0? "-->-":"-->")+s+"\n";//方法同上,改用vector实现//可以看出来麻烦很多    vector<int> s_rev(0);    //vector<int> s(0);    int i=0;    for(int a=n;a;a/=2){        s_rev.push_back((a%2)? 1:0);        //cout<<s_rev[i];        i++;    }    i=i-1;//用容器的时候定义的容器个数与下标会差1,debug发现的     int j;    vector<int> s(s_rev);    for(j=i;j>=0;j--){        s[i-j]=s_rev[j];    }    j+=1;//用容器的时候定义的容器个数与下标会差1     cout<<setw(11)<<n<<(n<0? "-->-":"-->");    for(j;j<=i;j++){        cout<<s[j];    }    cout<<endl;//采用整数内码特性    int i=31;    while(!(n & 1<<i)) i--;//i定位到从左到右第一个非0位置

利用getline()来一次性输入

一般用cin>>s来读取的时候总是将前面的空格滤掉;
用getline读取可以一次性输入。
getline()的原型是istream& getline ( istream &is , string &str , char delim );
其中 istream &is 表示一个输入流,譬如cin;string&str表示把从输入流读入的字符串存放在这个字符串中(可以自己随便命名,str什么的都可以);char delim表示遇到这个字符停止读入,在不设置的情况下系统默认该字符为’\n’,也就是回车换行符(遇到回车停止读入)。给大家举个例子:

    string line;    cout<<"please cin a line:"    getline(cin,line,'#');    cout<<endl<<"The line you give is:"line;

那么当我输入”You are the #best!” 的时候,输入流实际上只读入了”You are the “,#后面的并没有存放到line中(应该是在缓冲区里吧)。然后程序运行结果应该是这样的:
please cin a line:You are the #best!
The line you give is:You are the
而且这里把终止符设为#,你输入的时候就算输入几个回车换行也没关系,输入流照样会读入,譬如:
please cin a line:You are the best!
//这里输入了一个回车换行
Thank you!
# //终止读入
The line you give is:You are the best!
//换行照样读入并且输出
Thank you!

引用作为函数参数

作为函数参数时引用有两种原因:
1、在函数内部会对此参数进行修改
2、提高函数调用和运行效率

关于第一点,都知道C++里提到函数就会提到形参和实参。如果函数的参数实质就是形参,不过这个形参的作用域只是在函数体内部,也就是说实参和形参是两个不同的东西,要想形参代替实参,肯定有一个值的传递。函数调用时,值的传递机制是通过“形参=实参”来对形参赋值达到传值目的,产生了一个实参的副本。即使函数内部有对参数的修改,也只是针对形参,也就是那个副本,实参不会有任何更改。函数一旦结束,形参生命也宣告终结,做出的修改一样没对任何变量产生影响。

例如:

    void swap(int p1, int p2) //对两个变量进行交换处理。此处函数的形参为p1, p2,没有引用    {        int p;        p = p1;        p1 = p2;        p2 = p;     }    void main( )    {        int a,b;        cin >> a >> b; //输入a,b两变量的值        swap(a,b); //直接以变量a和b作为实参调用swap函数        cout << a << ' ' << b; //输出结果

你会发现输出的a和b还是你输入的值,没有交换。

如果我们改为:

void swap(int &p1, int &p2) //对两个变量进行交换处理。此处函数的形参为p1, p2都是引用{    int p;    p = p1;    p1 = p2;    p2 = p;}

再次执行,就会发现值交换了。

原理就在于采用&p1和&p2时,p1和p2是实参的别名而已,像一个指针指向实参。改变p1和p2就是改变实参的值。
关于第二点,可以结合第一点分析,p1和p2是实参的引用,不用经过值的传递机制,已经有了实参值的信息。所以没有了传值和生成副本的时间和空间消耗。当程序对效率要求比较高时,这是非常必要的.

引用作为函数返回值

说明:
(1)以引用返回函数值,定义函数时需要在函数名前加&
(2)用引用返回一个函数值的最大好处是,在内存中不产生被返回值的副本。
例如:

#include <iostream.h>float temp; //定义全局变量tempfloat fn1(float r); //声明函数fn1float &fn2(float r); //声明函数fn2float fn1(float r) //定义函数fn1,它以返回值的方法返回函数值{ temp=(float)(r*r*3.14); return temp;}float &fn2(float r) //定义函数fn2,它以引用方式返回函数值{ temp=(float)(r*r*3.14); return temp;}void main() //主函数{ float a=fn1(10.0); //第1种情况,系统生成要返回值的副本(即临时变量) float &b=fn1(10.0); //第2种情况,可能会出错(不同 C++系统有不同规定) //不能从被调函数中返回一个临时变量或局部变量的引用 float c=fn2(10.0); //第3种情况,系统不生成返回值的副本 //可以从被调函数中返回一个全局变量的引用 float &d=fn2(10.0); //第4种情况,系统不生成返回值的副本 //可以从被调函数中返回一个全局变量的引用 cout<<a<<c<<d;}

引用作为返回值,必须遵守以下规则:
(1)不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了”无所指”的引用,程序会进入未知状态。
(2)不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题,可对于这种情况(返回函数内部new分配内存的引用),又面临其它尴尬局面。例如,被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放,造成memory leak。
(3)可以返回类成员的引用,但最好是const。主要原因是当对象的属性是与某种业务规则(business rule)相关联的时候,其赋值常常与某些其它属性或者对象的状态有关,因此有必要将赋值操作封装在一个业务规则当中。如果其它对象可以获得该属性的非常 量引用(或指针),那么对该属性的单纯赋值就会破坏业务规则的完整性。
这里推荐几本书,有兴趣的朋友去看看里面关于引用的说明和注意事项:
《Effective C++》
《Thinking in C++》

计算程序运行时间

clock() 捕捉程序运行到被调用所耗费的时间,单位是 clock tick,即时钟打点。
常数CLK_TCK/CLOCKS_PER_SEC代表及其时钟每秒走的时钟打点数。

#include<time.h>clock_t start stop;//clock_t是clock()函数返回的变量类型double duration;int main(){    start = clock();//开始计时    MyFunction();//要计时的函数    stop = clock();//停止计时    duration = ((double)(stop-start))/CLK_TCK;//计算运行时间    return 0;}

输入数据加上scanf(“\n”)避免segmentation fault

输入数据时候,测试数据如果有换行输入,那就加上scanf(“\n”),避免把\n当做下一次输入造成segmentation fault
很重要!!!

VS2013 消除_CRT_SECURE_NO_WARNINGS

Warning 1 warning C4996: ‘fopen’: This function or variable may be unsafe. Consider using fopen_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
在编程过程中难免会用到一些过时,或者曾经不安全的函数,如上,这是编译器会出现warning提示用某某新函数,如果不想使用新的函数可以使用一下方法:
1. 使用VS提供的 编译器选择性提供warning功能 link: http://msdn.microsoft.com/en-us/library/2c8f766e.aspx 例:上面的错误使用 #pragma warning( disable : 4996) 即可消除。
2. 使用提示中的_CRT_SECURE_NO_WARNINGS,以下是使用方法:
a. Project properties->Configuration Properties->C/C++->Preprocessor->Preprocessor
Definitions
b. 点击按钮 (…)
c. 输入:_CRT_SECURE_NO_WARNINGS。 注:使用 “\n” 相隔
3.#define _CRT_SECURE_NO_WARNINGS
#include

0 0