日记2----C专用

Posted on 2019-10-31 15:54  金色的省略号  阅读(676)  评论(0编辑  收藏  举报

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函数源代码:

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;
}
View Code

5、位段结构体

位段成员必须声明为int,signed int或unsigned int,在成员名的后面是一个冒号和一个整数,这个整数指定该位段所占用的位的个数。

存储方式为:第二个位段无法放在第一个位段剩余的位上时,编译器会把第二个位段放在内存的下一个字节上,在VC 中位段存储单元的大小是4字节。位段不能跨平台使用。

struct packed {
    unsigned one:1;   //占一位
    unsigned two:2;   //占二位
    unsigned three:3; //占三位
    unsigned four:4;   //占四位
} data;
View Code

6、结构体的内存对齐

#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;
}
View Code

7、某些编译器为空指针使用不存在的内存地址。

10、二级指针传参创建链表

 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  }
View Code

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、函数的包装,有参、无参,同名,不同名的函数包装,函数指针

#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;
}
View Code
#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;
}
View Code

33、循环相克

 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 }
View Code

34、全局变量,默认是extern作用域是整个工程在一个文件内定义的全局变量,在另一个文件中,通过extern对全局变量进行声明,就可以使用全局变量const变量默认是局部变量,在其他文件使用,就必须申明extern

  在被引用的文件extern可以省略,引用的文件中不能省略,它只是一个声明,跟定义有区别,int a 是定义, extern int a是申明,定义编译就会分配内存,定义只能一次,声明可以多次
  全局变量仅限本文件引用,而不能被其他文件引用,可以在定义全局变量时在前面加一个static关键字

/*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;
}
View Code
/*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
View Code
/*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;         //重新开始
    }
}
View Code

  五子棋

/*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;
}
View Code
/*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
View Code
/*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;         //重新开始
    }
}
View Code

35、静态二维数组传参

#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;
}
View Code
#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;
}
View Code

36、柔性数组

#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;
}
View Code

67、typedef 指针与 const 的结合所产生的问题

#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;
}
View Code

68、组合数分解

#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;
}
View Code

69、递归打印回文数

#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;
}
View Code

70、命令行输出字符串

#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;
}
View Code

 71、strtod 函数,从字符串 提取数字包括数字0

#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;
}
View Code

72、篮球赛

#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;
}
View Code

73、1~9组成的3个3位数,1:2:3

#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;
}
View Code

74、删除重复字符,比如,abb,输出a

//使用指针
#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;
}
View Code
#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;
}
View Code

75、子串和

#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;
}
View Code
#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;
}
View Code

76、指针数组、二维数组

#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;
}
View Code

指针数组元素为包装不等长数组的对象地址

#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;
}
View Code