C语言复习笔记

数学函数

  • 上取整函数ceil(),下取整函数floor(),传入双精度浮点数参数,返回整形
  • 幂指函数pow(a,n)=a^n,a整形/浮点型
  • 平方根函数sqrt(),传入双精度浮点数参数,返回浮点数

printf

%g,实数格式占位符
%p,输出指针的值/地址

函数

  • 函数声明时可以不写形参名,但要写形参类型

  • 值传递变指针传递:实参前加&,形参前加*,形参使用前加*

  • 函数作为参数C语言复习笔记

    • 函数不能值传递
    • 函数定义时形参写法
      • 第一个参数:函数返回值做变量类型,(*函数名)(函数参数类型)
        • (*函数名)实际是函数指针,这里的函数名指针可以不和函数名名字相同,毕竟是一个形参,代表一类参数
      • 二个参数:函数参数
        • 该参数也可以没有,则外函数的定义中要包含该参数以便内函数传参
      • 函数调用时实参写法:第一个参数只写函数名,第二个参数写函数参数

输出N以内所有质数的方法

  • 双for循环依次判别质数,可优化
  • 筛法:标记出所有非质数,输出未被标记的数
    • 从小到大判断是否为质数,若为质数将其倍数的标志位都标称合数

字符串的输入输出

  • 输出printf("%s",string),字符串整体输出
  • 输入scanf("%s",string),不写&因为数组名代表数组指针
  • scanf遇空格结束
  • sprintf(string,printf的输出语法),输出写入字符串string

指针

  • 字符串字面量不是变量
  • 内存
    • 栈区:存储局部变量,编译时自动分配大小固定
    • 堆区:手动申请,需手动释放,大小不固定
    • 全局区:存储全局变量和静态变量
    • malloc.h和stdlib.h用于申请堆内存
      • intp=(int)malloc(n*sizeof(int));
      • intp=(int)calloc(n,sizeof(int));(初始化为0)
      • free§;p=NULL;
      • malloc默认返回void*
      • 一般用于动态内存分配,提前申请多的内存

位运算

  • 位运算虽说是按照补码来走,正数用原码算也对,但是负数会错。比如~-21会变成20.
    • -21原码:10010101
    • -21补码:11101011
    • ~-21原码/补码:00010100=20原码
  • 还有>>右移位运算,-5右移一位为-3而不是-2

scanf

  • scanf读取带空格的字符串
    • scanf("%[^\n]",str);
    • 其和%s都会默认跟’\0’,不需要自己加
  • scanf读取不知多少行的输入
    • while(scanf()!=EOF)
  • scanf连续读入有换行符的字符都需要getchar(),但是字符串不需要
  • 一位一位加入字符数组还要加’\0’
  • 直接类型转换就会实现ascⅡ码转换

结构体

  • 如果结构体定义不写类型别名,那么声明时要加上struct
  • 类型别名的写法
    • 1.结构体定义的前加typedef,后加类型别名
    • 2.单独写typedef struct 类型原名 类型别名
    • 可以通过第二种写法给一般变量写别名
  • 链表一般靠结构体实现
    • 节点结构体,内含本结构体指针C语言复习笔记

    • 定义结点指针,malloc后不需要定义节点,能够直接用指针->节点内变量

      • 链表没有定义结构体的过程,malloc使得指针有了值即地址,反向的构建了结构体变量。因为没有正向定义结构体,所以变量无名。
    • 创建链表函数(无头指针和头节点,从首节点开始)C语言复习笔记

多模块程序

  • 单程序
    • 编译生成可执行文件:gcc -o program main.c
    • 运行:./program
  • 多程序
    • 编译生成目标代码文件:gcc -c -o set.o set.c
    • 多模块链接:gcc -o program main.o set.o others.o
    • 运行:./program
  • 头文件
    • 将多文件共同使用的全局变量、类型定义、函数声明写到头文件中
    • 一般重复声明问题
      • #ifndef xxx 和#endif,若xxx未定义则有效
      • 注意xxx的定义只是一个条件,其内部定义未必是xxx
    • 嵌套头文件重复引用导致的重复声明问题
      • 头文件开始判断宏是否被定义过,若则跳过整个头文件
      • 用#ifndef xxx 和#endif包裹整个头文件内容
  • makefile
    • make命令可以读取makefile文件,并根据makefile中的规则描述把源文件生成为可执行文件,这些命令不通过make也可以实现
    • make命令在命令行输入
    • 格式:
      • 目标:依赖1 依赖2…
      • \t命令
    • 举例
      • array.o: array.c array.h
      • \t gcc -c -o array.o array.c
      • 表示生成的文件是目标代码文件array.o,它依赖于array.c和array.h。
      • 当我们在命令行中执行makearray.o时,根据这一规则,如果array.o不存在或者array.c与array.h至少之一比array.o更新,就会执行gcc -c -o array.o array.c。
      • 我们把上述代码保存为Makefile,与array.c和array.h放在同一目录,在那个目录里执行make array.o就能看到效果。
      • 注意:Makefile里的除当前目录隐藏文件外的第一个目标会成为运行make不指定目标时的默认目标。
    • 如果有多条规则只希望生成其中一个
      • make+生成文件(即目标)
    • 删除命令
      • clean:
      • \t rm -f array.o main.o main
      • 但是如果有一个文件叫clean则无法执行
        • .PHONY: clean
        • clean:
        • \t rm -f array.o main.o main
        • .PHONY用于声明一些伪目标,伪目标与普通的目标的主要区别是伪目标不会被检查是否存在于文件系统中而默认不存在且不会应用默认规则生成它。
    • 注释:#
    • 变量:替代书写
      • 定义:INOBJS = main.o array.o
      • 使用:$(INOBJS)
  • 命令行参数
    • main的参数int main(int argc, char **argv)
    • 第一个参数整形,传入参数个数(不算自己)
    • 第二个参数储存传入参数
    • 参数间空格分割,若空格作为参数需要用引号
    • 参数当作字符串在代码使用
    • ./main hello world
      • argc=3
      • argv[0]=./main
      • argv[1]=hello
      • argv[2]=world

文件操作

  • FILE *fp;
    • 文件指针stdin,stdout,stderr
    • 断开:fclose(fp);如果不写,自动执行
    • 也可以断开三个文件指针
  • 文件关联:fp=fopen(文件路径,访问模式)
    • “r”,“w”,“a”
  • 读文件
    • fgetc(fp);获取当前指针之后位置的一个字符,获取后自动后移,到达文件末返回EOF
    • fgetc(stdin);获得来自标准输入的字符
    • fscanf(fp,"%c",&a);
    • fscanf(stdin,"%c",&a);等价于scanf("%c",&a);
  • 写文件 fputc(‘c’,fp);将字符‘c’写入文件
    • fputc(ch, stdout); 将变量 ch 中的字符输出到标准输出
    • fputc(ch, stderr); 将变量 ch中的字符输出到标准错误
    • fprintf(fp,"%c",a);
    • fprintf(stdout,"%c",a);等价于printf("%c",a);
  • 将一个文件复制到另一个文件的函数C语言复习笔记