1、c语言 ,sleep(10); 的头文件 #include <unistd.h>
2、c所有的库函数源代码都位于glibc中,只需要下载glibc包,然后解压即可,具体下载网址:http://ftp.gnu.org/gnu/libc/,可以下载一个c函数速查chm,随时查阅库函数的用法,或者查阅MSDN
3、数据在内存中的存放顺序 (变量的地址,最低地址的那个字节)
(1)一个整数类型内部,低地址存储低位,高地址存储高位。
(2)若干个局部变量(在栈中存储的),先定义的高地址,后定义的低地址
(3)类、结构体或数组的元素,先定义的低地址,后定义的高地址
4、memcpy函数源代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
void *memcpy(void *dst, const void *src, size_t len) { if(NULL == dst || NULL == src){ return NULL; } void *ret = dst; if(dst <= src || (char *)dst >= (char *)src + len){ //没有内存重叠,从低地址开始复制 while(len--){ *(char *)dst = *(char *)src; dst = (char *)dst + 1; src = (char *)src + 1; } }else{ //有内存重叠,从高地址开始复制 src = (char *)src + len - 1; dst = (char *)dst + len - 1; while(len--){ *(char *)dst = *(char *)src; dst = (char *)dst - 1; src = (char *)src - 1; } } return ret; }
5、位段结构体
位段成员必须声明为int,signed int或unsigned int,在成员名的后面是一个冒号和一个整数,这个整数指定该位段所占用的位的个数。
存储方式为:第二个位段无法放在第一个位段剩余的位上时,编译器会把第二个位段放在内存的下一个字节上,在VC 中位段存储单元的大小是4字节。位段不能跨平台使用。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
struct packed { unsigned one:1; //占一位 unsigned two:2; //占二位 unsigned three:3; //占三位 unsigned four:4; //占四位 } data;
6、结构体的内存对齐
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> using namespace std; #pragma pack(1)// struct S1 { char C1; int i; char C2; }; int main() { cout<<sizeof(struct S1)<<endl; //6(12) return 0; }
7、某些编译器为空指针使用不存在的内存地址。
10、二级指针传参创建链表
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<stdlib.h> 3 4 typedef struct node 5 { 6 int date; 7 struct node *next; 8 }node; 9 10 void Creatlink(struct node ** tp,int k); 11 int main() 12 { 13 int tmp; 14 struct node *head =NULL,*tail =NULL; 15 head=(struct node *)malloc(sizeof(node)); 16 scanf("%d",&(head->date)); 17 tail=head; 18 while(~scanf("%d",&tmp) && tmp){ 19 Creatlink(&tail,tmp); 20 } 21 tail->next=NULL; 22 for(tail=head;tail;tail=tail->next) 23 printf("%d ",tail->date); 24 return 0; 25 } 26 27 void Creatlink(struct node ** tp,int k) 28 { 29 (*tp)->next=(struct node *)malloc(sizeof(node)); 30 (*tp)->next->date=k; 31 (*tp)=(*tp)->next; 32 }
11、c++ 返回对象引用与返回对象 https://blog.csdn.net/lws123253/article/details/80382401
12、若派生类执行无参构造函数,则其基类必须定义有无参构造函数才能正常执 ,这个说法是错的,如果基类有默认的构造函数,是不需要定义的。
13、C++ 调用虚函数操作的只能是对象指针或对象引用,否则仍为静态联编;
14、在宏定义#define PI 3.14159中,用宏名PI代替一个字符串
15、关系运算符<= 与 == 的优先级不相同。
16、在C程序中,可以将整型数以二进制形式存放到文件中的函数是fwrite()
17、fread(buffer,size,count,fp);其中的buffer代表的是一个指针,指向要存放读入数据的地址
18、http://forspeed.onlinedown.net/down/126disk.com_csf.rar
19、C结构体内不允许有静态变量,可以用全局变量代替
21、C++在new时的初始化的规律可能为:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0。
28、LIB和DLL的区别与使用 https://www.cnblogs.com/zkwarrior/p/10948174.html
29、freopen("F:\\桌面\\test.txt","r",stdin);
30、数组名,不是变量
31、编译器内置宏:__FILE__ 和 __LINE__ ,__FILE__表示代码所在文件路径的字符串,__LINE__表示代码所在行的行数
32、函数的包装,有参、无参,同名,不同名的函数包装,函数指针
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> void* f1( void(*f)(int,int) ){ return (void*)f; } void f2(int i,int j){ //有参,同名 printf("%d\n",i+j); } void* f2(){ //无参,同名 return (void*)f1(f2);//调用f1并返回有参函数指针 } void f3( void* (*f)() ) //传无参,使用有参 { int x=3,y=4; void (*p)(int,int) = ( void(*)(int,int) )f(); p(x,y); } int main() { f3(f2); //传无参函数,使用有参函数 return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> void f1(int i,int j){ //有参,不同名 printf("%d\n",i+j); } void* f2(){ //无参 ,不同名 return (void*)f1; //传不同名有参函数指针 } void f3( void* (*f)() ) //传无参,使用有参 { int x=3,y=4; void (*p)(int,int) = ( void(*)(int,int) )f(); p(x,y); } int main() { f3(f2); return 0; }
33、循环相克
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <stdio.h> 2 int main () 3 { 4 //x,y的状态都是0 1 2 5 //循环相克 6 int x,y; 7 while(1){ 8 scanf("%d%d",&x,&y); 9 if( 10 !(x==0||x==1||x==2)|| 11 !(y==0||y==1||y==2) 12 ) continue; 13 14 if( x==(y+1)%3 )puts("x"); 15 else if(x==y) puts("t"); 16 else puts("y"); 17 } 18 19 return(0); 20 }
34、全局变量,默认是extern,作用域是整个工程,在一个文件内定义的全局变量,在另一个文件中,通过extern对全局变量进行声明,就可以使用全局变量,const变量默认是局部变量,在其他文件使用,就必须申明extern
在被引用的文件extern可以省略,引用的文件中不能省略,它只是一个声明,跟定义有区别,int a 是定义, extern int a是申明,定义编译就会分配内存,定义只能一次,声明可以多次
全局变量仅限本文件引用,而不能被其他文件引用,可以在定义全局变量时在前面加一个static关键字
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*main.cpp*/ #include "111.h" int main() { char press; int winer=0; system("color 2f"); l: drawqipan(); press=getch(); while(1) { Keypress(press); if(press=='p') winer=checkWin(); if(winer!=0) gotoxy(0,20); if(winer==2) printf("the side of ● wins\n"); else if(winer==1) printf("the side of ○ wins\n"); else { // if(player==0) // { // //cluozi(1,2); //此处落子由电脑控制 // } press=getch(); continue; } printf("do you want to play again?(y/n):"); p: press=getch(); if(press=='n') break; else if(press=='y') { winer=0; goto l; } else goto p; } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*111.h*/ #ifndef xxx_H_ #define xxx_H_ //包含的头文件 #include "stdio.h" #include "windows.h" #include <stdlib.h> #include <conio.h> #define up 'w' #define left 'a' #define down 's' #define right 'd' #define lz 'p' #define cls 'q' //结构体声明 struct stu { //定义位置记录结构体 int x; int y; }; //全局变量声明 extern struct stu weizhi; extern int player; extern int Q[20][20];//定义数组以记录落子情况 //函数声明 void gotoxy(int x, int y); void drawqipan(); void jilu(); int cluozi(int x,int y) ; void luozi() ; int checkWin() ; void Keypress(char n) ; #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*111.cpp*/ #include "111.h" //全局变量的定义 struct stu weizhi; int player=1; int Q[20][20]= {0}; //定义数组以记录落子情况 //函数的定义 void gotoxy(int x, int y) //建立坐标函数 { COORD c; c.X=2*x; c.Y=y; SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE), c); //修改当前光标的位置 } void drawqipan() //绘制棋盘及数据初始化 { int i,j; system("cls"); //清除屏幕 for(i=0; i<20; i++) { for(j=0; j<20; j++) { Q[i][j]=0; printf("十"); } printf("\n"); } weizhi.x=0; weizhi.y=0; //程序数据初始化 gotoxy(0,0); } void jilu() //记录落子情况 { Q[weizhi.x][weizhi.y]=player+1; if(player) { player=0; //玩家变换 return; } player=1; } int cluozi(int x,int y) //由电脑落子时调用 { weizhi.x=x; weizhi.y=y; gotoxy(weizhi.x,weizhi.y); if(Q[weizhi.x][weizhi.y]==0) { //判断当前位置是否已经落子 jilu(); printf("○"); gotoxy(weizhi.x,weizhi.y); } } void luozi() //玩家落子 { if(Q[weizhi.x][weizhi.y]==0) { //判断当前位置是否已经落子 if(player) { jilu(); printf("●"); } else { jilu(); printf("○"); } gotoxy(weizhi.x,weizhi.y); } } int checkWin() //检查游戏是否有输赢 { int p; int r,c,rr,cc,count=0; p=player==0?2:1; for(c=0; c<20; c++) { for(r=0; r<20; r++) { if(Q[r][c]!=p) continue; //检查列 rr=r; cc=c; while(--cc>=0 &&Q[rr][cc]==p) count++; cc=c; while(++cc<20 &&Q[rr][cc]==p) count++; cc=c; if(count+1>=5) return p; //检查行 count=0; while(--rr>=0 &&Q[rr][cc]==p) count++; rr=r; while(++rr<20 &&Q[rr][cc]==p) count++; rr=r; if(count+1>=5) return p; //检查反斜边 count=0; cc--; rr--; while((cc>=0||rr>=0) &&Q[rr][cc]==p) { count++; cc--; rr--; } rr=r; cc=c; cc++; rr++; while((cc<20||rr<20) &&Q[rr][cc]==p) { count++; cc++; rr++; } rr=r; cc=c; if(count+1>=5) return p; count=0; //检查正斜边 count=0; cc++; rr--; while((cc<20||rr>=0) &&Q[rr][cc]==p) { count++; cc++; rr--; } rr=r; cc=c; cc--; rr++; while((cc>=0||rr<20) &&Q[rr][cc]==p) { count++; cc--; rr++; } rr=r; cc=c; if(count+1>=5) return p; count=0; } } return 0; } void Keypress(char n) //光标位置移动 { switch(n) { case up: if(weizhi.y<=0) weizhi.y=19; else weizhi.y--; gotoxy(weizhi.x,weizhi.y); break; //向上移动光标 case left: if(weizhi.x<=0) weizhi.x=19; else weizhi.x--; gotoxy(weizhi.x,weizhi.y); break; //向左移动光标 case right: if(weizhi.x>=19) weizhi.x=0; else weizhi.x++; gotoxy(weizhi.x,weizhi.y); break; //向右移动光标 case down: if(weizhi.y>=19) weizhi.y=0; else weizhi.y++; gotoxy(weizhi.x,weizhi.y); break; //向下移动光标 case lz: luozi(); break; //开始落子操作 case cls: drawqipan(); break; //重新开始 } }
五子棋
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*main.cpp*/ #include "111.h" int main() { int ctrl = 1; while (ctrl) { //棋盘 drawqipan(); system("color 2f"); //下棋 xiaqi(); //循环 gotoxy(0,21);//提示语放到xiaqi()函数里会让循环代码莫名其妙 printf("输入0结束游戏游戏,输入1重新开始:"); scanf("%d", &ctrl); system("cls"); } return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*111.h*/ #ifndef xxx_H_ #define xxx_H_ //包含的头文件 #include "stdio.h" #include <stdlib.h> #include <windows.h> #include <conio.h> #define up 'w' #define left 'a' #define down 's' #define right 'd' #define lz 'p' #define cls 'q' //结构体声明 struct stu { //定义位置记录结构体 int x; int y; }; //全局变量声明 extern struct stu weizhi; extern int player; extern int Q[20][20];//定义数组以记录落子情况 //函数声明 void xiaqi(); //下棋 void gotoxy(int x, int y); void drawqipan(); void jilu(); int cluozi(int x,int y) ; void luozi() ; int checkWin() ; void Keypress(char n) ; #endif
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*111.cpp*/ #include "111.h" //全局变量的定义 struct stu weizhi; int player=1; int Q[20][20]= {0}; //定义数组以记录落子情况 //函数的定义 void xiaqi() { char press; int winer=0; while(1) { press=getch(); Keypress(press); if(press=='p') winer=checkWin(); if(winer!=0) gotoxy(0,20); if(winer==2){ printf("the side of ● wins\n"); break; } else if(winer==1){ printf("the side of ○ wins\n"); break; } // if(player==0) // { // cluozi(1,2); //此处落子由电脑控制 // } } } void gotoxy(int x, int y) //建立坐标函数 { COORD c; c.X=2*x; c.Y=y; SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE), c); //修改当前光标的位置 } void drawqipan() //绘制棋盘及数据初始化 { int i,j; system("cls"); //清除屏幕 for(i=0; i<20; i++) { for(j=0; j<20; j++) { Q[i][j]=0; printf("十"); } printf("\n"); } weizhi.x=0; weizhi.y=0; //程序数据初始化 gotoxy(0,0); } void jilu() //记录落子情况 { Q[weizhi.x][weizhi.y]=player+1; if(player) { player=0; //玩家变换 return; } player=1; } int cluozi(int x,int y) //由电脑落子时调用 { weizhi.x=x; weizhi.y=y; gotoxy(weizhi.x,weizhi.y); if(Q[weizhi.x][weizhi.y]==0) { //判断当前位置是否已经落子 jilu(); printf("○"); gotoxy(weizhi.x,weizhi.y); } } void luozi() //玩家落子 { if(Q[weizhi.x][weizhi.y]==0) { //判断当前位置是否已经落子 if(player) { jilu(); printf("●"); } else { jilu(); printf("○"); } gotoxy(weizhi.x,weizhi.y); } } int checkWin() //检查游戏是否有输赢 { int p; int r,c,rr,cc,count=0; p=player==0?2:1; for(c=0; c<20; c++) { for(r=0; r<20; r++) { if(Q[r][c]!=p) continue; //检查列 rr=r; cc=c; while(--cc>=0 &&Q[rr][cc]==p) count++; cc=c; while(++cc<20 &&Q[rr][cc]==p) count++; cc=c; if(count+1>=5) return p; //检查行 count=0; while(--rr>=0 &&Q[rr][cc]==p) count++; rr=r; while(++rr<20 &&Q[rr][cc]==p) count++; rr=r; if(count+1>=5) return p; //检查反斜边 count=0; cc--; rr--; while((cc>=0||rr>=0) &&Q[rr][cc]==p) { count++; cc--; rr--; } rr=r; cc=c; cc++; rr++; while((cc<20||rr<20) &&Q[rr][cc]==p) { count++; cc++; rr++; } rr=r; cc=c; if(count+1>=5) return p; count=0; //检查正斜边 count=0; cc++; rr--; while((cc<20||rr>=0) &&Q[rr][cc]==p) { count++; cc++; rr--; } rr=r; cc=c; cc--; rr++; while((cc>=0||rr<20) &&Q[rr][cc]==p) { count++; cc--; rr++; } rr=r; cc=c; if(count+1>=5) return p; count=0; } } return 0; } void Keypress(char n) //光标位置移动 { switch(n) { case up: if(weizhi.y<=0) weizhi.y=19; else weizhi.y--; gotoxy(weizhi.x,weizhi.y); break; //向上移动光标 case left: if(weizhi.x<=0) weizhi.x=19; else weizhi.x--; gotoxy(weizhi.x,weizhi.y); break; //向左移动光标 case right: if(weizhi.x>=19) weizhi.x=0; else weizhi.x++; gotoxy(weizhi.x,weizhi.y); break; //向右移动光标 case down: if(weizhi.y>=19) weizhi.y=0; else weizhi.y++; gotoxy(weizhi.x,weizhi.y); break; //向下移动光标 case lz: luozi(); break; //开始落子操作 case cls: drawqipan(); break; //重新开始 } }
35、静态二维数组传参
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> void f(int** arr, int m, int n){ for(int i=0; i<m; ++i){ //行 for(int j=0; j<n; ++j){ //列 printf( "%d ", arr[i][j] ); } } } int main() { int arr[2][3] = { 1,2,3, 4,5,6 }; int* p[3]; for(int k=0; k<2; ++k){ p[k] = arr[k]; } //p本质上是一维数组,每个数组元素都是指针 //p是数组名,表示数组的首地址, p = &p[0] //p[0]( 即arr[0] )是一维数组(1,2,3)的地址,p就是一个二维指针了 /* int** pp = p; f(pp,2,3); */ f(p,2,3); //传二维 return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> void f(int* arr, int m, int n){ for(int i=0; i<m; ++i){ //行 for(int j=0; j<n; ++j){ //列 // i*n //行*列数 printf( "%d ", *(arr + i*n + j) ); } } } int main() { int arr[2][3] = { 1,2,3, 4,5,6 }; f(arr[0],2,3); //传一维 return 0; }
36、柔性数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct test{ int a; double b; char p[]; //p[0] 柔性数组 C99标准支持不完整类型 }test; int main() { char a[] = "Hello"; test *t = (test*) malloc( sizeof(test) + sizeof(a) ); if( t ){ strcpy( (char*)( t+1 ),a ); //a拷贝到结构体后面的空间里 sizeof(test) 之后 printf( "%s\n", t+1 ); //该空间是malloc分配 } free( t ); //释放 return 0; }
67、typedef 指针与 const 的结合所产生的问题
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int main() { char str1[] = "Hello"; char str2[] = "World"; typedef char* pchar; //pchar是个指针,const pchar,const是限制指针的,不是限制指针指向的 const pchar cstr = str1; // 相当于 char *const cstr //pchar const cstr = str1 ; //同理 //cstr = str2; //错误,说明指针cstr是const的,不可以改变指向 cstr[0] = 'W'; //可以运行,说明可以通过指针cstr改变所指向的变量的值 printf("%s\n", cstr ); return 0; }
68、组合数分解
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> /* 组合数学理论中,一个自然数可以唯一分解为k个组合数之和,公式所示: N = (ck, k ) + ... + (c2, 2) + (c1, 1) ck>... >c2>c1>=0 (ci, i ) ci! /( i!-(ci-i)! ) 0 ci < i 72 5 // n=75,k=5 72 = (8,5) + (6,4) + (3,3) + (1,2) + (0,1) 56 15 1 0 0 */ //阶乘计算函数 long long fac[1000] = {1,1}; long long fact( int k){ int i=k+1; for(; !fac[i-1];--i ); for(; i<=k; ++i){ //计算阶乘 fac[i] = fac[i-1]*i; } return fac[k]; } //通项式函数 int term(int ci, int i){ //组合数之和 通项式 return fact(ci)/( fact(i)*fact(ci-i) ); } //一个系数计算 int coef(int n, int i, int* t ){ int ci=i; for( int tmp=0; tmp=term(ci,i),n>=tmp; ++ci ) *t = tmp; return ci-1; } //全部系数计算 void calcom(int n, int k, int c[]){ int index=0; while(k>0){ int t=0; c[index++] = coef(n,k,&t); //存储系数 n-= t; k--; } } int main() { int n=854,k=4,ci=0,t=0; int c[1000] = {0}; //数组存储系数 calcom( n,k,c ); //计算 for(int i=0; i<k; ++i){ //打印系数 printf("%d,", c[i] ); } return 0; }
69、递归打印回文数
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> void f(int x[],int n){ if(n>1){ printf("%d,",x[0]); f(&x[1],n-1); printf("%d,",x[0]); } else printf("%d,",x[0]); } int main() { int arr[] = {4,5,6,7,8}; f(arr,5); return 0; }
70、命令行输出字符串
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char**argv) { //printf("%d\n",argc); int size = argc-1; char**str = (char**)malloc(size*sizeof(char*)); for(int i=0; i<size; i++){ str[i]=(char*)malloc(8*sizeof(char)); } for(int i=0; i<size; ++i){ strcpy(str[i],argv[i+1]); } for(int i=0; i<size; ++i){ printf("%s ",str[i]); } for(int i=0; i<size; ++i){ free(str[i]); } free(str); return 0; }
71、strtod 函数,从字符串 提取数字,包括数字0
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <stdlib.h> int main() { char str[] = "0x00ghi0x11xyz789.1aaaaa"; char* p=str,*q=str; double x; while( *p ){ x = strtod(p,&q); if( p<q ){ //字符串提取数字,包括0,不能用返回值x判断,用q判断 printf("%f,",x); p=q; } p++; } return 0; }
72、篮球赛
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> /* 篮球赛 */ int main() { char a, b, c; for(a='x'; a<='z'; ++a ){ //a与 x,y,z for(b='x'; b<='z'; ++b){ //b与 x,y,z if(a!=b ) //一对一比赛 比如,a与x比赛,则b不能与x比赛 //注释掉就可以看明白 { for(c='x'; c<='z'; ++c){ //b与 x,y,z if(a!=c && b!=c)//一对一比赛 比如,a与x比赛,则c不能与x比赛 { //同理,则b不能与x比赛,则c不能与x比赛 //注释掉就可以看明白 if(a!='x' && (c!='x'&&c!='z') ){ //题目给的条件,a不与x比赛,c不与x比赛,c不与z比赛 printf("三对赛手名单:a--%c, b--%c, c--%c\n", a, b, c ); } } } //c end } // a!=b end } //b end } // a end return 0; }
73、1~9组成的3个3位数,1:2:3
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int func( int x, int y, int z ) { int num[10] = {0}; int ret = 1; while( x ) { if( ++num[ x%10 ]>1 || ++num[ y%10 ]>1 || ++num[ z%10 ]>1 || num[0] >=1 ) { ret = 0; break; } x/=10, y/=10, z/=10; } return ret; } int main() { for(int num=123; num<=333; ++num ){ if( func(num, 2*num, 3*num ) ){ // 1:2:3 printf("%d,%d,%d\n", num, 2*num, 3*num ); } } return 0; }
74、删除重复字符,比如,abb,输出a
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//使用指针 #include <stdio.h> int main() { char str[128]; gets(str ); char* p1=str, *p2=str, *p3=p2; while(*p2 )//p2遍历 { if(*p2 != *(p2+1) ) { *p1++ = *p2++; //p2移动一位 p3=p2+1; } else //连续2个字符相等包含2个以上 { if(*p2 == *p3 ) p3++; else p2= p3; //p2移动一位以上 } } *p1 = '\0'; //字符串结束标志 printf("%s\n", str ); return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int main() { char str[128]; gets(str ); int i=0, j=0, t=1; while(str[i] )// i 不是'\0',则 i+1 是 '\0' { if(str[i] != str[i+1] ) //向后比较一位,连续2个字符不等 { str[j++] = str[i++]; //更新j,更新i t=1; //避免嵌套循环,借用while } else //连续2个字符相等包含2个以上 { if(str[i] == str[i+t] ) //2个以上,i+1,i+2,i+3,... t++; else //否则更新i i+=t;//i所指,为之前字符的非重复位置 } } str[j] = '\0'; //字符串结束标志 printf("%s\n", str ); return 0; }
75、子串和
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> #include <string.h> /* f[i]:表示以s[i]结尾的子串 f[i]=f[i-1]+i-pos[s[i]] 在s[i]以前不包含s[i]的只有i-pos[s[i]]个起点,终点确定,所以要加上i-pos[s[i]] */ int main() { char str[100000+1] = "ababc"; long long f[100000+1] = {0}; long long pos[100000+1] = {0}; int sum=0; gets(str+1 ); int n = strlen(str+1 ); for(int i=1; i<=n; ++i ) { f[i] = f[i-1]+i-pos[str[i] ]; pos[str[i] ] = i; sum += f[i] ; } printf("%d\n", sum ); return 0; }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int function(char *str, int i, int j ) { int sum=0; int key[26] = {0 }; for(int k=i; k<=j && str[j]; ++k ) { int ch = str[k]-'a'; if( !(key[ch]++ ) ) sum++; } return sum; } int main() { char str[100000+1] = "ababc"; int sum=0; //gets(str ); for(int i=0,j=0; str[i]; ++j ) { if( !str[j] ) { i++; j=i; } sum += function(str,i,j ); } printf("%d\n", sum ); return 0; }
76、指针数组、二维数组
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> int main() { /* int arr1[] = { 1,2,3,4,5 }; int arr2[] = { 2,3,4,5,6 }; int arr3[] = { 3,4,5,6,7 }; int* parr[3] = { arr1,arr2,arr3 }; //指针数组//3个数组的元素不是连续的 int **pp = parr; int i = 0; //第i行元素 for (int*p = *pp; 3 > (i += (5 > p-*pp ) ? 0 : (p = *++pp, printf("\n"), 1) ); ++p ) { printf("%d,",*p ); } */ int parr[][5] = {{ 1,2,3,4,5 }, { 2,3,4,5,6 }, { 3,4,5,6,7 } //二维数组//每个元素都是连续的 }; int (*pp)[5] = parr; int i = 0; for (int*p = *pp; 3*5 > p-*pp; ++p ) { printf("%d,",*p ); if(0 == ++i%5 ) printf("\n"); } return 0; }
指针数组元素为包装不等长数组的对象地址
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <stdio.h> struct Arr{ int *arr; int length; }arr1{new int[5]{1,2,3,4,5},5}, //new arr2{new int[8]{2,3,4,5,6,7,8,9 },8 }, arr3{new int[5]{3,4,5,6,7},5 }; int main() { struct Arr* parr[3] = { &arr1,&arr2,&arr3 }; //指针数组//3个对象里的数组元素不等也不连续 struct Arr **pp = parr; int i = 0; //第i个元素 for (int*p = (*pp)->arr; 3 > (i += ((*pp)->length > p-(*pp)->arr ) ? 0 : (p = (*++pp)->arr, printf("\n"), 1) ); ++p ) { printf("%d,",*p ); } delete[] arr1.arr; //释放 delete[] arr2.arr; delete[] arr3.arr; return 0; }