C++编程思想笔记(1)

变量声明的语法
extern关键字表示变量是在文件以外定义的,或在文件后面部分才定义。
extern int a; //在变量定义前加extern关键字表示声明一个变量但不定义它。extern也可以用于函数的声明,但这对函数来说是多余的。

包含头文件
包含头文件,要使用#include预处理命令。它告诉预处理器打开指定的头文件并在#include语句所在的地方插入头文件。
#include<>,用尖括号来指定文件时,预处理器是以特定的方式来寻找文件,一般是环境中或编译器命令行指定的某种寻找路径,这种设置寻找路径的机制随机器,操作系统,c++实现的不同而不同,如#include<iostream>从“inlcude”目录下开始寻找。
#inlcude"",用双引号时,预处理器通常是从当前目录开始寻找,如果文件没有找到,那么include命令就按与尖括号同样的方式重新开始寻找。

C++ include语句格式
从c继承下来的带有传统“.h”扩展名的库仍然可用,然而,也可以在文件名前加一个字母"c"。这样
#include<stdio.h>
就变成
#incldue<cstdio>
新的包含格式和老的效果是不一样的,使用.h的文件是老的,非模板化的版本,而没有.h的文件是新的模板化版本。如果在同一程序中混用这两种形式,会遇到某些问题。

使用iostream类

iostream类包自动定义了一个名为cout的变量(对象),它接受所有与标准输出绑定的数据。
cout << "howdy!";
意思就是把字符串 "howdy!" 发送到cout对象(cout是“控制台输出(console output)”的简写),然后cout对象按从左向右的顺序将参数打印出来。
cin对象代表控制台输入。

名字空间
namespace关键字,库或程序中的每一个C++定义集被封装在一个名字空间中,如果其他的定义中有相同的名字,但它们在不同的名字空间,就不会产生冲突。所有的标准C++库都封装在一个名字空间中,即“std”(代表standard),可以用关键字 “using” 来使用这个名字空间中的声明和定义,即using namespace std;
过去典型包含头文件的方式是带上".h",那时,名字空间不是语言的一部分。所以队已经存在的代码要提供向后兼容,如给出
#include <iostream.h>

它相当于
#include <iostream>
using namespace std;


字符数组的拼接

如果两个加引号的字符数组邻接,并且它们之间没有标点,编译器就会把这些字符数组连接成单个字符数组。如
#incldue <iostream>
using namespace std;
int main(){
    cout << "This is fat too long to put on a "
      "single line but it can be broken up with "
      "no ill effects\nas long as there is no "
      "punctuation separating adjacent character "
      "arrays.\n";
}


文件的读写

为了打开文件进行读写操作,必须包含<fstream>。显然<fstream>会自动包含<iostream>,但如果打算使用cin,cout,最好还是显式地包含<iostream>。
为了读而打开文件,要创建一个ifstream对象,它的用法和cin相同,为了写而打开文件,要创建一个ofstream对象,用法与cout相同。
iostream库中的getline()函数可以把一行读入到string对象中(以换行符结束)。getline()的第一个参数是ifstream对象,从中读取内容,第二个参数是stream对象。函数调用完成之后,stream对象就装载了一行内容。

//将一个文件scopy.cpp的内容拷贝到另一个文件scopy2.cpp,一次循环拷贝一行
#include<iostream>
#include<string>
#include<fstream>
using namespace std;

int main(){
    ifstream in("scopy.cpp");  //open for reading
    ofstream out("scopy2.cpp");  //open for writing
    string s;
    while(getline(in,s))  //getline第一个参数是ifstream对象,从中读取内容,第二个参数是stream对象。
                            //函数调用完成之后,string对象s就装载了一行内容。
        out << s << "\n";
    return 0;
}

//把整个文件拷贝成vector数组,再输出到屏幕

#include<iostream>
#include<string>
#include<fstream>
#include<vector>
using namespace std;

int main(){
    vector<string> v;
    ifstream in("fillvector.cpp");
    string line;
    while(getline(in,line))
        v.push_back(line);
    for(unsigned i=0;i<v.size();i++)
        cout<<i<<": "<<v[i]<<endl;
    return 0;
}
//将一个文件的内容拷贝到vector数组,把输入分解成由空格分隔的单词而不是一些行
#include<iostream>
#include<string>
#include<fstream>
#include<vector>
using namespace std;

int main(){
    vector<string> words;
    ifstream in("getword.cpp");  //open for reading
    string word;
    while(in >> word)  //使用iostream中的操作符>> 代替getline()函数
        words.push_back(word);
    for(unsigned i=0;i<words.size();i++)
        cout<<words[i]<<endl;
    return 0;
}

说明符
用sizeof()运算符显示用字节表示的数据类型大小

修改外部对象
通常,向函数传递参数时,在函数内部生成该参数的一个拷贝。这称为按值传递。
#include<iostream>
using namespace std;

void f(int a){
    cout<<"a="<<a<<endl;
    a=5;
    cout<<"a="<<a<<endl;
}

int main(){
    int x=47;
    cout<<"x="<<x<<endl;
    f(x);
    cout<<"x="<<x<<endl;
}
在函数调用期间为变量a分配临时空间,拷贝x的值给a来初始化它,这可以通过打印结果得到验证。但是f()调用结束时,分配给a的临时空间就消失了,我们可以看到,在a和x之间的曾经发生过的唯一联系,是在把x的值拷贝到a的时候。
通过给函数传递指针可以允许函数修改外部对象。即void f(int *a),调用的时候f(&x);

C++引用
C++中增加了另外一种给函数传递地址的途径,就是按引用传递,即void f(int &a)。尽管这看起来像是一般的按值传递,但实际上引用的作用是传递地址,而不是值的一个拷贝。按引用传递允许一个函数去修改外部对象,就像传递一个指针所做的那样。


静态变量
通常,函数中定义的局部变量在函数作用域结束时消失,当再次调用这个函数时,会重新创建该变量的存储空间,其值会被重新初始化。如果想使局部变量的值在程序的整个生命期里仍然存在,我们可以定义函数的局部变量为static(静态的),并给它一个初始值。初始化只在函数第一次调用时执行。static变量的优点是在函数范围之外它是不可用的,所以它不能被轻易地改变。static的第二层意思和前面的含义相关,即在某个作用域外不可访问。

预处理宏介绍

#include<iostream>
using namespace std;

//定义宏。只要在调用宏的地方,预处理程序就删除名字PRINT并替换代码。
#define PRINT(STR,VAR) \
    cout<<STR "=" <<VAR<<endl;

int main(){
    int i,j,k;
    cout<<"enter an integer: ";
    cin>>j;
    cout<<"enter another integer: ";
    cin>>k;
    PRINT("j",j);
    PRINT("k",k);
    i=j+k; PRINT("j+k",i);
    j%=k; PRINT("j%=k",j);
    return 0;
}
使用宏PRINT()可以节省输入,传统上用大写字母来命名预处理宏以便突出它,宏可能会变得危险。跟在宏名后面的括号总的参数会被闭括号后面的所有代码代替。只要在调用宏的地方,预处理程序就删除名字PRINT并替换代码。


位运算
位运算只适用于整型char、int、long。
如果输入位都是1,则与运算(&)在结果位上产生1,否则为0.如果两个输入位有一个是1,则或运算(|)在结果位上产生1,当两个输入位都是0时,结果位才为0.如果两个输入位之一是1而不是同时为1,则异或运算xor(^)的结果位为1。

移位运算
左移位运算符(<<)引起运算符左边的操作数向左移动,移动位数由运算符后面的操作数指定。右移位运算符(>>)引起运算符左边的操作数向右移动,移动位数由运算符后面的操作数指定。

用typedef命名别名
typedef表示“类型定义”,但用“别名”来描述可能更精确,因为这正是它真正的作用。它的语法是
typedef 原类型名 别名;

struct
struct structure1{
    char c;
    int i;
}

int main(){
    struct structure1 s1,s2;
}
上面的例子表明,当定义变量时,不能只说structure1,必须说struct structure1。故可以使用typedef来命名别名。
在C中可以:
typedef struct {
    char c;
    int i;
} structure1;

int main(){
    structure1 s1,s2;
}
在C++中:

typedef struct structure1{
    char c;
    int i;
} structure1;

int main(){
    structure1 s1,s2;
}
这时可以重复struct的名字,就像struct名和typedef一样。实际上,struct的名字不必和typedef的名字相同,但是,一般使用相同的名字,为了使得事物更简单。


指针算术
指针常用的运算符是++————“给指针加1”。它的实际意义是改变指针移向“下一个值的地址”。
不能把两个指针相加,如果使指针相减,其结果是两个指针之间相隔的元素的个数。不过,一个指针可以加上或减去一个整数。

把变量和表达式转换成字符串
写调试代码的时候,编写由包含变量名和后跟变量的字符数组组成的打印表达式是很乏味的。幸运的是,标准C具有字符串化运算符“#”。在一个预处理宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组。把这一点与没有插入标点符号的若干个字符数组结合而连接成一个单独的字符数组,能够生成一个十分方便的宏用于调试期间打印出变量的值:
#define PR(x) cout << #x "=" << x << "\n";
如果调用宏PR(a)来打印变量a的值,它和下面的代码有同样的效果:
cout << "a=" <<a << "\n";


定义函数指针

要定义一个指针指向一个无参数无返回值的函数,可以写成:
void (*funcPtr)();
读懂复杂声明的方法:当看到像这样复杂的定义时,最好的处理方法是从中间开始和向外扩展。从中间开始的意思是从变量名开始,这里指funcPtr,向外扩展表示先注意右边最近的项(在这里没有该项,以右括号结束),然后注意左边(左边为一个星号,表示指针),注意右边(即(*funcPtr)的右边,为空参数表,表示这个函数没有带任何参数),再注意左边(void指示函数没有返回值),大多数声明都是以右-左-右动作的方式工作的。
故这个声明表示funcPtr是一个指针,它指向一个不带参数并返回void的函数。
这里有个问题,如果*funcPtr不使用括号,编译器会看到:
void *funcPtr();
这可能是在声明一个函数(返回一个void*)而不是定义一个变量。

使用函数指针
一旦定义了一个函数指针,在使用前必须给它赋予。一个数组arr[10]的地址是由不带方括号的这个数组的名字(arr)产生的。函数func()的地址也是由没有参数列表的函数名(func)产生的,也可以使用更加明显的语法&func()。
#include<iostream>
using namespace std;

void func(){
    cout << "func() called..." <<endl;
}

int main(){
    void (*fp)();  //函数指针的声明
    fp=func;   //fp指针指向func函数的地址
    (*fp)();   //用指针调用函数
    void (*fp2)()=func; //声明并初始化
    (*fp2)();
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值