| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 5058 人关注过本帖, 1 人收藏
标题:C++ Primer Plus 学习中,不时更新一些自己感觉有趣,初学者可能还不知道的 ...
只看楼主 加入收藏
wengbin
Rank: 10Rank: 10Rank: 10
来 自:陕西西安
等 级:贵宾
威 望:19
帖 子:370
专家分:1846
注 册:2015-5-8
结帖率:100%
收藏(1)
 问题点数:0 回复次数:17 
C++ Primer Plus 学习中,不时更新一些自己感觉有趣,初学者可能还不知道的小知识,也算是自己的学习笔记吧
1.C++11新增循环:基于范围(range-based)的for循环,简化了一种常见的循环任务:对数组(或容器,如vector和array)的每个元素执行相同的操作。
如:
double prices[5]{4.99,10.98,6.87,7.99,8.48};
for (double x:prices)
    cout<<x<<std::endl;

其中,x最初表示数组prices的第一个元素。显示第一个元素后,不断执行循环,x依次表示数组的其他元素。
要修改数组的元素时,使用语法:
for (double &x: prices)
    x=x*0.80;


还可结合使用基于范围的for循环和初始化列表:
for (int x:{3,5,2,8,9})
    cout<<x<<" ";
cout<<endl;

这种循环主要用于各种模版容器类。


2.常见的字符输入做法:
程序代码:
char ch;
cin.get(ch);
while(cin.fail()==false)
{
    ...//do stuff
    cin.get(ch);//attemp to read another char
}
//可以在上述代码中使用一些简捷方式,!算符可将true切换为false,或将false切换为true,可以使用此算符将上述while测试改写成:
while(!cin.fail())//while input has not failed
//方法cin.get(char)的返回值是一个cin对象.然而,istream类提供了一个可以将istream对象(如cin)转换为bool值的函数。
//当cin出现在需要bool值的地方(如循环的没条件测试中),时文该转换函数将被调用,另外,如果一次读取成功了,
//没转换得到的bool值为true,否则为false,所以,上述循环测试可以写为这样:
while(cin)//while input is successful
//最后,由于cin,get(char)的返回值为cin,因此可以将循环精简为:
while(cin.get(ch))//while input is successful
{
    ...//do stuff
}//这样,cin.get(char)只被调用一次,而不是两次:循环前一次,循环结束后一次。


3.写入到文本文件
程序代码:
//必须包含头文件fstream。
//头文件fstream定义了一个用于处理输出的ofstream类(cout便是头文件iostream预定义(声明)好的一个名为cout的ofstream对象)。
//需要声明一个或多个ofstream对象,并命名。
//必须指明名称空间。比如为使用ofstream类,必须使用编译指令using,或前缀std::。
//需要将自己定义好的ofstreamc对象与文件关联起来,方法之一是使用open()方法。
//使用完文件后,应用方法close()奖其关闭
//声明一个ofstream对象并将其同文件关联后,便可以像使用cout那样使用它。
#include <iostream>
#include <fstream>
int main()
{
    using namespace std;
    ofstream outFile;//fostream对象的定义
    outFile.open("fish.txt");//关联文件
    for(int i=0;i<10;i++)
    {
        outFile<<i<<"\t";
    }
    outFile<<endl<<"Done.";
    outFile.close();//关闭文件
    return 0;
}
//或者像这样:
#include <iostream>
#include <fstream>
int main()
{
    //using namespace std;
    std::ofstream outFile;//fostream对象的定义
    outFile.open("fish.txt");//关联文件
    for(int i=0;i<10;i++)
    {
        outFile<<i*2<<"\t";
    }
    outFile<<std::endl<<"Done.";
    outFile.close();
    return 0;
}



4.读取文本文件
程序代码:
///必须包含头文件fstream.
///头文件stream定义了了用于处理输入的类ifstream
///需要声明一个或多个ifstream对象,并命名
///必须指明名称空间。比如为使用ifstream类,必须使用编译指令using,或前缀std::。
///需要将自己定义好的ifstreamc对象与文件关联起来,方法之一是使用open()方法。
///使用完文件后,应用方法close()奖其关闭
///可结合使用ifstream对象和get()方法来读取一个字符,使用ifstream对象和getline()读取一行字符。
///可结合使用ifstream对象和eof(),fail()等方法来判断输入是否成功
///ifstream对象本身被用作测试条件时,如果最后一个读取操作成功,它将被转换为bool型值true,否则为false.
///声明一个ifstream对象并将其同文件关联后,便可以像使用cin那样使用它。
/**声明对象与关联文件的方法
ifstream inFile;
ifstream fin;//对象的定义

inFile.open("bowling.txt");
char filename[50];
cin>>filename;
fin.open(filename);//文件的关联

double wt;
inFile>>wt;//reading a number from bowling.txt
char line[81];
fin.getline(line,81);//read a line of text
//对象的使用

///检测文件是否成功打开的方法:
inFile.open("bowling.txt");
if(!inFile.if_open())//如果文件成功打开,is_open()返回true。
{
    exit(EXIT_FAILURE)//exit()被定义于头文件cstdlib中,作用是终止程序
}
**/#include<iostream>
#include<fstream>
#include<cstdlib>
const int SIZE=60;
int main()
{
    using namespace std;
    char filename[SIZE];
    ifstream inFile; // object for handling file input
    cout << "Enter name of data file: ";
    cin.getline(filename, SIZE);
    inFile.open(filename); // associate inFile with a file
    if (!inFile.is_open()) // failed to open file
    {
        cout << "Could not open the file " << filename << endl;
        cout << "Program terminating.\n";
        exit(EXIT_FAILURE);
    }
    double value;
    double sum = 0.0;
    int count = 0; // number of items read
    inFile >> value; // get first value
    while (inFile.good()) // while input good and not at EOF
    {
        ++count; // one more item read
        sum += value; // calculate running total
        inFile >> value; // get next value
    }
    if (inFile.eof())
        cout << "End of file reached.\n";
    else if (inFile.fail())
            cout << "Input terminated by data mismatch.\n";
        else
            cout << "Input terminated for unknown reason.\n";
    if (count == 0)
        cout << "No data processed.\n";
    else
    {
        cout << "Items read: " << count << endl;
        cout << "Sum: " << sum << endl;
        cout << "Average: " << sum / count << endl;
    }
    inFile.close(); // finished with the file
    return 0;
}


txt文件自己命名,内容为:
18 19 18.5 13.5 14
16 19.5 20 18 12 18.5
17.5


/////////17.5后面最好有个回车,不然可能不会读取17.5


5.const关键字:
void show_array(const double ar[],int n)
const只表明此调用将ar[]看作只读数据,不能在此调用中改变其值,并不表明ar[]是常量数组。
int age=39;
const int *pt=&age;//声明pt指向一个const int,因此不能用pt来修改这个值,也就是说*pt是一个const值,不能被修改,对pt而言,其指向值为常量,但被指向的量不一定为常量,如此处,age不是常量,可以改变age的值,但不能通过改变*pt来改变age的值


6.函数指针
程序代码:
#include<iostream>
double add(double x,double y){return x+y;}//加法
double multi(double x,double y){return x*y;}//乘法,两个函数的共同点是参数列表一致
double calculate(double m,double n,double (*pf)(double p,double q)){return (*pf)(m,n);}//计算函数,传递两个待计算的数,并用指向函数的指针调用计算函数

int main()
{
    typedef double (*pFunc)(double,double);//定义指针函数
    pFunc pa[2]{add,multi};//指向函数的指针数组并初始化为相关函数地址
    std::cout<<"Enter two numbers: ";
    double m,n;
    while(std::cin>>m>>n)
    {
        std::cout<<"add:"<<calculate(m,n,pa[0])<<std::endl;//做加法
        std::cout<<"multi:"<<calculate(m,n,pa[1])<<std::endl;//做乘法
    }
    std::cout<<"Down!\n";
    return 0;
}//可见指向函数的指针还是有一定优势的,能减小代码量,简化写法


[此贴子已经被作者于2016-1-15 11:24编辑过]

搜索更多相关主题的帖子: 知识 元素 
2016-01-05 12:00
yangfrancis
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:贵宾
威 望:141
帖 子:1510
专家分:7661
注 册:2014-5-19
收藏
得分:0 
矢量专用的吧。貌似
2016-01-05 12:21
wengbin
Rank: 10Rank: 10Rank: 10
来 自:陕西西安
等 级:贵宾
威 望:19
帖 子:370
专家分:1846
注 册:2015-5-8
收藏
得分:0 
回复 2楼 yangfrancis
数组也是可以的
2016-01-05 14:51
eFun
Rank: 6Rank: 6
等 级:禁止访问
威 望:1
帖 子:58
专家分:400
注 册:2015-12-27
收藏
得分:0 
2016-01-05 15:11
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:0 
以下是引用wengbin在2016-1-5 14:51:37的发言:

数组也是可以的
编译器是按照如下流程做的:
1. 如果是数组,……
2. 如果此类有begin/end成员函数
3. 如果此类能作为std::begin/std::end函数的参数
2016-01-05 16:28
wengbin
Rank: 10Rank: 10Rank: 10
来 自:陕西西安
等 级:贵宾
威 望:19
帖 子:370
专家分:1846
注 册:2015-5-8
收藏
得分:0 
我来自己顶一下,免得找不着了
2016-01-15 11:25
wengbin
Rank: 10Rank: 10Rank: 10
来 自:陕西西安
等 级:贵宾
威 望:19
帖 子:370
专家分:1846
注 册:2015-5-8
收藏
得分:0 
7.创建引用变量
程序代码:
int rats;
int & rodents=rats//makes rodents an alias for rats
//其中,&不是地址运算符,而 类似标识符的一部分。就像声明中的char*指的是指向char的指针一样,int & 指的是指向int的引用。上述声明允许将rats和rodents互换——它们指向相同的值和内存单元
//简单点吧,我的理解就是定义了现个变量,内存块大小一样,首地址一样呗?
//主要用途:作函数形参,可以访问和修改原始数据

//对C用户,会想到指针:
int rats=101;
int & rodents=rats;//这申明的是一个变量
int * prats=&rats;//这是一个指针
//这样的结果是rodents和*prats都可以同rats互换,而&rodets和prats可以互换。从而使得引用看上去很像伪装表示的指针。
//二者的不同点:1.不同的表示方法(费话)。2.必须在声明引用时将其初始化,而指针则不必如此
int rats;
int & rodents;
rodents=rats;//这样是不可以的
int *prats;
prats=&rats;//而这是可以的
//引用更接近const指针,必须在创建时进行初始化,一旦与某个变量关联,将一址效忠:
int & rodents=rats;//其实是如下代码的伪装表示:
int * const pr=&rats;//rodents扮演的角色与*pr相同

以上引用变量称为左值引用,C++11新增右值引用:
程序代码:
double && rref=std::sqrt(36.00);//not allowed for double&
double j=15.0;
double &&jref=2.0*j+18.5;//not allowed for double&
std::cout<<rref<<"\n";//didplay 6.0;
std::cout<<jref<<"\n";//didplay 48.5;


特别贴上T版的教导:C++的string類,是一個引用,事實上在多次編輯字符串動作之後,這個串的內存入口地址是可能會變化的(它使用了realloc()函數重新分配空間,故對大內存字符串進行大量編輯尤其是涉及長度擴張的動作,有時會出現呆滯現象,因此它有一個遞進的緩衝區,真實佔用內存不是表面上那個尺度的)。由於字符串的內存空間會改變,所以在C++中經常勸誡程序員少用指針,也是這個緣故。對象的地址變了,指針的値也變,但是指向對象的指針卻可能不止一個,於是你得把所有這些指向同一個對象的指針都同步起來(那工作量嚇死你),引用卻不會,它不管對象地址變到哪了,都是直接這個對象的真身,而指針就像孫悟空的毫毛化身。用C寫多了程序,自然會遇到這些問題,才會感受到C++這種改變的精粹是什麽,所有新型語言,都力戒用指針,道理也在這裏。在這裏提到指針和引用,與樓主新帖提及引用的理解有關,把引用理解爲指針模型,那就是偏差。

8.ostream类的部分成员函数:
对于ostream & os;
os.precision(0):指定显示小数点后0位
os.setf():设置格式化状态:os.setf(ios_base::fixed)将对象置于使用定点表示法的模式,os.setf(ios_base::showpoint)将对象置于显示小数点的模式,即使小数部分为0,所有这些设置都将一直保持不变,直到重新调用重新分配显示格式,os.withs(15):设置下一次输入操作使用的字段宽度,一次性有效,默认宽度为0,即正好容纳要显示的内容。

[此贴子已经被作者于2016-1-19 10:05编辑过]

2016-01-15 14:24
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 6楼 wengbin
你對引用的理解有偏差

授人以渔,不授人以鱼。
2016-01-15 21:57
wengbin
Rank: 10Rank: 10Rank: 10
来 自:陕西西安
等 级:贵宾
威 望:19
帖 子:370
专家分:1846
注 册:2015-5-8
收藏
得分:0 
9.默认参数:
默认参数指的是函数调用中省略了实参时自动使用的一个值。如果将void wow(int n)设置成n有默认值为1,则函数调用wow()相当于wow(1)。
方法:在函数原型中,将值赋给原型中的形参,如:char* left(const char* str,int n=1);
程序代码:
//对于带参数列表的函数,必须从右向左添加默认值:
int harpo(int n,int m=4,int j=5);//可以的
int chico(int n,int m=6,int j);//不可以的
//实参按从左到右的顺序依次被赋给相应形参,而不能跳过任何参数
int beeps=harpo(2);//相当于harpo(2,4,5)
int beeps=harpo(1,8);//相当于harpo(1,8,5)
//在类的设计中,通过默认参数可以减少要定义的析构函数,方法以及方法重载的数量


10.关键字decltype(C++11)
程序代码:
int x;
decltype(x)y;//使y与x同类型,给decltype提供的参数可以是表达式
decltype(x+y)xpy=x+u;//使xpy与x+y同类型并将x+y的值赋给xpy
//此关键字可用于函数模版中:

template<typename T1,typename T2>
void ft(T1 x,T2 y)
{
    ...
    decltype(x+y)xpy =x+y;//在不能确定xyp类型时可以用此关键字保证模版可被顺利具体化
    ...
}
//如果需要多次声明,可结合使用typedef
template<typename T1,typename T2>
void ft(T1 x,T2 y)
{
    ....
    typedef decltype(x+y) xytype;
    xytype xpy=x+y;
    xytype arr[10];
    xytype & rxy=arr[2];
    ....
}


11.另一种函数声明语法(C++11后置返回类型)
有一个与10相关的问题是decltype本身无法解决的:
程序代码:
template<typename T1,typename T2>
?type?gt(T1 x,T2 y)
{    
    ....
    return x+y//在函数开头处还未声明x和y,所以无法用decltype关键字定义回返类型,无法定义返回类型
}

C++新增了一种声明和定义函数的方法,工作原理如下:
程序代码:
double h(int x,float y);
//可以写成:
auto h(int x,float y) ->double;//将返回类型移到参数后面,->double被称为后置返回类型,auto是一个占位符,这种语法也可用于函数定义
//对于上述返回值问题:
template<typename T1,typename T2>
auto gt(T1 x,T2 y) ->decltype(x+y)
{    
    ....
    return x+y//decltype在参数声明后面,x和y位于作用域内,可以被使用
}


[此贴子已经被作者于2016-1-20 11:28编辑过]

2016-01-19 10:46
TonyDeng
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:贵宾
威 望:304
帖 子:25859
专家分:48889
注 册:2011-6-22
收藏
得分:0 
回复 8楼 wengbin
最後一句註釋是你自己的話?

授人以渔,不授人以鱼。
2016-01-19 19:13
快速回复:C++ Primer Plus 学习中,不时更新一些自己感觉有趣,初学者可能还不知 ...
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.021738 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved