0%

C语言基础

前言

大一学习的 C 语言,现在回过头来发现已经忘的差不多了,正好趁着这个机会复习整理下,本文的目的偏向于整理备忘,讲解的部分会占很少。

目录及相关习题参考 《C程序设计(第四版)》谭浩强

1 算法表示

1.1 常见流程图

当型循环

直到型循环

1.2 NS 流程图

伪代码表示

2 数据类型

2.1 整型数据

1
2
3
4
5
6
7
8
9
10
11
1)普通整型(int),存储单元中使用反码形式存放
2字节 -32768~327674字节 -2147483648~2147483647

2)短整型(short int 或 short),同反码存储
vc6.0 int 4 字节,short int 2 字节

3)长整型(long int 或 long)
vc6.0 long 4 字节

4)双长整型(long long int
一般 8 字节

有符号数据 0 正 1 负,默认为有符号数据

2.2 字符型数据

一字节

1
char c = '?';

==注意==

1
2
'A' 表示一个字符
"A" 表示一个字符串,后面还有一个 \0

2.3 浮点型数据

1
单精度浮点型(float),双精度浮点型(double),长双精度(long double

2.4 赋值过程中类型转换

因为 C 是强类型语言,如赋值语句两侧变量类型不相同则会进行转换

==注意==

1
2
3
printf("%f\n", 1/3);    //输出 0.000000,因为 1/3 结果为整型 0

printf("%f\n", 1.0/3); //正确方法,输出 0.333333

2.5 强制类型转换

1
2
3
(double)a
(int)(x+y)
int(x)+y //只将 x 转为整型

3 C 语言注释

两种注释方式

  • 块注释(block comment):以 /* 开始,*/ 结束
  • 行注释(line comment):以 // 开始

4 数据的输入输出

4.1 printf 输出数据

4.1.1 一般格式

语法:printf(格式字符, 输出变量);

example: printf("%d,%c\n",i,c); // 注意是双引号

4.1.2 格式字符

修饰字符

1
2
3
4
%m.nf   指定数据的宽度和小数位数,m 包含小数点

printf("%6.3f\n", 1.0/3); //输出 0.333
printf("%06.3f\n", 1.0/3); //输出00.333 宽度不够 0 凑位

4.2 scanf 输入数据

4.2.1 一般形式

语法:scanf(格式字符, 地址表列);

example: scanf("a=%f,b=%f,c=%f", &a, &b, &c); //1. 双引号 2. 注意是地址 &a

4.2.2 格式字符

==注意==

1
2
3
4
5
6
7
1
double 类型数据
scanf 时格式字符使用 %lf
printf 时格式字符使用 %f

2
scanf 时,遇空格,回车,tab或遇到非法字符(如输入数字时遇到字符)则认为该数据结束

4.3 字符数据的输入输出

putchar 输出一个字符

1
putchar(c);

getchar 输入一个字符

1
getchar(c);

getchar 还可以获取屏幕上无法显示的字符,如控制字符

4.4 习题(第三章)

1
2
3
4
5
6
7
8
9
10
11
12
13
//math 库 pow 函数应用
#include <stdio.h>
#include <math.h>

int main(){
float r, p;
int n;
r = 0.09;
n = 10;
p = pow((1+r), n);
printf("%f\n", p);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//利息计算
#include <stdio.h>
#include <math.h>

int main(){
double P1, P2, P3, P4, P5;

P1 = 1000*(1+5*0.0585);
P2 = (1000*(1+2*0.0468))*(1+3*0.054);
P3 = (1000*(1+3*0.054))*(1+2*0.0468);
P4 = 1000*pow(1+0.0414, 5);
P5 = 1000*pow(1+0.0072/4, 5*4);

printf("%f\n%f\n%f\n%f\n%f\n", P1, P2, P3, P4, P5);
return 0;
}

==注意==

第二问,char 存储为一字节,按补码形式存储

==注意==

scanf 时,遇空格,回车,tab或遇到非法字符(如输入数字时遇到字符)则认为该数据结束

所以 71.82 和 Aa 之间不应有空格或回车

5 选择结构程序设计

5.1 if 语句实现选择结构

一般有两种形式

(1)

1
2
3
4
5
6
if(a>b){
c = a;
}
else{
c = b;
}

(2)

1
2
3
4
5
6
7
8
9
if(number>500){
cost = 0.15;
}
else if(number>300){
cost = 0.075;
}
else{
cost = 0;
}

==注意==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 无花括号时,if 条件为真,只会执行之后的一条语句
#include <stdio.h>

int main()
{
if (true)
{
printf("11111111111\n"); // 这两条都会打印
printf("11111111111\n");
}

if (false)
printf("11111111111\n"); // 只有这一条不会打印
printf("22222222222\n"); // 以下两条都会打印
printf("22222222222\n");
return 0;
}

5.2 关系运算符及优先次序


优先次序

5.3 逻辑运算符及优先次序


优先次序,!(非)最高

5.4 条件表达式

1
ch=(ch>='A' && ch<='Z')?(ch+32):ch;

5.5 switch 语句

1
2
3
4
5
6
7
8
9
switch(grade){
case 'A': printf("85~100\n");break;
case 'B': printf("70~84\n");break;
case 'C': printf("60~69\n");break;
case 'D': printf("<60\n");break;
default: printf("enter datda error!\n");
}

//注意每次需要用 break 跳出语句,不然后一直往下运行

5.6 习题(第四章)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// (1)判断哪个等级方法(2)60一下输出E
#include <stdio.h>
int main()
{ float score;
char grade;
printf("请输入学生成绩:");
scanf("%f",&score);
while (score>100||score<0)
{printf("\n 输入有误,请重输");
scanf("%f",&score);
}
switch((int)(score/10))
{case 10:
case 9: grade='A';break;
case 8: grade='B';break;
case 7: grade='C';break;
case 6: grade='D';break;
case 5:
case 4:
case 3:
case 2:
case 1:
case 0: grade='E';
}
printf("成绩是 %5.1f,相应的等级是%c\n ",score,grade);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <stdio.h>
#include <math.h>
int main()
{
int num,indiv,ten,hundred,thousand,ten_thousand,place; //分别代表个位,十位,百位,千位,万位和位数
printf("请输入一个整数(0-99999):");
scanf("%d",&num);
if (num>9999)
place=5;
else if (num>999)
place=4;
else if (num>99)
place=3;
else if (num>9)
place=2;
else place=1;
printf("位数:%d\n",place);
printf("每位数字为:");
ten_thousand=num/10000;
thousand=(int)(num-ten_thousand*10000)/1000;
hundred=(int)(num-ten_thousand*10000-thousand*1000)/100;
ten=(int)(num-ten_thousand*10000-thousand*1000-hundred*100)/10;
indiv=(int)(num-ten_thousand*10000-thousand*1000-hundred*100-ten*10);
switch(place)
{case 5:printf("%d,%d,%d,%d,%d",ten_thousand,thousand,hundred,ten,indiv);
printf("\n反序数字为:");
printf("%d%d%d%d%d\n",indiv,ten,hundred,thousand,ten_thousand);
break;
case 4:printf("%d,%d,%d,%d",thousand,hundred,ten,indiv);
printf("\n反序数字为:");
printf("%d%d%d%d\n",indiv,ten,hundred,thousand);
break;
case 3:printf("%d,%d,%d",hundred,ten,indiv);
printf("\n反序数字为:");
printf("%d%d%d\n",indiv,ten,hundred);
break;
case 2:printf("%d,%d",ten,indiv);
printf("\n反序数字为:");
printf("%d%d\n",indiv,ten);
break;
case 1:printf("%d",indiv);
printf("\n反序数字为:");
printf("%d\n",indiv);
break;
}
return 0;
}


顺序排序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.h>
int main()
{int t,a,b,c,d;
printf("请输入四个数:");
scanf("%d,%d,%d,%d",&a,&b,&c,&d);
printf("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);
if (a>b)
{ t=a;a=b;b=t;}
if (a>c)
{ t=a;a=c;c=t;}
if (a>d)
{ t=a;a=d;d=t;}
if (b>c)
{ t=b;b=c;c=t;}
if (b>d)
{ t=b;b=d;d=t;}
if (c>d)
{ t=c;c=d;d=t;}
printf("排序结果如下: \n");
printf("%d %d %d %d \n" ,a,b,c,d);
return 0;
}

6 循环结构程序设计

6.1 while 实现循环

当型循环

1
2
3
4
while(i<=100){
sum=sum+i;
i++;
}

6.2 do……while 实现循环

直到型循环

1
2
3
4
do{
printf("%d", i++);
}
while(i<=100);

6.3 for 实现循环

1
2
3
for(i=1;i<=100;i++){
printf("%d", i);
}

6.4 习题(第五章)

==重点==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 求解最小公倍数和最大公约数
// 求最大公约数: 辗转相除法(欧几里得算法)
// 两数乘积等于最大公约数与最小公倍数的乘积
#include <stdio.h>
int main(){
int m,n,temp,r,p;
printf("请输入两个正整数 m,n:");
scanf("%d%d", &m, &n);
if(m<n){
temp=m;
m=n;
n=temp;
}
p=m*n;
while(n!=0){
r=m%n;
m=n;
n=r;
}
printf("最大公约数是: %d\n", m);
printf("最小公倍数是: %d\n", p/m);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// if((c=getchar())!='\n')
#include <stdio.h>
int main()
{
char c;
int letters=0,space=0,digit=0,other=0;
printf("请输入一行字符:\n");
while((c=getchar())!='\n')
{
if (c>='a' && c<='z' || c>='A' && c<='Z')
letters++;
else if (c==' ')
space++;
else if (c>='0' && c<='9')
digit++;
else
other++;
}
printf("字母数:%d\n空格数:%d\n数字数:%d\n其它字符数:%d\n",letters,space,digit,other);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//注意an的求法
#include <stdio.h>
int main(){
int a,n,i=1,result=0,an=0;
printf("a,n:");
scanf("%d,%d",&a,&n);
while(i<=n){
an=an+a;
printf("%d\n",an);
result=result+an;
a=a*10;
i++;
}
printf("a+aa+aaa+ …=%d\n",result);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
int main()

{double s=0,t=1;
int n;
for (n=1;n<=20;n++)
{
t=t*n;
s=s+t;
}
printf("1!+2!+...+20!=%22.15e\n",s);
return 0;
}

==重点==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//水仙花数
#include <stdio.h>
#include <math.h>
int main(){
int i,ge,shi,bai;
for(i=100;i<1000;i++){
ge=i%10;
shi=(i%100)/10;
bai=i/100;
if(i==(pow(ge,3)+pow(shi,3)+pow(bai,3))){
printf("%d ",i);
}
}
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//100以内的完数
#include <stdio.h>
int main()
{int m,s,i;
for (m=2;m<1000;m++)
{s=0;
for (i=1;i<m;i++)
if ((m%i)==0) s=s+i;
if(s==m)
{printf("%d,its factors are ",m);
for (i=1;i<m;i++)
if (m%i==0) printf("%d ",i);
printf("\n");
}
}
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//斐波那契数列变形
#include <stdio.h>
int main()
{
int i,n=20;
double a=2,b=1,s=0,t;
for (i=1;i<=n;i++)
{
s=s+a/b;
t=a,
a=a+b,
b=t;
}
printf("sum=%16.10f\n",s);
return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//牛顿迭代法求平方根
//初值x0=a/2
//注意do……while循环while的条件
#include <stdio.h>
#include <math.h>
int main()
{
float a,x0,x1;
printf("enter a positive number:");
scanf("%f",&a);
x0=a/2;
x1=(x0+a/x0)/2;
do
{x0=x1;
x1=(x0+a/x0)/2;
}while(fabs(x0-x1)>=1e-5);
printf("The square root of %5.2f is %8.5f\n",a,x1);
return 0;
}

==重点==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//图形输出问题
//分成两部分来看,找每一行空格,*和行号的规律
//注意输出一行后记得输出\n
#include <stdio.h>
int main(){
int i,j,k;
for(k=1;k<=4;k++){
for(i=1;i<=4-k;i++){
printf(" ");
}
for(j=1;j<=2*k-1;j++){
printf("*");
}
printf("\n");
}
for(k=1;k<=3;k++){
for(i=1;i<=k;i++){
printf(" ");
}
for(j=1;j<=2*(3-k)+1;j++){
printf("*");
}
printf("\n");
}
return 0;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//比赛排序问题
//先逻辑图,判断出正确结果
//编程使用假设的方法,三层循环,判断符合条件的情况
#include <stdio.h>
int main(){
char i,j,k;
for(i='X';i<='Z';i++){
for(j='X';j<='Z';j++){
if(i!=j){
for(k='X';k<='Z';k++){
if(k!=i&&k!=j){
if(i!='X'&&k!='X'&&k!='Z'){
printf("A-%c,B-%c,C-%c\n",i,j,k);
}
}
}
}
}
}
return 0;
}

7 数组

7.1 一维数组

7.1.1定义方法

1
int a[10];

==注意==

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1)a[10] 下标从0开始到9

2
int a[3+5]; // 合法

scanf("%d", &n);
int a[n];

int a[n] 是不合法的,即c语言不允许对数组的大小作动态定义

3
void func(int n){
int a[2*n];
}

为函数参数时可以,这种情况称为“可变长数组”

4)为static存储方式时,不能用“可变长数组”
static int a[2*n]; //非法

7.1.2 引用

1
a[0] 或 a[2*3]

7.1.3 初始化

  1. 全部初始化
    1
    int a[10]={0,1,2,3,4,5,6,7,8,9};    //注意大括号,逗号
  2. 只给一部分元素赋值
    1
    int a[10]={0,1,2,3,4};  // 前5个赋初值,后5个赋初值0
  3. 全部赋初值0可写成
    1
    int a[10]={0};
  4. 可以不指定数组长度
    1
    int a[]={0,1,2,3,4};    //数组长度自动为5

    7.2 二维数组

    7.2.1 定义方法

    1
    float a[3][4];  //可以理解成3行4列矩阵,内存中先顺序存储第一行,再存储第二行

    7.2.2 引用

    1
    2
    3
    4
    int a[3][4];    //定义3×4二维数组
    a[3][4]=3; //不存在a[3][4]元素

    注意定义和数组下标范围的区别

    7.2.3 初始化

  5. 分别赋初值
    1
    int a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}}; 大括号中嵌套大括号
  6. 可写在一个大括号内
    1
    int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
  7. 7.3 字符数组

    1
    char c[10]="China";

    7.3.1 字符串处理函数

    #include <string.h>
  8. puts
    1
    2
    char str[]="China\nBeijing"
    puts(str);
  9. gets
    1
    gets(str);
  10. strcat - 连接字符串
    1
    2
    3
    4
    5
    strcat(str1, str2);

    注意:
    1)str1必须足够大,以便容纳连接后的新字符串
    2)连接前两字符串后面都有\0
  11. strcpy 和 strncpy - 字符串复制
    1
    2
    3
    strcpy(str1,str2);  //  将str2复制到str1

    strcpy(str1,str2,n); //将str2最前面n个字符复制到str1中
  12. strcmp
    1
    2
    3
    4
    5
    6
    7
    8
    9
    strcmp(str1,str2);

    1)如全部字符相同,则认为两个字符串相等
    2)若出现不相同字符,则以第一队不相同的字符的比较结果为准

    函数值:
    1)相等,则返回0
    2)str1 > str2,返回正整数
    3)str1 < str2,返回负整数
  13. strlen
    1
    strlen(str);    //字符长度,不包含\0
  14. strlwr - 小写,strupr - 大写

    7.4 习题(第六章)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    #include <stdio.h>
    #include <math.h>
    int main()
    {int i,j,n,a[101];
    for (i=1;i<=100;i++)
    a[i]=i;
    a[1]=0;
    for (i=2;i<sqrt(100);i++)
    for (j=i+1;j<=100;j++)
    {if(a[i]!=0 && a[j]!=0)
    if (a[j]%a[i]==0)
    a[j]=0;
    }
    printf("\n");
    for (i=2,n=0;i<=100;i++)
    { if(a[i]!=0)
    {printf("%5d",a[i]);
    n++;
    }
    if(n==10)
    {printf("\n");
    n=0;
    }
    }
    printf("\n");
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    #include <stdio.h>
    int main()
    { int a[11]={1,4,6,9,13,16,19,28,40,100};
    int temp1,temp2,number,end,i,j;
    printf("array a:\n");
    for (i=0;i<10;i++)
    printf("%5d",a[i]);
    printf("\n");
    printf("insert data:");
    scanf("%d",&number);
    end=a[9];
    if (number>end)
    a[10]=number;
    else
    {for (i=0;i<10;i++)
    {if (a[i]>number)
    {temp1=a[i];
    a[i]=number;
    for (j=i+1;j<11;j++)
    {temp2=a[j];
    a[j]=temp1;
    temp1=temp2;
    }
    break;
    }
    }
    }
    printf("Now array a:\n");
    for (i=0;i<11;i++)
    printf("%5d",a[i]);
    printf("\n");
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //一个数组中元素逆序
    //以中间元素为中心,两侧元素互换即可
    #include <stdio.h>
    #define N 5
    int main()
    { int a[N],i,temp;
    printf("enter array a:\n");
    for (i=0;i<N;i++)
    scanf("%d",&a[i]);
    printf("array a:\n");
    for (i=0;i<N;i++)
    printf("%4d",a[i]);
    for (i=0;i<N/2;i++) //循环的作用是将对称的元素的值互换
    { temp=a[i];
    a[i]=a[N-i-1];
    a[N-i-1]=temp;
    }
    printf("\nNow,array a:\n");
    for (i=0;i<N;i++)
    printf("%4d",a[i]);
    printf("\n");
    return 0;
    }
    ==重点:杨辉三角==

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>
    # define N 10
    int main(){
    int i,j,a[N][N];
    for(i=0;i<N;i++){
    a[i][i]=1;
    a[i][0]=1;
    }
    for(i=2;i<N;i++){
    for(j=1;j<=i-1;j++){
    a[i][j]=a[i-1][j]+a[i-1][j-1];
    }
    }
    for(i=0;i<N;i++){
    for(j=0;j<=i;j++)
    printf("%6d", a[i][j]);
    printf("\n");
    }
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    //图形输出
    #include <stdio.h>
    int main()
    { char a[5]={'*','*','*','*','*'};
    int i,j,k;
    char space=' ';
    for (i=0;i<5;i++)
    { printf("\n");
    printf(" ");
    for (j=1;j<=i;j++)
    printf("%c",space);
    for (k=0;k<5;k++)
    printf("%c",a[k]);
    }
    printf("\n");
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    //非凯撒密码,对称密码
    #include <stdio.h>
    int main()
    {int j,n;
    char ch[80];
    printf("input cipher code:\n");
    gets(ch);
    printf("\ncipher code:%s\n",ch);
    j=0;
    while (ch[j]!='\0')
    { if ((ch[j]>='A') && (ch[j]<='Z'))
    ch[j]=155-ch[j];
    else if ((ch[j]>='a') && (ch[j]<='z'))
    ch[j]=219-ch[j];
    else
    ch[j]=ch[j];
    j++;
    }
    n=j;
    printf("original text:");
    for (j=0;j<n;j++)
    putchar(ch[j]);
    printf("\n");
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //strcat实现    不用strlen的方法
    //s1[i++]=s2[j++]
    #include <stdio.h>
    int main()
    { char s1[80],s2[40];
    int i=0,j=0;
    printf("input string1:");
    scanf("%s",s1);
    printf("input string2:");
    scanf("%s",s2);
    while (s1[i]!='\0')
    i++;
    while(s2[j]!='\0')
    s1[i++]=s2[j++];
    s1[i]='\0';
    printf("\nThe new string is:%s\n",s1);
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //strcmp实现
    #include <stdio.h>
    int main()
    { int i,resu;
    char s1[100],s2[100];
    printf("input string1:");
    gets(s1);
    printf("\ninput string2:");
    gets(s2);
    i=0;
    while ((s1[i]==s2[i]) && (s1[i]!='\0'))i++;
    if (s1[i]=='\0' && s2[i]=='\0')
    resu=0;
    else
    resu=s1[i]-s2[i];
    printf("\nresult:%d.\n",resu);
    return 0;
    }
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    //strcpy实现 运用了strlen
    #include <stdio.h>
    #include <string.h>
    int main()
    { char s1[80],s2[80];
    int i;
    printf("input s2:");
    scanf("%s",s2);
    for (i=0;i<=strlen(s2);i++)
    s1[i]=s2[i];
    printf("s1:%s\n",s1);
    return 0;
    }

    8 函数

    8.1 定义函数

    定义函数别忘了声明函数

    8.2 数组作为函数参数

    数组名作为函数参数时,传递的是数组首元素的地址,也就是说形参的值改变,实参的值也改变
    1
    2
    3
    4
    5
    6
    float score[10];
    average(score);

    float average(float array[10]){
    ……
    }

8.3 局部变量和全局变量

8.3.1 局部变量

1
2
1)在一个函数内部定义即为局部变量
2)形式参数也是局部变量

8.3.2 全局变量

在函数外部定义

为区别全局变量和局部变量,习惯将全局变量的第一个字母用大写表示

8.4 变量的存储方式和生存期

8.4.1 动态存储方式和静态存储方式

静态存储方式是指在程序运行期间由系统分配的固定的存储空间,动态存储方式是在程序运行期间根据需要进行动态分配

C 的存储类别包括四种:自动(auto),静态(static),寄存器(register),外部(extern)

8.4.2 局部变量存储类别

  1. 自动变量(auto 变量)
    默认为自动变量,在调用该函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间。
  2. 静态局部变量(static 局部变量)
    局部变量的值在调用结束后不消失,下一次再调用该函数时,使用该值。

==注意==

1
虽静态局部变量在函数结束调用后仍存在,但其他函数不能调用它。
  1. 寄存器变量(register)

    8.3.3 全局变量存储方式

    全局变量都存储在静态存储区中

拓展外部变量的作用域:

  1. 在一个文件内拓展
    1
    2
    3
    4
    5
    6
    7
    //将 A,B,C 使用范围拓展到定义之前
    int main(){
    extern int A,B,C;
    ……
    }

    int A,B,C
  2. 拓展到其他文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    file1:
    int A;
    int main(){
    ……
    }

    file2:
    extern A;
    ……
  3. 将外部变量作用域限制在本文件中
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /// 添加static声明
    file1:
    static int A;
    int main(){
    ……
    }

    file2:
    extern A;
    ……

    8.5 内部函数和外部函数

    8.6 习题(第七章)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    //函数递归应用
    #include <stdio.h>
    double P(int n,int x);
    int main(){
    int n,x;
    double result;
    printf("n,x:");
    scanf("%d,%d",&n,&x);
    result=P(n,x);
    printf("%f",result);
    }
    double P(int n,int x){
    if(n==0){
    return 1;
    }
    else if(n==1){
    return x;
    }
    else if(n>=1){
    return (2*n-1)*x-P(n-1,x)-(n-1)*P(n-2,x)/n;
    }
    }
    ![](./C_C++_01/20200301143808.png)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
int main()
{ void convert(int n);
int number;
printf("input an integer: ");
scanf("%d",&number);
printf("output: ");
if (number<0)
{putchar('-');putchar(' '); /* 先输出一个‘-’号和空格 */
number=-number;
}
convert(number);
printf("\n");
return 0;
}

void convert(int n)
{ int i;
if ((i=n/10)!=0)
convert(i);
putchar(n%10+'0');
putchar(32);
}

9 指针

9.1 指针变量

  1. 定义
    1
    int *point_1, *point_2;
  2. 引用指针变量
    1
    2
    3
    4
    5
    6
    p=&a;
    *p=1;


    (1)& 取地址符
    (2)* 指针运算符(或间接访问运算符),*p代表指针变量p指向的对象
  3. 指针变量作函数参数
    实现了调用函数使变量的值发生变化,在main函数中就可以使用这些改变了的值

9.2 指针引用数组

  1. 数组元素的指针
    1
    2
    3
    4
    5
    6
    int *p;
    int a[10]={0,1,2,3,4,5,6,7,8,9};

    p=a; //将a数组首元素的指针赋给p

    p=&a[0];
  2. 数组元素指针的计算
    1
    2
    p++;    //指向下一个元素地址
    p--; //指向前一个元素地址
  3. 指向多维数组

9.3 指针引用字符串

1
char *string="I love China";

9.4 内存动态分配

1
#include <stdlib.h>
  1. malloc
    1
    2
    #include <malloc.h>
    malloc(100); //开辟100字节临时分配空间
  2. calloc
    1
    p=calloc(50,4);     //分配50个4字节空间
  3. free
    1
    free(p);    //释放空间
  4. realloc
    1
    relloc(p,50);   //改变分配空间的大小

10 结构体

10.1 定义和使用

定义

1
2
3
4
5
6
7
8
struct Student{
int num;
char sex;
} student1,student2; // 注意分号

or

struct Student student1,student2;

初始化和使用

1
2
3
student1={11011,'M'};

student.num=10010; //使用 . 引用结构体内变量

10.2 结构体指针

1
2
3
struct Student stu_1;
struct Student *p;
p=&stu_1;

引用结构体中变量三种方法:

1
2
3
(1)stu.num
(2)(*p).num
(3)p->num //替代了第二种写法, '->' 称为指向运算符

10.3 共用体类型

共享一段内存的结构,后一个数据会覆盖前面的数据

1
2
3
4
5
union Data{
int i;
char ch;
float f;
}

10.4 枚举类型

一个变量只有几种可能的值

1
enum Weekday{sun,mon,tue,wed,thu,fri,sat};

10.5 typedef声明新类型名

1
2
3
4
5
6
7
8
9
一般用法:
typedef int Integer;

结构体;
typedef struct{
int mouth;
int day;
int year;
}Date;

11 文件输入输出

文件类型指针 stdio.h

11.1 打开与关闭文件

fopen打开文件

1
2
3
#include <stdio.h>
FILE *fp;
fp=fopen("al","r"); //注意双引号

文件使用方式

fclose关闭文件

1
fclose(fp);

11.2 顺序读写文件

11.2.1 读写字符

1
2
3
4
5
6
7
fgetc(fp);
fputc(ch,fp);



getc(fp); //stdio.h 中宏定义,和fgetc相同
putc(ch,fp);

11.2.2 读写字符串

1
2
fgets(str,n,fp);
fputs(str,fp);

11.2.3 格式化读写文件

1
2
fscanf(fp,"%d %f",&i,&f);
fprintf(fp,"%d,%6.2f",i,f);

11.2.4 二进制方式读写数据

1
2
fread(&stud[i],sizeof(struct Student_type),1,fp);
fwrite(&stud[i],sizeof(struct Student_type),1,fp);

11.3 文件位置标记与随机读写

  1. rewind 使文件位置标记指向文件开头
    1
    rewind(fp1);
  2. fseek改变文件位置标记
  3. ftell测定当前文件标记位置

11.4 文件读写的出错检测

12 位运算

12.1 按位与(&)

代码

1
2
3
4
5
6
7
8
9
10
#include "stdio.h"
int main()
{
int a,b;
a=077;
b=a&3;
printf("\40: The a & b(decimal) is %d \n",b);
b&=7;
printf("\40: The a & b(decimal) is %d \n",b);
}

样例输出

1
2
: The a & b(decimal) is 3
: The a & b(decimal) is 3

12.2 按位或(|)

代码

1
2
3
4
5
6
7
8
9
10
11
#include "stdio.h"
main()
{
int a,b;
a=077;
printf("%d",a);
b=a|3;
printf("\40: The a & b(decimal) is %d \n",b);
b|=7;
printf("\40: The a & b(decimal) is %d \n",b);
}

样例输出

1
2
63 : The a & b(decimal) is 63
: The a & b(decimal) is 63

12.3 异或(^)

同 0 异 1

代码

1
2
3
4
5
6
7
8
9
#include "stdio.h"
main()
{
int a,b;
a=7;
b=3;
printf("%d",a^b);
return 0;
}

样例输出

1
4

12.4 取反(~)

代码

1
2
3
4
5
6
7
8
#include "stdio.h"
main()
{
int a,b;
a=7;
printf("%x",~a);
return 0;
}

样例输出

1
fffffff8

12.5 移位运算

代码

1
2
3
4
5
6
7
8
#include "stdio.h"
main()
{
int a,b;
a=7;
printf("%x",a>>2);
return 0;
}

样例输出

1
1

常用C库函数

1. 数学函数

1
#include <math.h> 或 #include "math.h"
函数名 功能 函数原型
abs 绝对值 int abs(intx);
fabs 绝对值 double fabs(double x);
exp e^x double exp(double x);
floor 不大于x的最大整数 double floor(double x);
log lnx double log(double x);
log10 lgx double log10(double x);
pow x^y douoble pow(double x, double y);
sqrt √x double sqrt(double x);

计算log2n,使用换底公式

image-20200316134153930
1
log(n)/log(2);

2. 字符函数

1
#include <ctype.h>
函数名 功能 函数原型
isanum 判断是否数字 int isanum(int ch);
islower 判断是否小写字母 int islower(int ch);
isupper 判断是否大写字母 int isupper(int ch);

3. 字符串函数

1
#include <string.h>

1
2
# include <string.h>
void *memset(void *s, int c, unsigned long n);

4. 输入输出函数

1
#include <stdio.h>

5. 存储动态分配函数

运算符优先级

image-20200401135701567

同一优先级的运算符,结合次序由结合方向所决定。

简单记就是:! > 算术运算符 > 关系运算符 > && > || > 赋值运算符