C语言学习笔记(浙大翁恺老师)

说明:本文为浙江大学翁恺老师C语言课程的学习笔记,仅供自身参考学习,如有纰漏,请多指教,如有帮助,不胜荣幸。


一~六  初步

格式

#include<studio.h>

 

int main()

{

  printf(“hello world!\n”);

 

  return

}

变量定义

变量定义的一般形式:(类型名称)(变量名称)=(赋值)

int price=0(初始值) int price=0,int amount=1;

变量名第一个字符不能是数字

所有的变量第一次出现先赋值 

 

 

读整数,赋给price变量

scanf(“%d”,&price);

定义常量 const int AMOUNT=100

 

两个整数的运算结果只能是整数

浮点数和整数运算时,结果是浮点数,按浮点算

10和10.0不同

int变成double(浮点),此时输入用“%lf”,

数据类型

整数 int printf(“%d”,…)

scanf(“%d”,…)

浮点数 double printf(“%f”,…)输出 scanf(“%lf”,…)

表达式 运算符与算子

赋值是一种运算,优先级低

 

1.复合赋值(+-*\%与=复合)

total+=(sun+100)/2

total=total+(sum+100)/2

2.递增递减运算符“++”“--”算子必须是变量,作用是给算子加一或减一

count++

count+=1

count=count+1

前置和后置不一样int a=10

a++=10 a=11 a++这个表达式是运算前的值

++a=10 a=12 ++a是运算后的值

count++ 给count+1 表达式的值是count

++count 给count加一 表达式的值是count+1

 

ps:“!=”是不等于

判断

if(条件成立){

}; (大括号内的语句缩进一个tab距离)

关系运算符

相等==

不相等 !=

大于> 大于等于>=

关系成立,结果为1,不成立,结果为0,

所有关系运算的优先级低于算数运算,但高于赋值

 

以两个斜杠//开头的语句把程序分成几部分,这个叫做注释

延续数行的注释,以“/*”开始,以“*/”结束

else 否则的话,在if的};后面跟上else{

      }

if语句也可以没有大括号,直接跟在后面,没有分号就不算结束。如:

if()

        ……;(没有分号,次行缩进)

但是当if嵌套时,不用大括号有分不清else匹配的风险,(一般是就近原则,但有时内层if无else)。不要冒险!

嵌套 if() {…if…}else

级联if else if相当于串联

多路分支:switch case(相当于多个选择,多个if)

switch(type){

case 1:

    printf(“你好”);

     break;

case 2:…

……

}

括号里叫控制表达式,只能是整数型

 

case后叫常量,可以是常数,也可以是常数计算的表达式

case 1就是括号中变量type=1,break代表switch结束(出口)

 

循环(每次会回到while,直到条件不成立)

while(判断){

……;

循环体{大括号里}一定要有条件不成立的可能

ps:验证代码:个位数,10,0,复数,边界数据,特殊的倍数,有效范围两端的数据

ps:调试:在适当位置插入printf输出该处变量内容

 

do-while循环(先执行,再检查条件是否满足,满足则继续下一轮,不满足则结束)

do

{

    <循环语句>

}while(<循环条件>);(一定要有分号)

rand()召唤一个随机整数

 

for循环(设定一个计数器并初始化,在计数器到达某值前,重复执行循环体,在这个过程中,计数器调整)

for(i=0;i<5;i=i+1){

    printf(“%d”,i);

翻译:对一开始的i=0,当i小于5时,重复做循环体,每一轮循环完后,令i加一

循环的次数是n,结束后i为n(5),

tip:求和,初始值0;求积,初始值一

tip:for中每一个表达式都是可以省略的,

for(;条件;)==while(条件)

for==while

for(int i=1;i<=n;i++){

    fact *=i;

 

int i=1;

while(i<=n){

    fact*=i;

    i++;

 

TIPS FOR LOOPS

如果有固定次数,用for

如果必须执行一次,用do-while

其他情况用while

 

循环控制:素数的判断

1.

#include<studio.h>

 

int main()

{

     scanf(“%d”,&x);

 

    int i;

    for(i=2;i<x;i++){

        if(x%i==0){

            printf(“不是素数\n”);

        }

    }

     return0;

一个数输出好多次,

2.引入一个判断变量

    int i;

    int isprime=1;

    for(i=2;i<x;i++){

        if(x%i==0){

            isprime=0;

        }

    }

    if(isprime==1){

        printf(“是素数\n”);

    }else{

            printf(“不是素数\n”);

    }

    但是每一个都需要跑完全程,这很浪费

    3.引入出口(break)

if(x%i==0){

            isprime=0;

            break;

        }

保证可以整除时结束

ps:break vs continue

break:跳出循环,continue:跳过这一轮剩下的语句,直接进入下一轮循环

break和continue只能对它所在的那一层循环做

 

循环嵌套(如何输出100以内的素数)

在判断素数前后加循环(循环里还是循环)

int x;

for(x=1;x<=100;x++){

    判断

    ……

    if(isprime==1){

        printf(“%d”,x);

    }

注意:1.每一层的循环变量(计数器)应不一样

    2.控制变量是x,条件也可以用其他变量表示(限制)

ps:想换行?

if(cnt%5==0){

    printf(“\n”);// cnt是计数的

           对不齐?printf(“%d\t”,x)改变输出的

\n的意思其实是回车换行!!!

\t相当于tab(相当于八个空格)

多重嵌套循环,如何找到一个就结束?

    1.每层加break,但外层要设置条件,在前面做一个判断变量,否则(外面不设条件)第一次直接结束,不管找到没有。

    2.goto语句(传送锚点)

    goto out;然后在最后一个大括号后放上out;

ps:最好不用goto

 

tips:

    1.如何表示正负交错?

定义一个sign=1,每次令sign=-sign,每次乘上sign即可

    2.注释多行Ctrl+/,先调试一半

 

 

数据类型

c语言的变量必须:在使用前定义,且确定类型。

整数:char、short、int、long、long long(c99)

浮点数:float、double、long double(c99)

逻辑 bool(c99)

指针

自定义类型

 

 类型名称:int、long、double

输入输出:%d、%ld、%lf(输出时为%f)

所表示数的范围:char<short<int<float<double

 

sizeof 一个运算符,给出某个类型或变量在内存中占据的字节数。sizeif(int) sizeof(i)

 

整数类型:

char:1字节,8比特 short:2字节 int:一个字(取决于编译器) long:一个字 longlong:8字节

一个常量后面加u,就是unsigned,即该数没有负数,纯二进制

一个以0开始的数字字面量是8进制

一个以0x开始的数字字面量是16进制

%o用于八进制,%x用于十六进制

ps:虽然整数有很多,没什么特殊需要,就用int

 

浮点类型

float:字长32,有效数字7;scanf %f printf %f,%e

double:字长64,有效数字15;scanf%lf printf %f,%e

可以表示0,但在0的一个极小邻域内无法表示

科学计数法的输出 printf(“%e\n,ff”) 如-5.67e+16

输出精度

在%和f中间加上.n可以指定小数点后几位,它是四舍五入的

浮点数超过范围

printf输出inf表示超过范围的浮点数

printf输出nan表示不存在的浮点数

带小数点的字面量是double而非float

float需要用f后缀表明身份

选择浮点类型:没有特殊需要,用double

 

字符类型

char是一种整数,也是一种字符

用单引号表示字符‘a’,‘1’

printf和scanf里用%c输出字符

字符运算:一个字符加一个数字得到ASCII码表中那个数之后的字符

两个字符的减,得到他们在表中的距离

大小写转换:

ASCII表中,大小写分开排列,顺序排列。

a-A可以得到两段间距离,

a+‘a’-‘A’大写转小写,

a+‘A’-‘a’小写转大写

 

逃逸字符

\b 回退一格

覆盖,但之后输出为空则不覆盖,如123\b——123

123\bA——12A

\t 到下一个表格位

制表位 每行的固定位置,\t使上下两行对齐

\n 换行 \r 回车

 

类型转换

自动类型转换

运算符的两边出现不一样的类型,自动转换成较大的类型(表示范围更大)

char--short--int--long--longlong(向右转)

int--float--double

对printf,任何小于int的类型都转换成int,float转换成double

scanf不会,要输入short,需要%hd

强制类型转换:(类型)值。如(int)10.2

注:有时小的变量不能表示大的变量

强制类型转换优先级高于四则运算,应该是:

int i=(int)(a/b);

而不是:int i=(int)a/b;

 

逻辑类型 bool

需要加上#include<std bool.h>,之后可以用bool和true false,输出仍是整数

 

逻辑运算

! 逻辑非

&& 逻辑与

|| 逻辑或

判断c是否是大写字母:

c>=‘A’&&c<=‘Z’

优先级 !>&&>||

 

38badda2dd32419e9104a66fb27afec4.jpg

     9.赋值

短路:

对于&&,左边是false就不做右边了

对||,左边是true就不做右边了

所以不要把赋值,包括复合赋值组合进表达式

 

条件运算符

count=(count>20)?count-10:count+10;

条件、条件满足时的值和不满足时的值

优先级高于赋值,低于其他所有

 

逗号运算

逗号连接两个表达式,以右边的值作为结果,优先级最低

在for中使用

for(i=0,j=10;i<j;i++,j--)


七  函数

是一块代码,接收零个或多个参数,做一件事情,返回零个或一个值

 

函数定义

void sum(int begin,int end) 头部,sum叫函数名,void叫返回类型,圆括号里是参数表

{

    int i;

    int sum=0;

    for( i=begin;i<=end;i++){

        sum+=i;

    }

     printf("%d到%d的和是%d\n",begin,end,sum);

}

大括号里叫函数体

 

调用函数:函数名(参数值)

()起到了表示函数调用的作用,没有参数也要有()

 

从函数中返回值: return

return停止函数的执行,并送回 一个值(交给调用这个函数的地方,作为这个函数运行的结果)

return; return表达式;

没有返回值的函数

void 函数名(参数表) 不能使用带值的return,可以没有return

此时不能使用返回值的赋值,输出什么就是什么

 

函数先后关系

自上而下(先写出函数,再用函数)

函数原型

可以把函数第一行(函数头)粘贴到调用的函数前面,以分号结尾,就是函数的原型

作为声明;告诉编译器这个函数什么样,检查是否与定义一致

 

调用函数

如果函数有参数,调用函数时必须传递给它数量、类型正确的值

什么可以传递给函数的值?是表达式的结果,如:字面量、变量、返回值、计算结果

ps:调用函数时类型不匹配,会自动转换

c语言在调用函数时,只能传值给函数,调用参数和定义参数没有关系。详细的解释一下:函数里变量的运算只是读入了调用时相应参数的值,对这个值运算,而与调用参数无关,所以永远无法做到对参数的运算

每个函数有自己的变量空间,参数也只能在这个空间中有效,与其他函数没有关系

 

本地变量

函数的每次运行都产生独立的变量空间,这里的变量叫本地变量

定义在函数内部的变量是本地变量,参数是本地变量

运行到哪里,就在哪一个变量空间中

本地变量定义在块(大括号)内,可以是函数的块内,也可以是语句的块内,运行在块内就存在,运行至块外时消亡

块外面定义的变量在里边仍然有效,但里面定义了同名的变量就掩盖了外面的

本地变量不会被默认初始化,但是参数会

 

tips:

1.没有参数时,用void f(void),而不是void f()

2.调用函数时逗号和逗号运算符:f(a,b)是逗号;f((a,b))是逗号运算符

3.c语言不允许函数的嵌套定义(在函数里定义函数)(可以放函数的声明,不能放定义)

4.int main()也是一个函数,是返回int类型的main函数,有返回值,程序总是从main函数开始,最后到main函数结束(结束时有return语句)


八  数组

int number[100];

定义一个变量number,number是一个数组,大小是100(可以有100个int类型的变量)

number[cnt]=x 每一个x放在数组number中cnt的位置上(赋值) cnt是count缩写

 

定义数组

<类型>变量名称[元素数量];

double weight[20];

 

放在[]中的数字叫做下标或索引,有效范围从0到数组大小减一

记录0-10数字出现的次数

0a004a09599648f6a41cd0f5d232778f.jpg

 初始化:初始化数组中每一个变量,所以循环

-1是出口,最后输入-1直接结束

 

数组的集成初始化

直接用大括号给出数组中所有元素的初始值,不用给数组的大小

int a[]={2,4,6,7}

数组的大小:用sizeof表示出整个数组的字节大小

sizeof(a) sizeof(a[0])相除

 

数组的赋值

数组变量本身不能赋值(int b[]=a;是错误的)

要把数组的所有元素交给另一个数组,必须采用遍历

for(i=0;i<length;i++){

    b[i]=a[i];

}

tips:让i从零到<数组的长度,这样最大的i正好是数组最大的有效下标

常见错误:1.循环结束条件是<=数组长度

    2.离开循环后,继续用i的值做元素的下标(此时i的值已经是无效的下标范围)

 

数组作为函数参数时,必须用另一个参数传入数组的大小 : 在外面用单独变量i,调用函数时空着

(int key,int a[],int length) a[i]==key   

数组作为函数的参数时

不能在[]中给出数组的大小,不能用sizeof计算数组的元素个数

 

数组例子:素数

算法优化:

    1.去掉偶数后,从3到x-1,每次加二

    2.不用到x-1,到sqrt(x)

    3.判断是否能被已知且小于x的素数整除

13ddf49f117e439780bb0e26bfb7b64a.jpg

 int prime[number]={2}是用另一个数组的赋值,代表第0个元素为2,后面没有写就是0

prime[count++]=i 将i的值赋给数组中cnt的位置,cnt移到下一位置(自加一)

跟踪检测运行状态:1.调试2.在中间写入printf语句,可以用大括号,如

4a98c4829ce642d38297e55299963252.jpg

 为了更好看一点,再用一个大括号,输出表头

2b92ae28f2914d27bb6ce5e3a0acf475.jpg

 构造n以内素数表

令x=2;

将2x、3x、4x直至ax<n标记为非素数

令x为下一个没有标记的数,重复二

 

    1.开辟prime[n],初始化所有元素为1,prime[x]为1表示x是素数

    2.令x=2

    3.若x是素数,则对(i=2;x*i<n;i++)令prime[i*x]=0

    4.令x++,若x<n,重复3

90fb59c63148436d96a94d5bb253b9ec.jpg

 二维数组

int a[3][5];a是一个三行五列的矩阵

二维数组的遍历

08146f3428d94718809a77726a8a8c76.jpg

 a[i][j]是一个int,表示第i行第j列的单元

初始化

int a[][5]={

{0,1,2,3,4},

{2,3,4,5,6},

};

列数必须给出,每行一个{},逗号分隔,


九  取地址运算

运算符&:获得变量的地址,它的操作数必须是变量 scanf(“%d,&i”);

地址的大小是否与int相同取决于编译器

输出地址? int i;printf(“%p”,&i);

 

指针:指针变量就是记录地址的变量

scanf(“%d”,&i);

将取得的变量的地址传递给一个函数,通过这个地址在那个函数内访问这个变量

我们需要一个参数能保存别的变量的地址!

指针!就是保存地址的变量

int* p= &i;*p是一个指针,带*是标识,p是新变量,类型是int,它指向i这个变量,将i的地址交给指针(p保存i的地址)

作为参数的指针

void f(int *p);调用时给它变量的地址f(&i)

在函数里面可以通过这个指针访问外面的i

 

访问那个地址上的变量*

*用来访问指针的值所对应地址上的变量,可以做左值或右值(int k=*p *p=k+1)

如:在函数内部时,*p=26,实际是对i作用,这时候*p就代表函数外的i

ps:左值之所以叫左值,是因为赋值号左边的不是变量,而是值,是表达式计算的结果。*p=3

&与*就像逆运算

 

指针的使用

    1.交换两个变量的值

void swap(int *pa,int*pb)

{

    int t=*pa;

    *pa=*pb;

    *pb=t;

}

    2.函数返回多个值,某些值就只能通过指针返回

或:函数返回状态(对错,结果通过指针返回

常用的套路是让函数返回特殊的不属于有效范围内的值来表示出错

tip:指针一定要指向变量!!

 

数组与指针

函数参数表中的数组实际是指针, a[]中[]是地址,也是数组的运算符

以下四种函数原型等价

int sum(int *ar,int n);

int sum(int*,int);

int sum(int ar[],int n);

int sum(int[],int)

数组变量是特殊的指针,它本身表示地址

    1.int a[10];int*p=a;(无需用&取地址)

    2.数组的单元表示的是变量,需要用&取地址

    3.a==&a[0]a的地址等于a[0]的

[]运算符可以对数组做,也可以对指针做,如:int *p=&min;

printf(“*p=%d\n”,*p);

printf(“p[0]=%d\n,p[0]”);将p看作数组,p[0]就是数组中第一个数,就是min本身

*可以对指针做,也能对数组做,*a=25 (第一个元素)

数组变量是const的指针,所以不能赋值,int a[]即int* const a,

const做变量的修饰即该变量不能被改变,对a就是取得地址不能被改变

 

转换:总能把一个非const值转换为const的,void f(const int* x)传入一个指针

const数组

const int a[]={1,2,3,4,5,};

这里表示数组的每个单元都是const int,所以必须通过初始化赋值

保护数组

    1.因为数组传入函数时是地址,所以函数内部可以修改数组的值

    2.为了保护数组,可以设置参数为const,int sum(const int a[],int length);

 

指针运算

给一个指针加一,并不是地址加一,而是加一个sizeof(对应类型的一个单位,即移到下一个位置)

这些运算符可以对指针做

    1.给指针加减一个整数(+、+=、-、-=)

    2.递增递减(++\--)

    3.两个指针相减:得到的是两个指针地址间的长度除以sizeof,即两个地址间有多少个单位

 

p++:取出p所指的那个数据,随即把p移到下一个位置(常用于数组类的连续空间操作)

*的优先级没有++高

指针比较

<,<=,==,>=,!=都可以对指针做,比较它们在内存中的地址

ps:数组中单元的地址线性递增

0地址:不能随便碰,Null表示0地址

不论什么类型,指针的大小都一样,因为都是地址。

但指向不同类型的指针不能直接互相赋值,这是为了避免用错指针

但也不是不可以,指针类型转换:int* p=&i;void*q=(void*)p;(并没有改变p所指的变量类型,而是从q的角度看i,q也指向i,通过p看i,i是int,通过q看i,i是void*)

void*表示不知道指向什么的指针,计算时与char*相同

 

动态内存分配 int a[number]

a=(int*)malloc(number*sizeof(int));前面是类型转换,

最后还要还: free(a);(大括号外,return 0前)只能还申请空间的首地址

malloc

#include<Stdlib.h>

void* malloc(size_t size);(参数是size_t,返回类型是void*,需要类型转换为需要的类型)

向malloc申请的空间是以字节为单位的(乘sizeof)

没空间了?申请失败就返回0,或Null


十、字符串

char word[]={'h','e','l','l','\0'};

 

字符串:以0结尾的一串字符

    1. 0和'\0'一样,但与'0'不一样

    2.0标志字符串结束,但0不是字符串的一部分,计算字符串长度时不包含0

    3.字符串以数组的形式存在,以数组或指针的形式访问,不能用运算符运算,可以遍历

字符串常量 char* s=“Hello,world”;

s指针指向字符串常量,这个常量只能读不能写

要修改字符串,用数组:chars s[]=“Hello,world”;(重新定义)

写成指针形式还是数组形式?

数组:这个字符串在这,作为本地变量自动回收

指针:不知道在哪,处理参数,动态分配空间

 

字符串变量

char *str=“Hello”;(str指针指向一个数组,数组里内容是Hello)

char word[]=“Hello”;

 

字符串赋值

char* t=“title”;

char* s;

s=t;

并没有产生新的字符串,只是让指针s指向了t所指的字符串,

 

字符串输入输出

定义:char string[8];string初始化为0

scanf(“%s”,string);

printf(“%s”,string);

scanf读入一个“单词”(到空格,回车,tab为止)

不安全,因为可能越界(超过字符串大小)

安全:在%和s之间的数字表示最多允许读入的字符数,这个数字应该比数组的大小小一,

%7s 最多读七个字符,下面的内容交给下一个scanf或其他什么读入的语句去读

空字符串:char buffer[100]="";

buffer[0]=='\0'

若char buffer[]=“”;

这个数组长度一

 

字符串数组

char**a a是一个指针,指向另一个指针,那个指针指向一个字符(串)

char a[][10] a[0]即char[10](10是后面括号里的)a[1] a[2]都是,数组中每一个元素都是一个char[10]

char *a[] a[0] a[1]…是指针,指向外面某处的…

 

putchar函数

int putchar(int c);向标准输出一个字符(字节(不是四个)

输入是int类型,返回类型也是int,表示写出去几个字符,EOF(值是-1)表示写失败

getchar函数

int getchar(void);从标准输入读入一个字符

 

字符串函数

前面需要加 #include<string.h>

strlen说明字符串的长度

size_t strlen(const char *s);返回s的字符串长度,不包括结尾的0

 

strcmp

int strcmp(const char *s1,const char *2);

比较两个字符串,返回:0(s1==s2)、1(s1>s2)、-1(s1<s2)

 

strcpy

char *strcpy(char *restrict dst,const char *restrict src);

把src的字符串拷贝到dst,返回dst

复制一个字符串

char *dst=(char*)malloc(strlen(src)+1);

scrcpy(dst,src);

 

strcat

char *strcat(char *restrict s1,const char *restrict s2);

把s2拷贝到s1的后面,从/0(dst[strlen(dst)])开始

 

strcpy和strcat都可能没有足够的空间,安全版本

char *strncpy(char *restrict dst,const char *restrict src,size_t n);

char *strncat(char *s1,const char *restrict s2,size_t n);

还有一个

int strncmp(const char *s1,const char *s2,size_t n);只判断一个字符串开头3个字母是不是abc,不比较后面的,size写上3

 

字符串搜索函数 strchr

char *strchr(const char *s,int c);从左寻找c第一次出现的位置(返回的是指针)

strchr换成strrchr就是从右边数

返回NULL表示没有找到

1.

char s[]=“hello”;

char *p=strchr(s,'l');

//此时输出p,为llo,即找到第一个l,从此开始当成一个数组

//第二个呢

p=strchr(p+1,'l');

//此时结果lo

2.想输出he?

char s[]=“hello”;

char *p=strchr(s,'l');

char c=*p;

*p = '\0';

//令第一个l为0,copy一份s就是'he',再通过定义的c还原回去(*p=c)

char *t=(char*)malloc(strlen(s)+1);

strcpy(t,s);

字符串中找字符串

char *strstr(const char *s1,const char *s2);

把strstr换成strcasestr表示忽略大小写


十一、枚举

常量符号化

枚举语句:enum枚举类型名字{名字0,…,名字n};

大括号里的名字就是常量符号,类型是int,值依次从0到n,如:enum colors{red,yellow,green};创建了三个常量,red的值是0,yellow的值是1,green是2

当需要一些可以排列起来的常量值时,定义枚举的意义是给这些常量值名字

作为变量或函数调用时enum color作为一个整体

enum color{red}

小套路:自动计数的枚举

enum color{red,yellow,green,numcolors};这样numcolors就是个数

枚举量:声明枚举量的时候可以指定值

enum color{red=1,yellow,green=5};yellow跟在后面,就是2

 

结构类型

struct point {

    int x;

    int y;

};p1,p2;

或者不要大括号后的p1p2,在后面加上语句

struct point p1,p2;

结构的初始化

struct date today={07,31,2014};

数组用[]运算符和下标访问成员 a[0]=10;结构用.运算符和名字访问成员 today.day

结构运算

要访问结构,直接用结构变量的名字

对整个结构,可以赋值,取地址,传递给函数参数

p1=(struct point){5,10}; 强制令5,10转换为struct类型,pl.x=5;pl.y=10;

p1=p2;即pl.x=p2.x;pl.y=p2.y

结构指针

和数组不同,结构变量的名字不是结构变量的地址,必须使用&

 

结构作为函数参数

int numberodays(struct date d)

整个结构作为参数的值传入函数,此时是在函数内新建一个结构变量,复制调用者结构的值

输入结构

在输入函数中,创建一个临时结构变量,把这个结构返回

指向结构的指针

p->month = 12;

结构数组

struct date dates[100];

struct date dates[]={{4,5,2005},{2,4,2005}};

结构中的结构(结构中的变量可以是结构)

struct dateAndTime{

struct date sdate;

struct time stime;

};

r.pt1.x rp->pt1.x


十二、全局变量

定义在函数外的变量
全局变量没有初始化会得到0值
静态本地变量
在本地变量前加上static修饰符,实际上是特殊的全局变量
特性:函数离开后,静态本地变量继续存在保持其值,以后进入函数保持上次离开的值
返回指针的函数
返回本地变量地址危险,全局变量地址安全,最好返回传入的指针
tips:尽量避免使用全局变量,不要用全局变量在函数间传递参数和结果

编译预处理指令:以#开头的指令
#define定义一个宏
#define<名字><值> 没有分号
名字必须是一个单词,值可以是各种东西
在c语言的编译器编译前,预处理程序将程序中的名字换成值

    1.一个宏的值中有其他宏的名字,会被替换
    2.一个宏的值超过一行,最后一行末加\
    3.空格或其他符号都会被当做值,但//注释不会
像函数的宏(带参数)
#define cube(x)((x)*(x)*(x))
原则:一切都要有括号(整个值,每一个参数)
可以带多个参数 #define min(a,b)((a)>(b)?(b):(a))
可以嵌套宏

在devc++中新建一个项目,会把项目中所有文件编译后链接起来

头文件:把函数原型放到一个头文件(以.h结尾)中,在需要调用该函数的源代码文件(.c结尾)中#include这个头文件

#include是编译预处理指令,把相应文件的全部文本内容插入
#include有两种形式指出要插入的文件,“”要求编译器在.c文件所在的目录寻找,没有就在编译器指定目录找。<>只在指定目录找

int i;是变量的定义
extern int i;是变量的声明
只有声明可以放在头文件中,定义不能。
同一个编译单元,同名结构不能重复声明

为了避免重复,引入标准头文件结构:
#ifndef _LIST_HEAD_
#define_LIST_HEAD_
最终结构:
#include "node.h"
代码内容……
#endif


十三  格式化输入输出

printf

%[flags][width][.prec][hlL]type

    1.flag:"-"(左对齐),"+"(前面加加号或减号),"(space)"(正数留空),“0”(0填充)

    2.width或prec:“number”(输出要占据的位数)如9,*:下一个参数是字符数,.number:小数点后的位数,.*下一个参数是小数点后的位数

    3.修饰符

hh:单个字节,h:short,l:long,ll:long long,L:long double

    4.类型type

d1f1df9ef02246f18d79009386ba845a.jpg

 scanf%[flag]type

36d99421dceb4682950ce372b4210839.jpg

c73c156e2e0b49a5b3bc338656fc10d8.jpg 

 [^.]读在符号前的所有字符,如[^,]读逗号前的字符

scanf("%*[^,],%[^,]")

 

文件输入输出

打开文件的标准代码

FILE* fp=fopen("file","r"); fopen是函数,r表示读,对file进行打开读操作

if(fp){

    fscanf(fp,…);

    fclose(fp);

}else{…

}

if的作用是判断文件是否打开

ace5d94decbd4f7c9acfef3e7a02b097.jpg

c8c42e1131924d0cab003d34d0e2e95b.jpg 

ce824e27a71349819871c72d934efedc.jpg 

7f9ff4c560f54ee4916fa68e7110b3fd.jpg 

 


十四  可变数组

 

Array array_create(int int_size);创建数组

void array_free(Array *a);释放空间

int array_size(const Array *a);大小

int* array_at(Array *a,int index);访问某个单元

void array_inflate(Array *a,int more_size);长大

 

typedef struct{

    int*array;

    int size;

}Array;

40505d0f2e164f1ca144546c6c5bfeb5.jpg

 ->意思是所指的

自动增长

3c69d094e2a141789a781152494d6827.jpg

 每次申请一块(block)

25e788a9c5b04829abd5f7da06a8407d.jpg

 每次都重新申请有许多弊端,所以要有链表,直接连接起来

22eada2006674396bf59feabc6735e50.jpg

 链表的函数

链表的搜索:遍历并输出。用if函数找

链表的删除:前一个指向后一个,中间的free了

如果第一个就是呢?if判断一下,head指向后一个

链表的清除(整个)

for (p=head;p;p=q){

q=p—>next;

free (p);

}

 

后:学习还未结束,to be continue…

 

 

 

 

 

 

 

 

 

  • 11
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
浙江大学翁恺C语言课件是浙江大学计算机学院教授翁恺编写的一套C语言课程教材。这套课件主要用于C语言的教学与学习,内容包括基本语法、数据类型、运算符、流程控制、函数、指针、数组、字符串等C语言的基础知识。 这套课件具有以下几个特点。首先,它简单易懂,适合初学者学习翁恺老师针对C语言的特点和学习难点,将知识点进行了简洁明了的讲解,同时结合了大量的示例和练习,帮助学生更好地理解和掌握C语言的编程思路和技巧。 其次,课件内容丰富全面。翁恺老师在编写课件时,充分考虑到C语言的广泛应用领域和学生的学习需求,涵盖了C语言的各个方面,包括基础语法、程序设计、算法、数据结构等内容,帮助学生建立正确的编程思维和解决实际问题的能力。 再次,课件设计灵活多样。为了培养学生的动手实践能力,课件中设计了丰富的编程实例和实践项目,学生可以边学边练,不断巩固和提高自己的编程能力。此外,课件中还包含了一些扩展知识,如文件操作、动态内存管理等,有助于学生进一步拓宽视野。 总之,浙江大学翁恺C语言课件是一套权威且实用的C语言学习资料,通过学习这套课件,学生可以系统地学习和掌握C语言的基础知识,提高编程能力,并为日后的学习和工作打下坚实的基础。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值