C\C++常识

数据格式详解:

  2^8=256 

  2^10=1024

  2^16=65536(32768)

C语言int的取值范围在32/64位系统中都是32位,范围为-2147483648~+2147483647,无符号情况下表示为0~4294967295。共有10位,十亿水平。

INT_MIN和INT_MAX分别表示有符号基本整型的最小值和最大值

随便写几个输出格式记着:%.3lf,%03d,%6d

枚举类型的元素长度根据编译器而定。在visual c++下,它和int一样长,是4个字节,在GCC下它会取尽可能短的长度,例如你这个枚举类型只有3种标识,那么它是一个字节

二进制是0b开头,八进制是0什么什么,十六进制是0x什么什么,如果在int前面加上0,那么就不再是十进制的,而是八进制的。

创建链表的时候,一定要给最后设置NULL,不然是会乱指的,C语言不会初始化指针的。在C++中,如果创建一个结构体指针不设NULL,同样会乱指。

c语言不会用&作为函数参数,但C++可以,代表地址,也就是说,可以完全相当于*,但是,如果是直接的常量,写死在内存上,那么就会报错,而*则不会出现这种问题,说白了就是一种自带注释的写法,但关键是,&更方便,代码更易懂。

  • 编译器隐式执行的任何类型转换都可以由static_cast来完成,比如int与float、double与char、enum与int之间的转换等。当编译器隐式执行类型转换时,大多数的编译器都会给出一个警告,使用static_cast可以明确告诉编译器,这种损失精度的转换是在知情的情况下进行的,也可以让阅读程序的其他程序员明确你转换的目的而不是由于疏忽。
  • 用法:使用static_cast可以找回存放在void*指针中的值。一般用于malloc,它的返回值正是void*,这叫自带解释。。
  • double * dptr = static_cast<double*>(vptr);

C11增加了一些新特性,and,or,not 何以取代&& || !真方便!

指针从本质上讲是一个变量,变量的值是另一个变量的地址,指针在逻辑上是独立的,它可以被改变的,包括指针变量的值(所指向的地址)和指针变量的值对应的内存中的数据(所指向地址中所存放的数据)。

  引用从本质上讲是一个别名,是另一个变量的同义词,它在逻辑上不是独立的,它的存在具有依附性,所以引用必须在一开始就被初始化(先有这个变量,这个实物,这个实物才能有别名),而且其引用的对象在其整个生命周期中不能被改变,即自始至终只能依附于同一个变量(初始化的时候代表的是谁的别名,就一直是谁的别名,不能变)。引用在定义时需要加上&,而在使用时不用加&

用assert启用断言,一般是对预计可能出现的错误函数参数或者溢出变量进行判断,需要时添加#include <assert.h> 不用时添加#define NDEBUG

for(expression : struct) 完全也可以用普通数组这个语法糖,但是指针就不行

在C++中,结构体可以直接相等赋值(里面没有指针),这个叫浅拷贝,如果有指针的话,可以预见,它们将使用同一地址,如果要拷贝,就应该开辟新的地址,放入新的数据,封装在单独的函数中执行即可

struct MyStruct t1 = {1, 2, "hello"};可以这样算

数据结构

早在C++98标准中就存在了auto关键字,那时的auto用于声明变量为自动变量,自动变量意为拥有自动的生命期,这是多余的,因为就算不使用auto声明,变量依旧拥有自动的生命期,C++98中的auto多余且极少使用,C++11已经删除了这一用法,取而代之的是全新的auto:变量的自动类型推断。auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型

auto默认是by-value方式

C++的struct可以放入函数,但是C语言的不行

1.C++有一个标准模板库STC,里面有各种数据结构

map的值是按照key升序排列的,也就是说,自动排列

 map的基本操作函数:
      C++ Maps是一种关联式容器,包含“关键字/值”对
      begin()          返回指向map头部的迭代器
      clear()         删除所有元素
      count()          返回指定元素出现的次数
      empty()          如果map为空则返回true
      end()            返回指向map末尾的迭代器
      equal_range()    返回特殊条目的迭代器对
      erase()          删除一个元素
      find()           查找一个元素
      get_allocator()  返回map的配置器
      insert()         插入元素
      key_comp()       返回比较元素key的函数
      lower_bound()    返回键值>=给定元素的第一个位置
      max_size()       返回可以容纳的最大元素个数
      rbegin()         返回一个指向map尾部的逆向迭代器
      rend()           返回一个指向map头部的逆向迭代器
      size()           返回map中元素的个数
      swap()            交换两个map
      upper_bound()     返回键值>给定元素的第一个位置
      value_comp()      返回比较元素value的函数

通过map对象的方法获取的iterator数据类型是一个std::pair对象。

iterator包括两个数据 iterator->first 和 iterator->second 分别代表关键字key和存储的数据value。


宏定义迭代器是一种检查容器内元素并遍历元素的数据类型。C++更趋向于使用迭代器而不是下标操作,因为标准库为每一种标准容器(如vector)定义了一种迭代器类型,而只用少数容器(如vector)支持下标操作访问容器元素。

1.宏常量没有数据类型,没有类型安全检查,不分配内存,并在字符串替换时可能会产生意想不到的错误,字符串中永远不包含宏,否则该宏名当字符串处理,宏定义末尾不必加分号,否则连分号一并替换,宏定义可以嵌套,可用#undef命令终止宏定义的作用域

2.带参数的宏定义实例:

#define INC(x) x+1

y = INC(5);

反例:

#define SQ(r) r*r

area = SQ(a+b);//就会变成a+b*a+b,所以最好所有层次都要带上括号

文件包含 #include

条件编译 #ifdef

3.在C语言的宏里,#的功能是将后面的宏参数进行字符串化操作

__LINE__表示是在多少行

__FILE__表示这个是在哪个源文件里的

__DATE__表示源文件被翻译到代码时的日期

__TIME__源代码翻译到目标代码的事件

只包含空格的行,被称为空白行,可能带有注释,C++ 编译器会完全忽略它。

4.此外,我们还可以使用 #if 0 ... #endif 来实现注释,且可以实现嵌套,格式为:

#if 0

   code#endif 

你可以把 #if 0 改成 #if 1 来执行 code 的代码。

这种形式对程序调试也可以帮助,测试时使用 #if 1 来执行测试代码,发布后使用 #if 0来屏蔽测试代码。

输入输出函数详解:

在codeblocks环境中启动程序不会使用在debug文件夹下的文件,若输出文件什么也没有输出,或者没有return 0的,证明程序没有运行完就强行关闭了。

5.scanf 函数的返回值反映的是按照指定的格式符正确读入的数据的个数。也就是说,可以运用while(scanf(“%d”,&x)==1){}来更加简化没有确定数据个数时的代码段,那么,这里只能输入字母来结束输入,在scanf中,回车,空格,tab键是无关紧要的,也就是输入多少也不会管,只有按下空格,再按Ctrl+z,然后再按回车,才算结束输入,这时候scanf接受的是第一个空格之前的字符,在Linux中,按下回车,再按下Ctrl+D即可结束输入,也就是说,scanf的这种特性基本没用,只有在ACM中有用。另外printf的添加空格功能也是非常重要的一个功能,格式为%3d

scanf函数输入字符串的的情况下空白字符(空格,回车,Tab)都只是被视为分隔符,当我们输入字符串jj后按回车的时候就会把jj连同换行符送入缓冲区,然而scanf只会接收字符串jj,并把这个字符串送入到以a为首地址的地址空间中,同时在字符串后面自动加上一个\0,那么如今缓冲区内就只有一个换行符了。如果gets()函数时,因为缓冲区内非空,那么gets直接回读取缓冲区中的换行符复制到str为首地址的内存空间,同时在字符串后面自动加上一个\0,所以输出的str的结果就是一个换行罢了。

gets只接受换行符或EOF作为分割,如果缓冲区不为空,会把换行符读进去,并把换行符改成NULL,如果缓冲区为空,则在换行符之后加上一个NULL ,而不是把换行符改成NULL 

getchar()会接收缓冲区中的而第一个字符,如果缓冲区是空的,那么程序便会停在gets()位置处的等待输入。

无缓冲输入getch()

getchar与getc用法略有不同,都使用返回值,不同的是getc需要指定文件参数

windows中在conio.h

8.输入输出重定向

freopen("d:\\data_in.txt","r",stdin); 将输入定向为文件d盘下的文件data_in.txt文件

freopen("d:\\data_out.txt","w",stdout); 将输出定向到d盘下的data_out.txt目录。如果进行了输入输出重定向的话,那么scanf就应该添加\n了,如果后面没有\n的话,说实在的,它也应该不会出错的,到不是数字的时候自动停止,应该不会出错的。也就是说,即便后面是什么鬼都没关系,就这样,更方便了呢

9.ifstream fin(“wormhole.in”);

fin >> N;

fin.close();

ofstream fout(“wormhole.out”);

fout << solve() << “\n”;

fout.close();

就是这么用,别忘了关闭就行了

cin>>a>>b;

count<<a<<b<<endl;

cout也是支持格式化输出的,只不过是特别恶心,例如让浮点数保留两位小数输出

cout << setprecision(2) << 3.1415926...注意会四舍五入,还必须要加上#include "iomanip"

printf不支持string,因此只能这么干:printf("%s",str.c_str()); 所以不推荐,因此cout和printf混用就好了

其中,另外,gets在C ++中会产生bug,而且在C11标准中 被废除,因此不建议使用,getline(cin, str)函数只能读取string类型,不能读取字符数组类型,cin.get可以读取字符数组类型,并且只会遇到回车而结束。用法为cin.get(ch,长度),另外需要注意的是,这个函数会将换行符留在输入队列中,如果连续两次调用,第二次将无法读入,应加上一个不带参数的cin.get吃掉换行符,推荐用cin.ignore(),因为看起来自带注释的感觉,另外cin>>noskipws也有读取空格字符串的功能

一般的,常会有使用一次cin之后连续多次使用getline,但是,由于cin不读入空格的特性,getline总会少输入一行,所以正确姿势是用cin.get()或者cin.ingnore(),感觉用后者更自带注释一些

8.1."\n" 表示内容为一个回车符的字符串。std::endl 是流操作子,输出的作用和输出 "\n" 类似,但可能略有区别。

std::endl 输出一个换行符,并立即刷新缓冲区,由于流操作符 << 的重载,对于 '\n' 和 "\n",输出效果相同。对于有输出缓冲的流(例如cout、clog),如果不手动进行缓冲区刷新操作,将在缓冲区满后自动刷新输出。不过对于 cout 来说(相对于文件输出流等),缓冲一般体现得并不明显。但是必要情况下使用 endl 代替 '\n' 一般是个好习惯。

对于无缓冲的流(例如标准错误输出流cerr),刷新是不必要的,可以直接使用 '\n'。

9.printf,sprintf,fprintf是三个亲兄弟,分别是输出到标准输出,字符串,文件。

11.fgetc(file)为从文件中读取一个字符,返回int型,而getchar()是从标准输入输出中获取一个字符,它等价于fgetc(stdin)

12.fgets(buff,MAXN,fin)将读取完整的一行存放到buff字符数组中,而且往往是以\n结尾(除了在文件结束前没有遇到\n这种特殊情况)。当一个字符也没有读到,函数返回null。同样有一个标准输入板的gets(s)函数,里面只有一个数组参数,风险较大,不建议使用。而在scanf中,是不包括\n的,但是也不能在接受字符串中打上\n,回车是一个输入完成键,在scanf与fgets混用时(我为什么要混用?可能以后再也不会混用了)要注意这个点。

13.在用fgets读取整段函数时,每一个段后面会有一个回车符需要减一,而最后一个段没有回车符,用一个0代替,好像也会录入,注意fgets与fscanf的不同,因为fscanf不吸收\n\r,因此交替使用时,要用scanf("...\n\r",...)吸收掉段尾标志才行。因为在文件里,没有敲回车代表完成输入的。

14.fgetc(pFile)从pFIle文件读取一个字符,返回值就是此字符,fputc(ch,pFile)也是这样,若失败了,返回EOF,为-1,而fegts(str,n,pFile)倘若失败,则返回NULL即0

15.fgets,fput,fprintf,fscanf,fread,fwrite(地址,要读写的字节数,每个数据项长度,文件指针)此为二进制方式

16.rewind(文件指针)使文件位置标记指向文件开头,fseek(文件类型指针,位移量,起始点0,1,2)

17.在C++中,getch已经变为_getch,我也不知道这会有什么意义

对于上下左右和别的一些扩展键使用getch会先返回一个224,再使用一次getch()这时返回的才是扫描码

fopen_s函数在安全性上有所提高,通过输入一个错误指针达到安全目的

printf返回字符串中字符个数

gettext函数是tc的函数,在vs里自然是没有的

字符串处理函数详解:

6.数组批量复制函数memcpy,数组清零函数memset函数,类似于a[100] = {0}只能在定义时使用,它们都在string.h中,善于利用这些函数,可以不用写for循环了。

10.头文件ctype.h中定义的isalpha(判断是否为大小写字母),isdigit(是否为十进制字符),isprint(是否为可打印字符)等工具可以用来判断字符属性,而toupper(返回字符的大写形式),tolower(返回字符的小写形式)等工具可以用来转换大小写。

14.c语言中的确有字符串转int型函数,为atoi函数,在stdlib里

strlen返回字符串长度的

内存函数

C 库函数 void *realloc(void *ptr, size_t size) 尝试重新调整之前调用 malloc 或 calloc 所分配的 ptr 所指向的内存块的大小.下面是 realloc() 函数的声明。

void *realloc(void *ptr, size_t size)
  • ptr -- 指针指向一个要重新分配内存的内存块,该内存块之前是通过调用 malloc、calloc 或 realloc 进行分配内存的。如果为空指针,则会分配一个新的内存块,且函数返回一个指向它的指针。另外,ptr必须是经过malloc创建的ptr,如果ptr参数是某个数组的首地址,或者用一个指针指向这个数组的首地址,然后传进去,也是不行的,必须是malloc得来的地址
  • size -- 内存块的新的大小,以字节为单位。如果大小为 0,且 ptr 指向一个已存在的内存块,则 ptr 所指向的内存块会被释放,并返回一个空指针。

该函数返回一个指针 ,指向重新分配大小的内存。如果请求失败,则返回 NULL。

sizeof测量字符串指针时,只会返回四字节,因为测量的是指针,但用sizeof测量字符串数组头节点的时候,返回的是包括0的所有长度,而用strlen的话,不包括后面的0,可以同时测量字符串数组和字符串指针

关于realloc与字符串之间的关系,因为所有的指针都是一个四字节的整型

在C++中,可以用new完全替代malloc,现在用malloc主要就是用来开辟一个结构或者一个结构数组,通过 MyStruct *ms = new MyStruct; 或者MyStruct *ms = new MyStruct[n];来完成,删除的话请用delete ms;完成,如果删除的是个数组,必须加方括号delete[] ms;来完成,因此从现在开始,由于new可以动态创建数组,而且可以方便替换,不需要加库函数,就用new创建数组就好了

 

 

 

 

 

 

 

 

 

 

 

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值