C++蜗牛

来源:互联网 发布:怎么点击升级淘宝网 编辑:程序博客网 时间:2024/04/29 21:08

C++蜗牛



1:windows静态连接
#include  “mysock.h”             //    头文件
#pragma  comment (lib,  “myxock.lib”)  对应的静态库库文件

作用:实现windows静态库的手动连接


2: char s [ 1024] = { 0 };

作用:将内容清空


3:数据类型的封装
用法 int  InitHardEnv(void **handle);
     void*指针作为左值用于“接收”任意类型的指针
     void*指针作为右值赋值给其它指针时需要强制类型转换
     典型的如内存操作函数memcpy和memset的函数原型分别为
    void * memcpy(void *dest, const void *src, size_t len);

    void * memset ( void * buffer, int c, size_t num );  


4:内存四区分析
 
5:const int* c   c是一个指向常整形数的指针(所指向的内存数据不能被修改,但是本身可以修改)
   Int* const d d是常指针(指针变量不能被修改,但是它所指向内存空间可以被修改)
Const int* const e e是一个指向常整形的常指针(指针和它所指向的内存空间,均不能被修改)
C++编译器对const常量的处理
当碰见常量声明时,在符号表中放入常量 =问题:那有如何解释取地址
编译过程中若发现使用常量则直接以符号表中的值替换
编译过程中若发现对const使用了extern或者&操作符,则给对应的常量分配存储空间(兼容C)
结论:
指针和指针所指向的内存空间是两个不同的概念,使用内存四区图来进行理解

看const的作用,看const 是修饰×的左边还是右边,左边就是指针变量可以改(可以使用a=a+1,a为指针),但是该指针所指向的内存块不可以改变内容;右边就是指针变量不能改,但是该指针所指向的内存块可以改变内容。


6:引用
 
引用是地址,引用是常量,引用所占的空间大小与指针相同,使用常指针实现
Const & 相当于const int* const e;

普通引用相当于int* const e1;


7: 函数默认参数的规则
只有参数列表后面部分的参数才可以提供默认参数值

一旦在一个函数调用中开始使用默认参数值,那么这个参数后的所有参数都必须使用默认参数值


8:函数重载
   函数返回值不能作为函数重载的依据
   由函数名和参数列表决定的
重载函数在本质上是相互独立的不同函数(静态链编)
当函数默认参数遇上函数重载
int func(int a, int b, int c = 0);int func(int a, int b);
c = func(1, 2)执行出错,存在二义性,编译通不过
重载和函数指针结合
当使用重载函数名对函数指针进行赋值时
根据重载规则挑选与函数指针参数列表一致的候选者
严格匹配候选者的函数类型与函数指针的函数类型
int func(int x) // int(int a)
{
return x;
}


int func(int a, int b)
{
return a + b;
}


int func(const char* s)
{
return strlen(s);
}


typedef int(*PFUNC)(int a); // int(int a)


int main(int argc, char *argv[])
{
int c = 0;
PFUNC p = func;
c = p(1);
printf("c = %d\n", c);
printf("Press enter to continue ...");
getchar();
return 0;

}


9:


10:三目运算符

C语言中其返回的是变量的值,在c++中返回的是变量本身,也就是说c中不能做左值,c++中能做左值。(注意,如果可能返回的值中有一个是常量,那么就不能作为左值使用)


11:c++中const常量与宏定义的不同

Const常量是由编译器处理的,提供类型检查和作用域检查;宏定义由预处理器处理,单纯的文本替换。


12:copy构造函数(赋值构造函数)

赋值构造函数和=操作是两个不同的概念。
当我们没有编写copy构造函数(赋值构造函数)的时候,c++编译器会默认给我们提供一个copy构造函数 执行的是浅copy
深拷贝和浅拷贝


13:c++/c中获取char【】数组的字符串长度

Strlen(const char*);


14:c++/c中获取数据类型所占字节大小

Sizeof (type);


15:二级指针的内存模型
二级指针的第一种内存模型
                Char * Accary [ ] = { “aaaaaa”,   ”bbbbbb”,   ”ccccccc” };
         


//接口形参使用方式
Int printfarr(char **ArrayStr, int iNUm)
{
    For (i =0; i<iNUm; i++)
     {


  Printf(“%s  \n”, ArrayStr[i]);
     }
}
//调用方式
Printfarr(Accary ,  3);


二级指针的第二种内存模型
            
 Char  Array[10][30] = {“aaaa”, “bbbb”, “cccccc”,};


// 接口形参使用方式
Void abc(char Arrary[30], 4 )
{
   For (i=0; i<4; i++)
   {
      Printf(“%s  \n”,Accary[i]);
   }
}
//调用方式
Printfarr(Array ,  3);


二级指针的第三钟内存模型
 char **real = (char **)malloc(3*sizeof(char *));
        for (int i=0; i<3; i++)
        {
                real[i] = (char *)malloc(30*sizeof(char));
        }


        sprintf(real[0],"dbsiudaudhakdhjhba");
        sprintf(real[1],"b");
        printf("%s \n", real[1]);
//接口形参使用方式
Int printfarr(char **ArrayStr, int iNUm)
{
    For (i =0; i<iNUm; i++)
     {


  Printf(“%s  \n”, ArrayStr[i]);
     }
}
//调用方式
Printfarr(Accary ,  3);




形参写法的引申:
Void str(char  abc[30]);
void str(char abc[  ]);   一维数组做形参,退化为指针
void str(char abc);手工加 * ,手工完成编译器任务
//针对第二种内存模型
Void str(char  abc[30][60]);
void str(char abc[  ][60]);   二维数组做形参,退化为指针,60为指针步长
void str(char (*abc)[60]);手工加 * ,手工完成编译器任务,其实就是数组指针


等价关系
     数组参数                                              等效指针参数 


一维数组 char a[ 30 ]  ------------------------------->  指针char × a
指针数组char  × a [ 30]-------------------------------->指针的指针 char × × a
二位数组 char a[30 ][30]-------------------------------->数组的指针 char(×a)[30]


16:ASCII编码对照表
ASCII值 字符 ASCII值 字符 ASCII值 字符
Decimal Hex Decimal Hex Decimal Hex
000 000 NUL     020 014 DC4(^T) 040 028 (
001 001 SOH    (^A) 021015NAK(^U)041029)
002       002 STX    (^B) 022016SYN(^V)04202A*
003 003 ETX    (^C) 023017ETB(^W)04302B+  
004 004 EOT    (^D) 024018CAN(^X)04402C ,   
005 005 ENQ    (^E) 025019EM(^Y)04502D-   
006 006 ACK    (^F) 02601ASUB(^Z)04602E.
007 007 BEL    (Bell) 02701BESC047 02F/
008 008 BS    (^H) 02801CFS 048 030 0
009 009 HT    (^I) 02901DGS 049 031 1
010 00A LF    (^J) 03001ERS 050 032 2
011 00B VT    (^K) 03101FUS 051 033 3
012 00C FF    (^L) 032020(空格)0520344
013 00D CR    (^M) 033021! 053 035 5
014 00E SO    (^N) 034022 "  0540366
015 00F SI    (^O) 035023# 055 037 7
016 010 DLE    (^P) 036024$  056 0388
017 011 DC1 (^Q) 037 025 % 0570399
018 012 DC2       (^R) 038026& 058 03A
019 013 DC3 (^S) 039 027 '   05903B
        
ASCII值 字符 ASCII值 字符 ASCII值 字符
Decimal Hex Decimal Hex Decimal Hex
060 03C <     099 063 c 13808Aè
061 03D = 100 064d139 08Bï
062       03E > 101 065e140 08Cî
063 03F ? 102 066f141 08Dì  
064 040 @ 103 067g142 08EÄ 
065 041 A 104 068h143 08FÅ 
066 042 B 105 069i144 090É
067 043 C 106 06A j  145091 æ
068 044 D 107 06Bk146 092Æ
069 045 E 108 06Cl  147093 ô
070 046 F 109 06Dm148 094ö
071 047 G 110 06En149 095ò
072 048 H 111 06Fo  150096 û
073 049 I 112 070p151 097ù
074 04A J 113 071q152 098ÿ
075 04B K 114 072r153 099Ö
076 04C L 115 073s154 09AÜ
077 04D M 116 074t155 09Bø
078 04E N 117 075u156 09C£
079 04F O 118 076v157 09DØ
080 050 P 119 077w158 09E×
081 051 Q 120 078x159 09Fƒ
082 052 R 121 079y160 0A0á
083 053 S 122 07Az161 0A1í
084 054 T 123 07B{162 0A2ó
085 055 U 124 07C|163 0A3ú
086 056 V 125 07D}164 0A4ñ
087 057 W 126 07E~  1650A5 Ñ
088 058 X 127 07FDEL1660A6 ª
089 059 Y 128 080Ç167 0A7º
090 05A Z 129 081ü168 0A8¿
091 05B [ 130 082é169 0A9®
092 05C \ 131 083â170 0AA¬
093 05D ] 132 084ä171 0AB½
094 05E ^ 133 085à172 0AC¼
095 05F _ 134 086å173 0AD¡
096 060 ` 135 087ç174 0AE«
097 061 a 136 088ê175 0AF»
098 062 b 137 089ë176 0B0_


         
ASCII值 字符 ASCII值 字符 ASCII值 字符
Decimal Hex Decimal Hex Decimal Hex
177 0B1 _   216 0D8 Ï 2550FF
178 0B2 _ 217 0D9+
179       0B3 ¦ 218 0DA+
180 0B4 ¦ 219 0DB_
181 0B5 Á 220 0DC_
182 0B6 Â 221 0DD¦
183 0B7 À 222 0DEÌ
184 0B8 © 223 0EF_  
185 0B9 ¦ 224 0E0Ó
186 0BA ¦ 225 0E1ß  
187 0BB + 226 0E2Ô
188 0BC + 227 0E3Ò
189 0BD ¢ 228 0E4õ
190 0BE ¥ 229 0E5Õ
191 0BF + 230 0E6µ
192 0C0 + 231 0E7þ
193 0C1 - 232 0E8Þ
194 0C2 - 233 0E9Ú
195 0C3 + 234 0EAÛ
196 0C4 - 235 0EBÙ
197 0C5 + 236 0ECý
198 0C6 ã 237 0EDÝ
199 0C7 Ã 238 0EE¯
200 0C8 + 239 0FF´
201 0C9 + 240 0F0
202 0CA - 241 0F1±
203 0CB - 242 0F2_
204 0CC ¦ 243 0F3¾
205 0CD - 244 0F4
206 0CE + 245 0F5§
207 0DF ¤ 246 0F6÷
208 0D0 ð 247 0F7¸
209 0D1 Ð 248 0F8°
210 0D2 Ê 249 0F9¨
211 0D3 Ë 250 0FA
212 0D4 È 251 0FB¹
213 0D5 i 252 0FC³
214 0D6 Í 253 0FD²
215 0D7 Î 254 0FE_


17:常用头文件
#include <assert.h> //设定插入点 
#include <ctype.h> //字符处理 
#include <errno.h> //定义错误码 
#include <float.h> //浮点数处理 
#include <fstream.h> //文件输入/输出 
#include <iomanip.h> //参数化输入/输出 
#include <iostream.h> //数据流输入/输出 
#include <limits.h> //定义各种数据类型最值常量 
#include <locale.h> //定义本地化函数 
#include <math.h> //定义数学函数 
#include <stdio.h> //定义输入/输出函数 
#include <stdlib.h> //定义杂项函数及内存分配函数 
#include <string.h> //字符串处理 
#include <strstrea.h> //基于数组的输入/输出 
#include <time.h> //定义关于时间的函数 
#include <wchar.h> //宽字符处理及输入/输出 
#include <wctype.h> //宽字符分类 
#include <complex> //复数类 
#include <ios> //基本输入/输出支持 
#include <iosfwd> //输入/输出系统使用的前置声明 
#include <iostream> 
#include <istream> //基本输入流 
#include <ostream> //基本输出流 
#include <queue> //STL 队列容器 
#include <set> //STL 集合容器 
#include <sstream> //基于字符串的流 
#include <stack> //STL 堆栈容器 
#include <stdexcept> //标准异常类 
#include <streambuf> //底层输入/输出支持 
#include <string> //字符串类 
#include <utility> //STL 通用模板类 
#include <vector> //STL 动态数组容器 
#include <dos.h>通用dos中断接口函数
#include <conio.h>)驻留并退出函数
18:C语言常用库函数
程序应包含在math.h
函数类型 函数形式 功能 类型
数学函数 abs(int i)求整数的绝对值int
fabs(double x)返回浮点数的绝对值double
floor(double x)向下舍入double
fmod(double x, double y)计算x对y的模, 即x/y的余数double
exp(double x) 指数函数 double
log(double x) 对数函数ln(x) double
log10(double x)对数函数logdouble
labs(long n) 取长整型绝对值 long
modf(double value, double *iptr)把数分为指数和尾数double
pow(double x, double y)指数函数(x的y次方)double
sqrt(double x)计算平方根double
sin(double x) 正弦函数 double
asin(double x)反正弦函数double
sinh(double x)双曲正弦函数double
cos(double x);余弦函数double
acos(double x)反余弦函数double
cosh(double x)双曲余弦函数double
tan(double x) 正切函数 double
atan(double x)反正切函数double
tanh(double x)双曲正切函数double
数学函数 abs(int i)求整数的绝对值int
fabs(double x)返回浮点数的绝对值double
floor(double x)向下舍入double
fmod(double x, double y)计算x对y的模, 即x/y的余数double
exp(double x) 指数函数 double
log(double x) 对数函数ln(x) double
log10(double x)对数函数logdouble
labs(long n) 取长整型绝对值 long
modf(double value, double *iptr)把数分为指数和尾数double
pow(double x, double y)指数函数(x的y次方)double
sqrt(double x)计算平方根double
sin(double x) 正弦函数 double
asin(double x)反正弦函数double
sinh(double x)双曲正弦函数double
cos(double x);余弦函数double
acos(double x)反余弦函数double
cosh(double x)双曲余弦函数double
tan(double x) 正切函数 double
atan(double x)反正切函数double
tanh(double x)双曲正切函数double
程序应包含在string.h
函数类型 函数形式 功能 类型
字符串函数 strcat(char *dest,const char *src)将字符串src添加到dest末尾char
strchr(const char *s,int c)检索并返回字符c在字符串s中第一次出现的位置char
strcmp(const char *s1,const char *s2)
       比较字符串s1与s2的大小,并返回s1-s2int
stpcpy(char *dest,const char *src)将字符串src复制到destchar
strdup(const char *s)       将字符串s复制到最近建立的单元 char
strlen(const char *s)       返回字符串s的长度 int
strlwr(char *s)   将字符串s中的大写字母全部转换成小写字母,并返回转换后的字符串 char
strrev(char *s)       将字符串s中的字符全部颠倒顺序重新排列,并返回排列后的字符串char
strset(char *s,int ch)将一个字符串s中的所有字符置于一个给定的字符chchar
strspn(const char *s1,const char *s2)扫描字符串s1,并返回在s1和s2中均有的字符个数char
strstr(const char *s1,const char *s2)描字符串s2,并返回第一次出现s1的位置char
strtok(char *s1,const char *s2)检索字符串s1,该字符串s1是由字符串s2中定义的定界符所分隔char
  strupr(char *s)将字符串s中的小写字母全部转换成大写字母,并返回转换后的字符串char
程序应包含在ctype.h
函数类型 函数形式 功能 类型
字符函数 isalpha(int  ch) 若ch是字母('A'-'Z','a'-'z')返回非0值,否则返回0 int
   isalnum(int  ch)      若ch是字母('A'-'Z','a'-'z')或数字('0'-'9')返回非0值,否则返回0int 
isascii(int  ch)    若ch是字符(ASCII码中的0-127)返回非0值,否则返回0int
iscntrl(int  ch)   若ch是作废字符(0x7F)或普通控制字符(0x00-0x1F)返回非0值,否则返回0 int 
isdigit(int  ch)  


若ch是数字('0'-'9')返回非0值,否则返回0
int 




  isgraph(int  ch) 
若ch是可打印字符(不含空格)(0x21-0x7E)返回非0值,否则返回0int 
islower(int  ch)   
  若ch是小写字母('a'-'z')返回非0值,否则返回0int 



isprint(int  ch)     若ch是可打印字符(含空格)(0x20-0x7E)返回非0值,否则返回0
int 
 ispunct(int  ch)      若ch是标点字符(0x00-0x1F)返回非0值,否则返回0int

isspace(int  ch) 
若ch是空格('  '),水平制表符('\t'),回车符('\r'), 走纸换行('\f'),垂直制表符('\v'),换行符('\n'),返回非0值,否则返回0


int



isupper(int  ch)     若ch是大写字母('A'-'Z')返回非0值,否则返回0
int
 isxdigit(int  ch)  
若ch是16进制数('0'-'9','A'-'F','a'-'f')返回非0值,否则返回0
int
 tolower(int  ch)    
若ch是大写字母('A'-'Z')返回相应的小写字母('a'-'z')int


 toupper(int  ch)    
若ch是小写字母('a'-'z')返回相应的大写字母('A'-'Z')int


程序应包含在stdio.h
函数类型 函数形式 功能 类型
输入输出函数 getch() 从控制台(键盘)读一个字符,不显示在屏幕上int
putch()    向控制台(键盘)写一个字符int
getchar()   从控制台(键盘)读一个字符,显示在屏幕上int
putchar()  向控制台(键盘)写一个字符 int
getchar()  从控制台(键盘)读一个字符,显示在屏幕上 int
getc(FILE  *stream) 从流stream中读一个字符,并返回这个字符 int
putc(int  ch,FILE  *stream)向流stream写入一个字符chint
getw(FILE  *stream) 从流stream读入一个整数,错误返回EOF int
putw(int  w,FILE  *stream)向流stream写入一个整数int
fclose(handle)关闭handle所表示的文件处理FILE *
fgetc(FILE  *stream) 从流stream处读一个字符,并返回这个字符 int
fputc(int  ch,FILE  *stream) 将字符ch写入流stream中 int
fgets(char  *string,int  n,FILE  *stream)流stream中读n个字符存入string中c har *
fopen(char *filename,char *type) 打开一个文件filename,打开方式为type,并返回这个文件指针,type可为以下字符串加上后缀FILE *
fputs(char  *string,FILE  *stream) 将字符串string写入流stream中 int
fread(void  *ptr,int  size,int  nitems,FILE  *stream)从流stream中读入nitems个长度为size的字符串存入ptr中int
fwrite(void  *ptr,int  size,int  nitems,FILE  *stream)向流stream中写入nitems个长度为size的字符串,字符串在ptr中int
fscanf(FILE  *stream,char  *format[,argument,…])以格式化形式从流stream中读入一个字符串int
fprintf(FILE  *stream,char  *format[,argument,…])以格式化形式将一个字符串写给指定的流streamint
scanf(char *format[,argument…])从控制台读入一个字符串,分别对各个参数进行赋值,使用BIOS进行输出int
printf(char *format[,argument,…])
发送格式化字符串输出给控制台(显示器),使用BIOS进行输出int


19:C语言运算符优先级和结合性
优先级 运算符 名称或含义 使用形式 结合方向 说明
1 [] 数组下标数组名[常量表达式]左到右
() 圆括号(表达式)/函数名(形参表)
. 成员选择(对象)对象.成员名
-> 成员选择(指针)对象指针->成员名
2 - 负号运算符-表达式右到左单目运算符
(类型) 强制类型转换(数据类型)表达式
++ 自增运算符++变量名/变量名++单目运算符
-- 自减运算符--变量名/变量名--单目运算符
* 取值运算符*指针变量单目运算符
& 取地址运算符&变量名单目运算符
! 逻辑非运算符!表达式单目运算符
~ 按位取反运算符~表达式单目运算符
sizeof 长度运算符 sizeof(表达式)
3 / 表达式/表达式左到右双目运算符
* 表达式*表达式双目运算符
% 余数(取模)整型表达式/整型表达式双目运算符
4 + 表达式+表达式左到右双目运算符
- 表达式-表达式双目运算符
5 << 左移变量<<表达式左到右双目运算符
>> 右移变量>>表达式双目运算符
6 > 大于表达式>表达式左到右双目运算符
>= 大于等于表达式>=表达式双目运算符
< 小于表达式<表达式双目运算符
<= 小于等于表达式<=表达式双目运算符
7 == 等于表达式==表达式左到右双目运算符
!= 不等于表达式!= 表达式双目运算符
8 & 按位与表达式&表达式左到右双目运算符
9 ^ 按位异或表达式^表达式左到右双目运算符
10 | 按位或表达式|表达式左到右双目运算符
11 && 逻辑与表达式&&表达式左到右双目运算符
12 || 逻辑或表达式||表达式左到右双目运算符
13 ?: 条件运算符表达式1? 表达式2: 表达式3右到左三目运算符
14 = 赋值运算符变量=表达式右到左
/= 除后赋值变量/=表达式
*= 乘后赋值变量*=表达式
%= 取模后赋值变量%=表达式
+= 加后赋值变量+=表达式
-= 减后赋值变量-=表达式
<<= 左移后赋值变量<<=表达式
>>= 右移后赋值变量>>=表达式
&= 按位与后赋值变量&=表达式
^= 按位异或后赋值变量^=表达式
|= 按位或后赋值变量|=表达式
15 , 逗号运算符表达式,表达式,…左到右从左向右顺序运算

c++优先级


Precedence OperatorDescriptionExampleAssociativity
1 ()
[]
->
.
::
++
-- Grouping operator
Array access
Member access from a pointer
Member access from an object
Scoping operator
Post-increment
Post-decrement (a + b) / 4;
array[4] = 2;
ptr->age = 34;
obj.age = 34;
Class::age = 2;
for( i = 0; i < 10; i++ ) ...
for( i = 10; i > 0; i-- ) ... left to right
2 !
~
++
--
-
+
*
&
(type)
sizeof
Logical negation
Bitwise complement
Pre-increment
Pre-decrement
Unary minus
Unary plus
Dereference
Address of
Cast to a given type
Return size in bytes if( !done ) ...
flags = ~flags;
for( i = 0; i < 10; ++i ) ...
for( i = 10; i > 0; --i ) ...
int i = -1;
int i = +1;
data = *ptr;
address = &obj;
int i = (int) floatNum;
int size = sizeof(floatNum); right to left
3 ->*
.* Member pointer selector
Member pointer selector ptr->*var = 24;
obj.*var = 24; left to right
4 *
/
% Multiplication
Division
Modulus int i = 2 * 4;
float f = 10 / 3;
int rem = 4 % 3; left to right
5 +
- Addition
Subtraction int i = 2 + 3;
int i = 5 - 1; left to right
6 <<
>> Bitwise shift left
Bitwise shift right int flags = 33 << 1;
int flags = 33 >> 1; left to right
7 <
<=
>
>= Comparison less-than
Comparison less-than-or-equal-to
Comparison greater-than
Comparison geater-than-or-equal-to if( i < 42 ) ...
if( i <= 42 ) ...
if( i > 42 ) ...
if( i >= 42 ) ... left to right
8 ==
!= Comparison equal-to
Comparison not-equal-to if( i == 42 ) ...
if( i != 42 ) ... left to right
9 & Bitwise ANDflags = flags & 42;left to right
10 ^ Bitwise exclusive ORflags = flags ^ 42;left to right
11 | Bitwise inclusive (normal) ORflags = flags | 42;left to right
12 && Logical ANDif( conditionA && conditionB ) ...left to right
13 || Logical ORif( conditionA || conditionB ) ...left to right
14 ? : Ternary conditional (if-then-else) int i = (a > b) ? a : b;right to left
15 =
+=
-=
*=
/=
%=
&=
^=
|=
<<=
>>= Assignment operator
Increment and assign
Decrement and assign
Multiply and assign
Divide and assign
Modulo and assign
Bitwise AND and assign
Bitwise exclusive OR and assign
Bitwise inclusive (normal) OR and assign
Bitwise shift left and assign
Bitwise shift right and assign int a = b;
a += 3;
b -= 4;
a *= 5;
a /= 2;
a %= 3;
flags &= new_flags;
flags ^= new_flags;
flags |= new_flags;
flags <<= 2;
flags >>= 2; right to left
16 , Sequential evaluation operatorfor( i = 0, j = 0; i < 10; i++, j++ ) ...left to right


20:字符串专题
字符与字符串的区别在于字符串的末尾是’\0’
Printf() 函数默认以C风格输出


拷贝复制 模型
Void(char *from, char *to) //++ 的优先级比×高
{
  While((*from++  = * to++) &&!= ‘\0’ )
      {


      }
}


语法越界【错误模型】
Char buf [ 3 ] = “abc”;


不断修改指针变量的值【错误模型】
Char *getKeyByValude(char **keyvaluebuf,char *keybuf)
{
Int i = 0;
Char  *a = (char*)malloc(50);
Printf(“%x”,a);                     //打印a的地址
For ( ; **keyvaluebuf  != ‘\0’ )
{
   *a++ = *(*keyvaluebuf)++;     //不断改变a所指向的内存首地址指向的内存的值,此时的a已经不是原先的那个a了,而是下移到后面去了
}
Free(a);   //真实释放的不是原先的那个a,而是后来下移的那个a,程序会当机。
}
解决方案
//可以定义一个辅助指针变量 char *a1;  a1 = a;


Strstr ( 源字符串 ,”需要查找的字符串” )
返回的是一个地址,需要查找的字符串第一次出现的地址,要使用指针接收该地址
Strchr(源字符串,‘需要查找的字符’)注意与strstr的相同指出与区别


从源字符串中寻找制定字符串的框架


Int count = 0;
Char *sub = “abcd”;
Char *p = “abc111abc22222abcqqqq”;
Char *p2 =NULL; //辅助指针
Do 
{
P = strstr(p , sub) 
If (p !=NULL )
{
   Count++;
   P = p + strlen(sub);
}
Else 
 {
   Break;
}
}while (*p != ‘\0’);
Printf(“count : %d \n”,count);




函数库中字符串函数原型
Void* memcpy(void *, const void *,size_t);
Int   mencmp(const void *,const void *,size_t);
Void *memset(void *,int ,size_t);
Char *_strset(char *,int);
Char *strcpy(char *p1,const char *p3);
Char *strcat(char *,const char *);
Int strcmp(const char *,const char *);
Size_t strlen(const char *);


两头堵模型


int trimSpace(char *inbuf,char *outbuf)
{
        char *p
int i; 
int j;
int count;
count = 0; 
        i = 0;
        j = strlen(inbuf)-1;
p = inbuf;
while (isspace(p[i]) && p[i] != '0')
{
i++;
}
while (isspace(p[j]) && p[j] != '0')
{
j--;
}
printf("%c\n",p[i]);
printf("%c\n",p[j]);
memcpy(outbuf,p+i,j-i+1);
outbuf[j-i+1] = '\0';
printf("%s\n",outbuf);
return 0;
}




字符串反置模型
void string_trun(char *abc, char *cba)
{
char *p;
char tem;
int len;
int i;
i = 0;
len = strlen(abc)-1;
p  = abc;
while (len>i)
        {
tem = p[i];
p[i] = p[len];
p[len] = tem;
i++;
len--;
}
        printf("%s\n",p);
memcpy(cba,p,strlen(p));
cba[strlen(p)-2] = '\0';
}
特别说明: char *p 定义的是一个指针
            Char a[ ] = “sssssss”定义的是一个数组
      P = a  p指向数组a的 首地址


21:c和c++不同:各自struct区别
C中没有保护行保护行为,不能定义函数,但是可以有函数指针。并不认为这是一种新类型
C++中有保护行为,默认public,可以定义函数,被编译器认为是一种新的类型
22:c和c++不同:c++中class和 struct区别
默认的继承权限:class按private处理,struct按public处理
默认的访问权限:class是private,struct是public
注意Union 不能继承
23:c和c++不同:判断c程序/c++程序(混合编译)
#ifdef __cplusplus
Cout << “c++”
#Else
Printf (“c”)
#endif
24:指针跟引用区别 
指针通过某个指针变量指向一个对象后,对他所指向的变量间接操作。
程序中使用指针,程序的可读性变差;
而引用本身就是目标变量的别名,对引用的操作就是对目标变量的操作。
1:引用必须初始化,指针不必
2:不存在指向空值的引用,蚕食存在指向空值的指针
3:引用初始化以后不能改变(c++)是可以的,指针可以改变所指的对象
25:int id[sizeof(umsigned long)];这个对么?why?
正确,sizeof()是编译时运算符,编译时就确定了,可以看作是和及其相关的常量。
26:c++中管理全局变量的方式(在类里面)
定义一个专门类,将所有的全局变量定义为静态变量, 
27:静态全局变量
静态全局变量限制了起作用域,即只在定义该变量的源文件中有效,在统一源程序中的其他源文件中不能使用。
28:c++中没有静态类的概念
静态类是指成员变量, 成员函数都是static
也就是说static class 类名 是无效的,直接忽略static
29:全局变量(跨文件使用)
使用extern 关键字
30:c++函数中值的传递方式有哪几种?
值传递,引用传递,指针传递
31:对于一个频繁使用的函数,在c中使用什么实现,在c++中怎么实现?
C使用宏定义#define
C++使用内联函数 inline
32:const与#define比较,const有什么有点
1:const常量有数据类型,宏常量没有数据类型。
2:编译器可以对const进行安全检查,对宏定义只是字符替换没有安全检查
3;有些工具可以对const常量进行调试,但是不能对宏常量进行调试。
33:malloc/free和new/delete的区别是什么
 
34:子类中不添加vitual关键字问题
子类中不添加vitual关键字,照样可以实现父类中的vitual方法。因为父类中的vitual关键字修饰符是默认被子类隐形继承的。
35:面向对象的三个特点,简述之
 
36:重载,重写,重定义三者的概念以及区别
重载:在同一命名空间内,存在多个同名函数,通过不同的参数列表进行区分
子类无法重载父类的函数,父类同名函数将被名称覆盖
重载是在编译期间根据参数类型和个数决定函数调用
重定义(隐藏):在不同命名空间内,用于继承,指子类和基类的函数名相同,子类的函数屏蔽基类的方法
重写(覆盖):不同命名空间内,用于继承,指子类重新实现父类虚函数方法
必须发生于父类与子类之间
并且父类与子类中的函数必须有完全相同的原型
使用virtual声明之后能够产生多态(如果不使用virtual,那叫重定义)
多态是在运行期间根据具体对象的类型决定函数调用
37:多态的作用
1) 隐藏具体的实现细节,有利于实现代码的模块化
2) 实现接口的重用:有利于方法的正确调用
38:当一个类中没有成员函数也没有成员变量时发生的奇异事件
当一个类中没有成员变量也没有成员函数的时候,那么sizeof(这个类)的值就等于1.解释发生该情况的原因,深度探索面向对象模型中是这样解释的:这一个字节的长度是被编译器插进去的一个char,这能够使得有这个类定义的每个实体对象都有自己独一无二的内存地址空间。也就是说这个char是用来标识不同的对象的。
39:c++中所有动作都是由main函数引起的么
不是的,譬如说,全局变量,注意这个全局变量依赖他的构造函数(自己定义的)
40:类型检查,inline 和define
Define 仅仅是替换
Inline有进行类型检查
41:析构函数跟虚函数的用法以及作用
析构函数没有参数,没有返回值,不能被随意调用,没有重载,只有在类对象生命结束的时候,自动调用,用与释放内存空间。虚函数是c++多态的表现。析构函数可以是虚函数,但好似构造函数不可以是虚函数。
42:“new“是什么
New 是一个操作符,在受编译器控制,可以被重载,mallo是一个库函数,不在编译器的控制范围内,不能被重载。
43:C和C++不同:c++中所有函数变量都要有类型
在C语言中
int f(    );表示返回值为int,接受任意参数的函数
int f(void);表示返回值为int的无参函数
在C++中
int f(  );和int f(void)具有相同的意义,都表示返回值为int的无参函数


44: C和C++不同:bool类型关键字
C中没有bool类型关键字,c++中有
45: C和C++不同:三目运算符增强
c中返回的是值,不能作为左值使用;c++中返回的是对象本身,可以出现在任何地方
注意:如果三目运算符可能返回的值中有一个是常量,那么就不能将其当左值
46:变量的本质
变量的本质是内存空间的别名,是一个标号
47: static关键字
Static函数在实现的时候也不需要static的修饰,因为static是声明性关键字
不在类中
Static变量:该变量仅在本cpp文件中有效
Static函数:该函数仅在本cpp文件中有效
在类中
Static变量:是所有该类对象的实例共有的,仅有一次初始化,为对象们共有
Static函数:不能访问该类中其他不是静态成员变量
访问方式:可以是类的实例对象,也可以是通过类名(不需要实例化)
48: 内存四区划分
  总共分为四个区,栈区(stack),堆区(heap),全局区(静态区static),用户代码区
栈区:由编译器自动分配内存,局部变量,函数参数值等
堆区:由程序员动态内存(new)分配释放,如过不手动释放就由操作系统回收。与堆区类似的有一个自由存储区,他是由malloc分配的内存,这里将这两块归并为堆区。
全局区:
      1)初始化完成的全局变量跟静态变量是放在一起的,没有初始化完成的全局变量跟静态变量也是放在一起的,在相邻另一边,该区域由操作系统释放。
      2)还有一个常量区,专门存放字符串常量和其他常量,由操作系统释放内存。
用户代码区:存放含函数的二进制代码。 
49: 堆栈的对比
1.碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。
2.生长方向:对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
3.分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。
4.分配效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。
50: C++中继承,子类访问方式
 
public继承不会改变父类对外访问属性;private继承会改变父类对外访问属性为private;protected继承会部分改变父类对外访问属性。
51: C++中继承,子类构造以及析构
子类对象在构造的时候通过调用父类的构造方法来初始化从父类继承的内容。
同样子对象在析构的时候通过调用父类的析构方法来清理从父类继承的内容。
52: 继承与组合混搭的情况下,构造和析构的顺序原则
原则: 先构造父类,再构造成员变量、最后构造自己
先析构自己,在析构成员变量、最后析构父类
53: 多态性体现,静态联编 
概念:
指联编工作是在程序编译连接阶段进行的,这种联编又称为早期联编。
54: 多态性体现,动态联编
概念:
在编译阶段并不能确切地知道将要调用的函数,只有在程序执行时才能确定将要调用的函数,为此要确切地知道将要调用的函数,要求联编工作在程序运行时进行,这种在程序运行时进行的联编工作被称为动态联编。
C++规定,动态联编是由虚函数的支持下完成的。
55: 函数指针
定义方式:
类型 (*函数指针名)(参数1类型, 参数2类型。。。。)=NULL




//函数名称就代表函数的入口地址 函数名称本身就是一个指针
//可以把函数名赋给一个函数指针,通过函数指针进行函数调用


声明一个返回值类型为int,入口参数为double &a,int &s,名称为p的函数指针
Int (*p)(double& a, int& s);此时p就是函数指针
Ps:  typedef  Int (*p)(double& a, int& s)此时,p可以看作是一种数据类型
p abc;声明了一个名称为abc的函数指针


函数指针专题讲座 
1、 语法基础
//1定义一个函数类型 
typedef int Func(int);
Func MyFunc;


//2定义一个指向函数类型的指针类型 
typedef int (*MyPFun)(int);
MyPFun  pMyFunc;




//3直接定义一个函数指针,并且赋值 
void (*myf1)() = NULL;


//函数名称就代表函数的入口地址 函数名称本身就是一个指针
//可以把函数名赋给一个函数指针,通过函数指针进行函数调用
int test(int a)
{
return a*a;
}
Func *myfun = NULL;
myfun = test;


2、语法基础
函数指针做函数参数的两种写法
第一种写法:
int add(int a, int b);
//第二个函数 是函数指针 做函数参数 
//在这个函数里面,就可以通过这个函数指针,去调用外部的函数,形成一个回调
int libfun(  int (*pDis)(int a, int b)  );


typedef int (*MyPFunDemo)(int);
MyPFunDemo  pMyFunc;
第二种写法
int libfunc2(MyPFunDemo myfunc);
2、 正向调用
//客户端初始化 获取handle上下
typedef int (*CltSocketInit)(void **handle ); 
//客户端发报文
typedef int (*CltSocketSend)(void *handle , unsigned char *buf ,  int buflen );
//客户端收报文
typedef int (*CltSocketRev)(void *handle , unsigned char *buf , int *buflen );


//客户端释放资源
typedef int (*CltSocketDestory)(void *handle);
//在这个函数里面完成动态库的加载
//利用winapi
void CMFC应用程序动态加载dll项目Dlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
HINSTANCE hInstance = NULL;
hInstance=::LoadLibrary("c:/socketclient.dll");
CltSocketInit cltSocketInit =  (CltSocketInit)::GetProcAddress(hInstance, "cltSocketInit");
CltSocketSend cltSocketSend =  (CltSocketSend)::GetProcAddress(hInstance, "cltSocketSend");
CltSocketRev cltSocketRev =  (CltSocketRev)::GetProcAddress(hInstance, "cltSocketRev");
CltSocketDestory cltSocketDestory =  (CltSocketDestory)::GetProcAddress(hInstance, "cltSocketDestory");


void *handle = NULL;
unsigned char buf[100]; 
int buflen = 10;
memcpy(buf, "ddddddddddssssssssss", 10);


unsigned char out[100] = {0};
int outlen = 0;


int ret = cltSocketInit(&handle);


ret = cltSocketSend(handle, buf, buflen);
ret = cltSocketRev(handle, out, &outlen);
ret = cltSocketDestory(handle);


printf("out:%s", out);






//SQRTPROC* pFunction;
//VERIFY(hInstance=::LoadLibrary("c:\\winnt\\system32\\mydll.dll"));
//VERIFY(pFunction=(SQRTPROC*)::GetProcAddress(hInstance,"SquareRoot"));
//double d=(*pFunction)(81.0);//调用该DLL函数






AfxMessageBox("dddd");
}
3、 反向调用
回调函数是利用函数指针实现的一种调用机制


回调机制原理
当具体事件发生时,调用者通过函数指针调用具体函数
回调机制的将调用者和被调函数分开,两者互不依赖


任务的实现 和 任务的调用 可以耦合  (提前进行接口的封装和设计)


需要重新审视 dll和其他第三方厂商 接口之间的关系




动态库可以集成第三方厂商的业务功能
动态库(框架)不经常改动,能兼容后来的业务模型  2010  能调用 2020写 具体的任务
代码复用、松耦合
动态库和第三方业务模型 模块之间 松耦合
//如何把一个普通的动态库变成一个业务模型框架,需要做的工作
//1 需要把第三方业务入口传进来(回调函数的入口地址传进来)
传进来有两种方式
1、 回调函数的入口地址缓存到框架库中
clitSocket_SetEncFunc(void *handle, EncData encDataCallbak, void *ref, int refLen)
2、回调函数入口直接放在参数中
cltSocketSend_enc(void *handle, unsigned char *buf,  int buflen, EncData encDataCallbakFunc, void *ref, int refLen)


//2 加密 解密 业务模型抽象
//实现 动态库 加密解密业务模型抽象
通过定义函数指针类型;函数指针做函数参数实现
/2 加密 解密 业务模型抽象
//实现 动态库 加密解密业务模型抽象
typedef int (*EncData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen);
typedef int (*DecData)(unsigned char *inData,int inDataLen,unsigned char *outData,int *outDataLen,void *Ref, int RefLen);


 






56: 构造/析构函数调用规则
1: 构造函数在对象创建时自动被调用(默认调用),隐身调用


2:只要在类中定义了任何构造函数,不管是有参还是无参,编译器都不会默认提供无参构造函数了。假设说类中并没有定义构造函数,编译器默认会提供无参构造函数。
57: 有构造函数的三种调用方式
//括号法
Test t1(10); //c++编译器自动调用这个类的有参构造函数
//=
Test t2 = 20; //c++编译器自动调用这个类的有参构造函数
//
Test t3 = Test(30);//程序员手工的调用构造函数 进行对象初始化
58: c++类中成员函数跟成员变量存放的位置是不同的
成员变量:占用类对象实例化后的内存空间
成员函数:1:不占用实例化后的内存空间,函数的地址是存放在代码区中的
          2:如果是虚函数,则占用一个指针的对象内存空间 
下面是网上参考:
简单点,非静态成员变量占用空间,成员函数(无论是否是静态的)则不占用空间:
class  MyClass{
int a;  //占用4字节
float b; //占用4字节
static int c;//在全局数据区,所有对象共享,不计入各对象中
int fun1(); //不占用对象的空间
float fun2();//不占用对象的空间
static int fun3();//不占用对象的空间
};


MyClass类的实例中:
占用2*4=8个字节 (即a b这两个成员)
 
涉及虚函数表那些你在另外研究。
c++中struct和class在计算对象大小时你就不用区别了,计算方法一样。
59: 操作符重载 
操作符重载基础 
重载的定义及基础
运算符函数是一种特殊的成员函数或友员函数
重载为成员函数,解释为:
ObjectL . operator op ( ObjectR )
    左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递 
重载为友员函数,解释为:
operator op ( ObjectL, ObjectR )
  左右操作数都由参数传递
为什么要有操作符重载
a = a + b; //int 是基础类型,编译器已经为这些类型提供+操作了。
//c1 = c1 + c2; 
//c1的类型是 Complex,这种类型,是自定义类型。 编译器根本不知道如何加,
//但是c++编译器会给你提供一个机制,让你实现自定义类型加
// 前置--
Complex& operator--()
{
this->a--;
this->b--;
return *this;
}


// 前置++
Complex& operator++()
{
this->a++;
this->b++;
return *this;
}


//后置--
Complex operator--(int)
{
Complex tmp = *this;
this->a --;
this->b --;
return tmp;
}


//后置++
Complex operator++(int)
{
Complex tmp = *this;
this->a ++;
this->b ++;
return tmp;
}
操作符重载的三个步骤(成员函数方法进行的时候)
//目标 通过类的成员函数,完成操作符重载
//1 要承认操作符重载是一个函数,要写函数原型
//2 写出函数调用语言 c1.operator-(c2)
//3 完善函数原型 

全局函数重载操作符友元用武之地
原因:
cout<<c1<<"链式编程测试"<<endl;
operator<<(cout, c1);
cout.operator<<(c1);




项目开发操作符重载难点 
int& operator[] (int i);
数组操作符的应用场景有两个 
1放在等号的右边 int operator[] (int i);
2 放在等号的左边 int&operator[] (int i);


=操作符也有两个应用场景
1、 a3  = a2; 不需要用operator=这个函数的返回值 
Array operator= (Array &a2);
2、a1 = a3  = a2;  需要用operator=这个函数的返回值
Array& operator= (Array &a2);
bool operator==(Array &a2);
bool operator!=(Array &a2);




int& Array::operator[] (int i)
{
return mSpace[i];
}


//Array a3(20);
//a3  = a2;
Array& Array::operator= (Array &a2)
{


printf("Array 执¡ä行D=操¨´作Á¡Â\n");
if (this->mSpace != NULL)
{
delete[] mSpace;
mLength = 0;
}



this->mLength = a2.mLength;
this->mSpace = new int[a2.mLength];


for (int i=0;i<a2.mLength; i++)
{
mSpace[i] = a2[i];
}


return *this;


}


bool Array::operator==(Array &a2)
{
//length


if (this->mLength != a2.mLength)
{
return false;
}
for (int i=0; i<a2.mLength; i++)
{
if (this->mSpace[i] != a2[i])
{
return false;
}
}
return true;
}


bool Array::operator!=(Array &a2)
{
return !(*this==a2);
}






60:泛型编程
泛型编程 
1、 泛型编程语法基础
//template关键字告诉c++编译器,现在开始泛型编程
//typename 告诉c++编译器,T为类型(T为类型,可以参数化,int float),你不要乱报错
//类型参数化。。。。。。。
template<typename T>
void swap2(T &a, T &b)
{
T c;
c = a;
a = b;
b = c;
}


void  main111()
{
//泛型编程的调用方式有两种
//自动类型推导
int x =1, y =2;
swap2(x, y);
printf("x:%d y:%d \n", x, y);


float x1= 1.0, y1 = 2.0;


//具体类型调用
swap2<float>(x1, y1);
printf("x1:%f y1:%f \n", x1, y1);
system("pause");
}
函数模板
template<class T>
void printfArray(T *a, int num)
{
cout<<endl;
for (int i=0; i<num; i++)
{
cout<<a[i]<<" ";
}
}


/*
1 函数模板可以像普通函数一样被重载
2 C++编译器优先考虑普通函数
3 如果函数模板可以产生一个更好的匹配,那么选择模板
4 可以通过空模板实参列表的语法限定编译器只通过模板匹配
*/


/*
函数模板不允许自动类型转化
普通函数能够进行自动类型转换
*/


/*
函数模板的深入理


― 编译器并不是把函数模板处理成能够处理任意类型的函数
― 编译器从函数模板通过具体类型产生不同的函数
― 编译器会对函数模板进行两次编译
―在声明的地方对模板代码本身进行编译
―在调用的地方对参数替换后的代码进行编译
*/
2、 类模板
class BB : public AA<int>
{
public:
//BB(int a, int b) : AA(a) 
BB(int a, int b) : AA<int>(a) 
{
this->b = b;
}


private:
int b;
};


#include <iostream>
using namespace std;


template<class T>
class Complex

public:
Complex( T r =0, T i =0 );
Complex(T a) { Real = a ;  Image = 0 ; } 
void print() const;
friend Complex<T>operator+(Complex<T>&c1,Complex<T>&c2)
{
T r = c1.Real + c2.Real ;     T i = c1.Image+c2.Image ;
return Complex<T>( r, i ) ;
}
//friend Complex operator- ( const Complex<T> & c1, const Complex<T> & c2 );
//friend Complex operator- ( const Complex<T> & c );
private:  
T  Real, Image ;
};


template<class T>
Complex<T>::Complex( T r, T i )

Real = r ;  Image = i ; 
}


/*
"class Complex<int> __cdecl operator+(class Complex<int> &,class Complex<int> &)" (??H@YA?AV?$Complex@H@@AAV0@0@Z),ê?该?符¤?号?在¨²函¡¥数ºy _main 中D被À?引°y用®?
1>E:\01-work\09-就¨ª业°¦Ì班㨤0415\day16\泛¤o型¨ª编À¨¤程¨¬\Debug\泛¤o型¨ª编À¨¤程¨¬.exe : fatal error LNK1120: 1 个?无T法¤¡§解a析?的Ì?外ªa部?命¨¹令¢?
========== 生¦¨²成¨¦: 成¨¦功| 0 个?,ê?失º¡ì败㨹 1 个?,ê?最Á?新? 0 个?,ê?跳¬?过y 0 个? ==========
*/




// template<class T> 
// Complex<T>operator+(Complex<T>&c1,Complex<T>&c2)
// { 
// T r = c1.Real + c2.Real ;     T i = c1.Image+c2.Image ;
// return Complex<T>( r, i ) ;
// }


template<typename T> 
void Complex<T>::print()const

cout << '(' << Real << " , " << Image << ')' << endl; 
}




void main61()
{
Complex<int>c1(1, 2);
Complex<int>c2(3, 4);


Complex<int>c3 = c1 + c2;
c3.print();


system("pause");
}





0 0
原创粉丝点击