了解之前面试不清楚的点:
宏的定义:宏定义是比较常用的预处理指令,即使用“标识符”来表示“替换列表”中的内容。标识符称为宏名,预处理的时候进行替换,有无参宏定义和有参宏定义
无参:#define 标识符 替换列表
eg:#define PI 3.123 一行写不下可以用反斜线\
#define WORD “ass\
sdd\
ass”
带参:#define 标识符(参数1,参数2,...,参数n) 替换列表
#define MAX(a,b) (a>b?a:b)
就是取a,b大值 但是要注意#define MAX (a,b) ( (a) > (b) ? (a) : (b) ) //错误的带参宏定义格式
是错误的,因为宏只是简单地文本替换,标识符和替换列表不要有空格。
宏和函数调用的区别:(宏更简单适合短的简单的)
-
宏在预编译时候替换,函数在程序运行时 函数参数检查严格,宏不检查,方便但是有类型不安全的风险
-
函数调用要分配形参空间,但是宏只是简单替换,所以可以不用分配空间。 宏替换仅是简单文本替换,不做任何语法或逻辑检查。函数在运行阶段参数需入栈和出栈操作,速度相对较慢。
-
由于宏替换是文本替换,即如果需替换的文本较长,则替换后会影响代码长度;而函数不会影响代码长度。故使用较频繁且代码量较小的功能,一般采用宏定义的形式,比采用函数形式更合适。
参考:宏定义
字符串、向量和数组
using声明:就是编译器在你给出的命名域里面把名字给找到。
比如我们的 using namespace std;
头文件不应该加入using 声明(?)要不就会把它都拷贝到头文件里面,有的时候不经意的包含,会引起名字冲突(之前写简单系统的时候有一次可能是由于命名空间重复包含,但是不包含我怎么用呢?可能有的不需要吧)
string:
表示可变长的字符序列,使用的话要包含string的头文件。
string的直接初始化(s(“value”))和拷贝初始化(s=“value”)。
直接初始化就是直接给一个值,而拷贝就是s成为value的副本,简单的时候不复杂,但是如果是复杂结构就会很麻烦
getline(is,s)
从is里面读一行给s,返回is。
int main()
{
string s;
cin>>s;//遇到空格不读
cout<<s<<end;
return 0;
}
在这里,你输入“hello world"得到的返回却是hello,因为遇到空格就不读了。
要想读取一行,可以用string下的getline while(getline(cin,s))cout<<s<<endl;
string size_type类型:之前利用的s.size(),s[i]都以为是int型 但其实是size_type类型。
*:size_type就是配套类型中的一种。它定义为与unsigned型(unsigned int获unsigned long)具有相同含义,而且保证足够大的能够存储任意的string对象的长度。string::size_type它在不同的机器上,长度是可以不同的,并非固定的长度。但只要你使用了这个类型,就使得你的程序适合这个机器。与实际机器匹配。string对象的索引也应为size_type类型。size_type
string类型也可以比大小:之前在力扣做题的时候看到题解有用 s[i]+t[j]>s[j]+t[i]
当时不理解如和比较大小。
规则如下:1.如果长度不同,而且较短的每一位都和较长的相同,就说短<长
2.如果某些位置不一致,就是那个第一个相异字符的结果。
string a="aaass";
string b="aaa";
string c="c";
这里就是a>b,c>a;
*:字面值:它的值一看便知,每个字面值变量都对应一种数据类型“0x24”十六进制“3,14159E0”浮点字面值.
string和字面值相加时,一定要保证+号一侧是string,
cctype里面的函数:isalnum©当c是字母或者数字时候为真,isdigit©,c为数字为真,isspace©,tolower©,如果c是大写字母就输出相应的小写,否则原样输出c。toupper©。
string s("Hello World!!");
decltype(s.size()) punct_cnt=0;//punct_cnt类型与s.size()相同 decltype就是拿来确定s.size()的
for(auto c:s)
if(ispunct(c))//如果是标点符号
++punct_cnt;
使用范围for语句改变字符串的字符
for(auto &c:s)
c=toupper(c);//由于&c是引用 所以可以改变字符串字符
cout<<s<<endl;
*十六进制的数字:0x表示十六进制
vector类型
vector是模板而非类型,所以由vector生成的类型要包含元素的类型。vector对象能高效增长,所以不需要在定义vector对象时设定其大小。而且需要在确知已存在的元素进行下标操作。
迭代器介绍
string s("some string");
if(s.begin()!=s.end())
{auto it=s.begin();
*it=toupper(*it);//获得s第一个字符的迭代器
}
cout<<s<<endl;
迭代器也有和常量指针差不多的 const_iterator>。记住凡是用了迭代器的循环体,都不要向迭代器所属容器添加元素。
数组
unsigner int cnt =42;//不是常量表达式
constexpr unsigned sz =42;//是常量表达式
int arr[10];//含有十个数数组
int *parr[sz];//含有十个整数指针
string bad[cnt];//错误,cnt不是整数表达式
而且数组不允许拷贝和赋值
int a[]={1,2,3};//正确
int a2[]=a;//错误 不允许初始化
a2=a;//错误 不能拿数组赋值
cstring:strcmp(p1,p2)看p1,p2是否相等,strcat(p1,p2)将p1,加到p1后面