智健blog

c语言知识点

c语言

变量声明 定义 初始化

  • 变量声明:对变量进行类型说明
    • 定义性声明:分配内存空间,简称定义
    • 引用性声明:extern引用其他的变量,不再额外分配内存空间,简称声明
  • 变量 定义 初始化:为变量赋值,分配内存空间

变量作用域

每个变量和函数有两个属性:类型和存储类别。存储类别分静态存储区和动态存储区

  • 静态存储区

    全局变量存放的位置

    //static时静态外部变量,只能用于本文件,不能被延伸到其他文件
    for (int i=1;i<3;++i){
      static int a=3;
      a++;
    }//a的值为6,当循环再一次执行static语句赋初值时会忽略,因为静态存储区只赋初值一次
    
    //extern,其实是将其他地方的变量作用于延伸到extern处
    //file1.c文件有int a;变量
    //在file2/c文件若公用file1.c文件里a,则按下面方式声明即可
    extern a;
    
  • 动态存储区

    局部变量存放的位置,如果局部变量加上static声明后,就会变为静态存储区,执行期间不被释放。

流程图

练习流程图 N-S图

输入输出

​ 都不属于关键字,属于库函数

  • scanf,对多个变量进行输入

    scanf("%d%d%d",a,b,c)   //整型,用空格隔开
    
  • printf()

    printf("%m.nf");  //m代表整个输出字符的宽度,n代表小数精确到n位。剩余列空间用空格在左端补上,若指定宽度小于实际宽度,则按实际宽度输出
    

运算符

  • % :取余
  • /:除号,用来做运算的,10/5=2

数据类型及运算

  • 浮点型

    • float型(单精度):单精度浮点数用4字节存储,可精确到小数点七位
    • double型(双精度):双精度浮点数用8字节存储
  • 浮点型 分母型

    需要用float或者double型,常量与浮点型相乘除时候,常量也要加小数点

    • 保留三位小数点

      printf("%.3f",0.56789)
      
  • void 空类型

    是指向空类型或者不指向确定的类型的数据,并非是能指向任何类型的数据 p287页

    //如需指向
    
  • 字符型与整型=整型(通过ASCII码)

  • 运算

    int i=1,j=5;
    int c=i+(++j);   //c为7
    c=i+++j          //c为6
    
  • 赋值

    int c=i=j; // 先将j的值赋给i,然后i的值赋给c
    
    • 左值与右值

      //在赋值运算符左边的是左值,右边的是右值
      int a = (b=3*4)  //a的结果为3*4
      int a = (a=b) = 3*4  //此表达式错误,因为(a=b)相对于3*4是左值,但(a=b)要么是1要么是0.不符合左值的要求
      
  • 算数符 关系符 赋值符

    • 优先级

      算数》关系》赋值

    a>b==c 等价于 (a>b)==c
    
    • !(非)》算术》关系》&& || 》赋值
    5>3 && 8<4-!0
    5>3 && 8<(4-!0)
    //等价,结果都是0
    
    • 如果一个表达式中的两个操作数具有相同的优先级 则用结合律

      算术运算符和操作数的组合方式是从左到右,赋值运算符则是从右到左

      *p1++ 等价于 *(p1++) 作用是先取出p1的值,然后p1++
      *++p1 等价于 *(++p1) 作用是p1先自加1,然后取出p1的值
      
    • 关系表达式和逻辑表达式的值都为0或1

数组

数组名只代表数组的首元素的地址

  • 字符数组与字符串指针

    //指针变量的值是可以改变的,而数组名代表一个固定的值,不可改变
    
    //使用字符数组时,只能采用在定义数组时初始化或逐个对元素赋值的方法
    char str[100];
    char str[]={};//只能通过下标再对它进行赋值
    
    char *string;
    string="dsa";//string指针指向字符串的首地址元素
    string[1]=='s';//但不可改变其值
    
    
    //只能用地址加减法访问,不能自增自减,如
    printf("%s",str+2);//合法(str是数组名)
    str=str+1  //不合法
    

字符数组处理

//puts函数
char str[]={"hello"};
puts(str);

//gets函数
char str[10];
get(str);

char str[]={"sunzhijian"};
str[11]='d';
puts(str);//结果为sunzhijian,第十位是'\0',puts发现\0后就结束输出

char str[]={"sunzhijian"};
str[10]='d';
str[11]='d';
puts(str);//结果为sunzhijiandd

//二维数组定义时 第二个下标必须声明

字符数组的库函数操作

先include<string.h>
//比较
strcmp(str1,str2)//相同则0,以第一个不相同的字母比较结果为准,str1》2则返回1,str《str2返回-1
//连接
strcat(str1,str2);//将str2连接到str1上去,且返回str1
//赋值
strcpy(str1,str2);//将str2按下标赋值到str1上去
strncpy(str1,str2,n);//将str2中前n个字符赋值到str1前n位上去

//实际长度
strlen(str);//等价于遍历到str[i]=='\0';

//字符数组的大小写转换
strlwr(str)//将字符串大写转小写
strupr(str)//将字符串小写转大写

指针

要区别指针和指针变量,指针就是地址本身,就是一个具体的地址值,而指针变量是用来存放地址的变量。所以认为指针是类型名是错误的,类型是没有值的,只有变量才有其值。

指针变量的值是所指向变量的内存地址,在指针变量上加*代表指针所指向变量。通过※point_a可以对变量a进行操作。

  • 一个指针包含:存储单元编号的地址;它指向的存储单元的数据类型

  • 由于数据在内存中所占的字节数和存储方式的不同,指针必须指定基类型

  • 指针变量只能赋值内存地址,不能直接赋值整型。但可以把指针指向到一个整型数

*point_a == a;//二者是等价的
point_a == &a;//二者是等价的
  • 实参与形参的数据传递是“值传递”的方式,传递的只是单纯的数值.

数组指针

  • 指针可以指向数组中的每一个元素

    int *p1,*p2;
    int list[]={1,2,3,4};
    p1=&list[1],p2=&list[2];
    
    //p2-p1等于1
    p1+1等于list[2];//加的是数组元素所占的字节数,不是单纯的1,并且数组元素在内存中地址是连续的
    p++//数组指针p加一个存储单元的长度
    

指针数组

int *p[4];//因为[]优先级高于*,所有p先与[]组合,成为一个包含四个元素的数组,而int * 声明数组中的元素都是int型指针类型的
int (*p)[4];//p声明为一个指针变量,指向包含四个整型元素的一维数组

多维数组指针

若a是一个二维数组,则其性质为

  • [] 优先级高于 *

  • 获取二维数组的某个元素使用两次※或者 [] ,二个符号可任意组合

  • a+i是个行指针,即指向的是一整行(某行的整块),而不是单个元素,对它加一则代表指向下一行

  • a[i]代表a的第i行首地址,即&a【i】[0]

    a是二维数组名,从二维角度进行操作
      //a+i是个行指针,即指向的是一整行(某行的整块),而不是单个元素,对它加一则代表指向下一行
    a[i]是一位数组名,从一维角度进行操作
      //a[i]+1 则是从第i行第二个元素
      //参考 p256 图8.20
    
  • *(a+1)[2],代表从第二行往下再加两行得到的首地址元素

  • 二维数组

    //二维数组参数
    void func(int a[][3]);
    int array[][3]={{1,2}};
    func(a);//因为传递的是内存地址,若在func中改变a的值,则array的值业随之改变
    
  • 二维数组指针

    int (*p)[3]; //指向一维数组(包含四个元素)的指针
    void output( int (*p)[3]){p[1][1]}  //可以传入一个n行三列的数组
    //p[1][2]第二个数组的指针的第三个下标
    

函数指针

指向函数的指针

程序中定义了一个函数,编译时,会为其分配一段存储空间,存储空间的起始地址称为函数的指针

  
int (*p)(int,int);//p是指向函数的指针,且函数参数为两个整型,返回值为int型
int (*p)(int,int);//定义函数指针
p=max;//指针指向函数,不能将形参给出,否则就是把函数执行后的返回值给p了
(*p)(a,b);//屌用函数
函数类型为指针的函数

函数类型为指针的函数也就是定义一个返回值为指针的函数

int *p(int,int){}//()优先级高于*
//p先与()结合成函数,然后*声明为int指针类型

动态分配内存

需要头文件 # include <stdlib.h>

  • malloc函数

    void *malloc(unsigned int size);
    void *calloc(unsigned n,unsigned size);
    void free(void *p);
    void *realloc(void *p,unsigned int size);
    

结构体

  • 定义

    有两种定义方式:typedef struct 和struct

    struct 结构体名{
    }变量名;
    
    struct Stu{  
    };
    struct Stu stu1;//声明结构体变量stu1,需要指明Stu是个结构体类型
    
    
    typedef struct 结构名{
    }结构体别名;//结构体别名只是名称,不是具体的变量
    
    typedef struct Stu{//typedef 的作用告诉系统Stu是个结构体类型名
    };
    
    //声明结构体变量
    Stu stu1;
    
    
    typedef struct Node{
    }Node,*Nodep;//给结构体起别名Node,此结构体指针类名为Nodep
    
    Node node1;
    Nodep *p;
    
    
    struct Node{
    }node,*p;//声明一个node结构体变量,和一个p结构体指针
    

原码 补码 反码

  • 补码

    • 正数的原码等于补码

    • 负数的补码等于原码的数字位取反,末位加一

库函数

math

  • sqrt(number) :求number的平方根
  • fabs(double number):求number的绝对值

经典算法

  • 模块化
  • 数据类型
    • 一维数组
    • 二维数组
    • 链表
    • 公式
  • 记住经典算法

判断素数(1-100内)

  • 判断素数函数模块

    • 如果传入是素数,return 1;否则return 0;

    反向求解

  • 如果i不能被2~i-1的数整除,则是素数

//判断素数模块
int isPrim(int x){
  int i;
  //从2开始
  for(i=2;i<x;i++)
    if (x%i==0) 
      return 0;
  return 1;
}

//装素数
void fun(int a[]){
  int i,index=0;
  for(i=2;i<=100;i++)
    if(isPrim(i))
      a[k++]=i;
}

闰年

  • 分析条件

    能被4整除且不能被100整除

    可被400整除

  • code

    (year%4==0&& year%100!=0 || year % 400 ==0)
    
posted @ 2020-09-21 20:20  智健  阅读(160)  评论(0编辑  收藏  举报