变量与基本类型
- 变量初始化规则
内置型变量是否自动初始化取决于其定义的位置,定义在函数体外部的都将初始化为0,定义为函数体内部的不进行自动初始化。
类类型初始化,如果未显示提供初始化式,则调用默认构造函数初始化。
-
定义与声明
定义为变量分配内存空间,并可以指定初值,声明向程序表明的变量的类型和名字。定义的同时也进行了相应的声明。可以采用extern声明变量名而不定义它。声明可以多次,定义只能一次。 -
枚举类型
enum test {A,B,C}; -
头文件
头文件为相关的声明提供了一个集中存放的位置,头文件一般包含类的定义、extern变量声明、函数声明、const变量定义等
#include <标准头文件>
#include <自定义头文件>
标准库类型
- 标准库string类型(size()或者下标类型string::size_t)、vector、iterator、bitset类型
数组和指针
-
数组的类型不能为引用
-
数组初始化,没有显式的初始化则元素与普通变量一致,内置数据类型函数内部无初始化,外部初始化为0;类类型则调用默认构造函数
-
数组级别上不能直接复制和赋值
-
数组下标类型size_t
-
void*可以保存任意类型的指针,const类型除外,需要使用const void*
-
指针和引用的区别:引用总是指向某个对象,定义引用的时候没有初始化是错误的;赋值行为的差异,给引用赋值是修改其关联对象的值,而不是使引用与另一个对象关联
-
指针和typedef
typedef string *pstring;
const pstring cstr ;等效于 string * const cstr; 前面那个const是修饰pstring
- c风格字符串,即末尾有一个结束标志
表征函数库#include <cstring>提供如下函数
strlen(s)
strcmp(s1,s2)
strcat(s1,s2)
strcpy(s1,s2)
strncat(s1,s2,n)
strncpy(s1,s2,n)
上述函数的调用者必须保证目标字符串有足够的大小
尽可能使用string而不是上述的c风格的字符串
表达式
- 算术操作符优先级
+(正号)、-(负号)
*、/、%
+、-
- 关系操作符和逻辑操作符
!
<、<=、>、>=
==、!=
&&
||
- 位操作符
~
<<、>>
&、^、|
- 赋值操作符(右结合性)
- 自增自减操作符
- 箭头操作符
(*p).foo 等价于 p->foo !
- 条件操作符 ?:
- sizeof操作符,返回类型size_t,单位byte
sizeof(type name)
sizeof expr
sizeof(expr)
-
逗号表达式,从左到右计算,最终结果为最右边的值
-
复合表达式
优先级,结合性
基本记忆:单目>双目>三目,算术>位移>逻辑判断>位运算,条件、赋值、逻辑与或都是很低的优先级 -
类型转换
需要注意的是算术转换:所有比int小的整型,char,unsigned char,short,unsigned short,如果该类型的所有可能值都包含在int内,他们就会被提升到int型,否则提升到unsigned int。 -
显示转换(强制类型转换)
cast-name<type>(expression)
1、dynamic_cast,继承体系中,从基类到子类的转换
2、const_cast,去除const属性
3、static_cast,常用的隐式类型转换
4、reinterpret_cast,为操作数位模式提供底层次的重新解释
语句
- break语句,结束最近的while、do while、for、switch
- try块和异常处理
1、throw表达式
2、try块,如果不存在处理该异常的catch,则跳到terminate,导致程序非正常退出
try{ st1
}catch(exc1){handle1
}catch(exc2){handle2
}
- <stdexcept>头文件定义的标准异常类
最常见的问题
exception
-
运行时错误
runtime_error
range_error
overflow_error
underflow_error
逻辑错误
-
logic_error
domain_error
invalid_error
length_error
out_of_error
- 使用预处理器进行调试
int main()
{
#ifndef NDEBUG
cerr<<"test"<<endl;
#endif
}
可以通过定义NDEBUG删除上述调试语句
同时预处理器还提供了一些有用的常量
__FILE__文件名
__LINE__当前行号
__TIME__文件被编译的时间
__DATE__文件被编译的日期
还有一个有用的工具是assert(断言)预处理宏,频繁的调用会极大的影响程序的性能,增加额外的开销。在调试结束后,可以通过在包含#include <assert.h>的语句之前插入 #define NDEBUG 来禁用assert调用。
一个非常简单的使用assert的规律就是,在方法或者函数的最开始使用,如果在方法的中间使用则需要慎重考虑是否是应该的。方法的最开始还没开始一个功能过程,在一个功能过程执行中出现的问题几乎都是异常。
函数
-
primer中介绍的例子为求取最大公约数,采用辗转求余法飞(small,big)==>(big%small,small)..........
递归形式可以这样写
int gcd(int small,int big){
if(small!=0) return gcd(big%small,small);
return big;
} -
void fcn(const int i)
void fcn(int i)
这两个没有构成重载,编译器认为后面那个重新定义了前面的函数,会出错,原因:对c的兼容 -
int *&v——这是一个指向int型的指针的引用
-
通常,函数不应该有vector或其他标准容器类型的形参,这是为了避免其复制vector的每一个元素(解决,使用const引用),更加合理的是使用容器的迭代器作为形参,传递容器内的值
-
使用数组名字时,数组名字会自动转换为指向数组第一个元素的指针
-
使用引用传递数组时,会严格检查数组的大小
void printValues(int (&arr)[10]) -
多维数组传递方法
void printValues(int (*a)[10],int n);
void printValues(int a[][10],int n); -
数组传递的两种常用方法
void printValues(int *begin, int *end);
void printValues(const int a[],int size); -
main(int argc, int **argv)
argc——传递参数个数
argv——指向传递的参数,通常第一个为程序名字 -
main 函数如果要求返回值,如果没有自己写的话,编译器会自己插入一个返回0 ,对于main函数返回0通常表示运行成功
-
默认实参可以在声明的时候指定,也可以在定义的时候指定,但是只能指定一次。
-
内联函数需要放在头文件中
-
重载函数:出现在相同的作用域中,如果两个函数的名字相同,形参表不同(除去const(这里有个例外const应用和指针会导致的不同会引起重载)、默认实参导致的不同),则称其为重载函数
-
重载确定三步骤
1、候选函数
2、选择可行函数
3、寻找最佳匹配 -
返回指向函数的指针
int (*ff(int))(int *, int)
标准IO库
-
iostream——对流进行读写
fstream ——对文件进行读写
sstream ——对string对象进行读写 -
IO对象不可复制和赋值,表明
1、只有支持复制的元素类型才能放置在容器内,故不能将流对象存储在vector中
2、在函数中传递或者返回IO对象时,必须使用指向的对象指针或者引用 -
导致while(cin>>i)终止的原因
1、系统级故障
2、输入无效的数据
3、遇到文件结束符 -
每个IO对象都管理了一个缓存区,用于存储对象读写的数据,当发生如下情况导致缓存区数据刷新,即写读入真正的设备或者文件
1、程序结束
2、缓存区满了,则在写下一个值之前会被刷新
3、显示刷新,如使用endl,unitbuf
4、将输出流与输入流关联起来 -
利用字符串流istringstream,ostringstream,stringstream实现一个句子倒序输出,头文件<sstream>
//字符串逆序
string inputLine;
getline(cin,inputLine);
istringstream inputLineStream(inputLine);
string word;
vector<string> wordVec;
while(inputLineStream>>word)
wordVec.push_back(word);
//逆序打印
vector<string>::reverse_iterator rit = wordVec.rbegin();
while(rit!=wordVec.rend())
{
if (rit == wordVec.rbegin())
cout<<*rit++;
else
cout<<" "<<*rit++;
}
cout<<endl;
- 文件操作示例,包括ifstream,ofstream,fstream头文件<fstream>
文件模式
in读权限
out写权限,文件会被清空,同时以in和out打开不清空
app追加
ate定位文件尾
trunc清空打开的文件内容
binary二进制打开
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
using namespace std;
const int FILE_NUM = 5;
int main()
{
//建立文件名
vector<string> svec;
string s("file");
for (int i = 0; i<FILE_NUM; i++)
{
stringstream filename;
filename<<"file"<<i<<".txt";
svec.push_back(filename.str());
}
//打开文件并写入数据
ofstream ofile;
for(vector<string>::iterator it = svec.begin();it!=svec.end();it++)
{
ofile.open(it->c_str());
if (!ofile)
{
cerr<<"open out file failed!";
system("pause");
return -1;
}
stringstream text;
text<<"this is "<<it->c_str()<<endl;
ofile<<text.str();
ofile.close();
ofile.close();
}
//读取内容
ifstream ifile;
for(vector<string>::iterator it = svec.begin();it!=svec.end();it++)
{
ifile.open(it->c_str());
if (!ifile)
{
cerr<<"open in file failed!";
system("pause");
return -1;
}
string line,word;
vector<string> wordvec;
getline(ifile,line);//获取一行数据
istringstream linestream(line);
while (linestream>>word)
wordvec.push_back(word);
ifile.close();
ifile.clear();
//打印
vector<string>::reverse_iterator rit = wordvec.rbegin();
while(rit!=wordvec.rend())
{
cout<<*rit<<" ";
rit++;
}
cout<<endl;
}
system("pause");
}
网友评论