C语言(函数与预处理、指针)

#一、函数与预处理
(一)一维数组
1.一维数组的定义格式为:
类型说明符 数组名[常量表达式]; 例如: int a[10];
它表示定义了一个整形数组,数组名为a,有10个元素。
2.在定义数组时,需要指定数组中元素的个数,方括弧中的常量表达式用来表示元素的个数,即数组长度。
3.常量表达式中可以包括常量和符号常量,但不能包含变量。
注意:
C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。
数组说明中其他常见的错误:
① float a[0]; /* 数组大小为0没有意义 /
② int b(2)(3); /
不能使用圆括号 /
③ int k, a[k]; /
不能用变量说明数组大小*/
(二)一维数组在内存中的存放
一维数组: float mark[100];
每个数据元素占用的字节数,就是基类型的字节数一个元素占4个字节
1.在定义数组时对数组元素赋以初值。
例如:int a[10]={0,1,2,3,4,5,6,7,8,9};
2. 可以只给一部分元素赋值。例如:
int a[10]={0,1,2,3,4};
定义a数组有10个元素,但花括弧内只提供5个初值,这表示只给前面5个元素赋初值,后5个元素值为0。
3. 如果想使一个数组中全部元素值为0,可以写成:
int a[10]={0,0,0,0,0,0,0,0,0,0};
或int a[10]={0};
不能写成:int a[10]={0*10};
(三)二维数组
1、类型说明符 数组名[常量表达式][常量表达式];
例如:
定义a为3×4(3行4列)的数组,b为5×10(5行10列)的数组。
如下:float a[3][4],b[5][10];
2、给二维数组初始化:四种方法对二维数组初始化:
①.分行给二维数组赋初值。
例如: int a[3][4]={{1,2,3,4},{5,6,7,8},
{9,10,11,12}};
②.可以将所有数据写在一个花括号内,按数组排列的顺序对各元素赋初值。
例如:
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
③.可以对部分元素赋初值。
例如: int a[3][4]={{1}, {5}, {9}};也可以对各行中的某一元素赋初值,如int a[3][4]={{1}, {0,6}, {0, 0, 0, 11}};
④.如果对全部元素都赋初值,则定义数组时对第一维的长度可以不指定,但第二维的长度不能省。
例如:
int a[3][4]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};等价于:int a[ ][4]={1, 2, 3, 4,5, 6, 7, 8, 9, 10, 11, 12};
3、字符数组的输入输出可以有两种方法:
•逐个字符输入输出。用格式符“%c”输入或输出一个字符。
•将整个字符串一次输入或输出。用“%s”格式符,意思是对字符串的输入输出。
说明:
(1)用“%s”格式符输出字符串时,printf函数中的输出项是字符数组名,而不是数组元素名。
(2)如果数组长度大于字符串实际长度,也只输出到遇′\0′结束。
(3)输出字符不包括结束符′\0′。
(4)如果一个字符数组中包含一个以上′\0′,则遇第一个′\0′时输出就结束。
(5)可以用scanf函数输入一个字符串。
(6) 如果利用一个scanf函数输入多个字符串,则在输入时以空格分隔。
例如:scanf(″%s%s%s″,str1,str2,str3);
(四)函数

  1. puts函数
    其一般形式为: puts (字符数组)
    •其作用是将一个字符串(以′\0′结束的字符序列)输出到终端。
    •假如已定义str是一个字符数组名,且该数组已被初始化为"China"。则执行puts(str);其结果是在终端上输出China。
    用puts函数输出的字符串中可以包含转义字符。
    例如:
    char str[]={″China\nBeijing″};
    puts(str);
    输出结果:
    China
    Beijing
  2. gets函数
    其一般形式为:gets(字符数组)
    其作用是从终端输入一个字符串到字符数组,并且得到一个函数值。该函数值是字符数组的起始地址。
    如执行下面的函数: gets(str)
    从键盘输入:
    Computer↙将输入的字符串"Computer"送给字符数组str
  3. strcat函数
    其一般形式为:strcat(字符数组1,字符数组2)
    Strcat的作用是连接两个字符数组中的字符串,把字符串2接到字符串1的后面,结果放在字符数组1中,函数调用后得到一个函数值——字符数组1的地址。
    例如:
    char str1[30]={″People′s Republic of ″};
    char str2[]={″China″};
    printf(″%s″,strcat(str1,str2));
    输出:
    People′s Republic of China
  4. strcpy函数
    其一般形式为:strcpy(字符数组1,字符串2)
    strcpy是“字符串复制函数”。
    作用:是将字符串2复制到字符数组1中去。例如:
    char str1[10],str2[]={″China″};
    strcpy(str1,”china”);
    (1)字符数组1必须定义得足够大,以便容纳被复制的字符串。字符数组1的长度不应小于字符串2的长度。
    (2)“字符数组1”必须写成数组名形式(如str1),
    “字符串2”可以是字符数组名,也可以是一个字符串常量。如:strcpy(str1,″China″);
    (3)复制时连同字符串后面的′\0′一起复制到字符数组1中。
    (4)可以用strncpy函数将字符串2中前面若干个字符复制到字符数组1中去。
    例如:strncpy(str1,str2,2);作用是将str2中前面2个字符复制到str1中去,然后再加一个‘\0’。
    (5)不能用赋值语句将一个字符串常量或字符数组直接给一个字符数组。如:
    str1=″China″; 不合法
    str1=str2; 不合法
    •用strcpy函数只能将一个字符串复制到另一个字符数组中去。
    •用赋值语句只能将一个字符赋给一个字符型变量或字符数组元素。
    •下面是合法的使用:
    char a[5],c1,c2;
    c1=′A′; c2=′B′;
    a[0]=′C′; a[1]=′h′; a[2]=′i′;
    a[3]=′n′; a[4]=′a′;
  5. strcmp函数
    其一般形式为:strcmp(字符串1,字符串2)
    strcmp的作用是比较字符串1和字符串2。
    例如:strcmp(str1,str2);
    strcmp(″China″,″Korea″);
    strcmp(str1,″Beijing″);
    比较的结果由函数值带回
    (1) 如果字符串1=字符串2,函数值为0。
    (2) 如果字符串1>字符串2,函数值为一正整数。
    (3) 如果字符串1<字符串2,函数值为一负整数。
    注意:对两个字符串比较,不能用以下形式:
    if(str1>str2)
    printf(″yes″);
    而只能用
    if(strcmp(str1,str2)>0)
    printf(″yes″);
  6. strlen函数
    其一般形式为: strlen (字符数组)
    strlen是测试字符串长度的函数。函数的值为字符串中的实际长度(不包括′\0′在内)。
    例如:char str[10]={″China″};
    printf(″%d″,strlen(str));
    7、寄存器变量register
    对于使用频繁的变量,可以使用register声明为寄存器变量,其值存储在CPU中,加快了运行速度。
    如:register int x;
    register char c;
    8、static函数的作用函数中的局部变量的值在函数调用结束后不消失而保留原值,以便下一次调用该函数时可以使用上一次调用的最后结果。这时就应该指定该局部变量为“静态局部变量”。
    #include <stdio.h>
    void increment(void);
    void main()
    {
    increment();
    increment();
    increment();
    }
    void increment(void)
    { int x=0;
    x++;
    printf(“%d\n”,x);
    }
    运行结果:
    1
    1
    1

#include <stdio.h>
void main()
{ void increment(void);
increment();
increment();
increment();
}
void increment(void)
{ static int x=0;
x++;
printf(“%d\n”,x);
}
运行结果:
1
2
3

9、extern函数
⑴在一个文件内声明外部变量
如果全局变量在后面定义,而在前面的函数中要使用,则必须在使用前用extern声明该全局变量。
如:extern int Abc;
⑵在多个文件的程序中声明外部变量
file1.c:
int Num; //若是 static int Num则在2.c中无法引用Num的值
main()
{ int power(int);
int b=3,c,d,m;
Num=3; m=2;
c=Numb;
d=powe(m);
}
file2.c:
extern Num;
power(int n)
{ int i,y=1;
for(i=1;i<=n;i++)
y
=Num;
return(y);
}
(五)函数的调用
函数调用的形式:
(1)作为函数语句调用。函数一般无返回值。例:
printf(“Hello,World!\n”);
(2)作为函数表达式调用。例:
m=max(a,b)2;
(3)作为函数参数调用。例:
printf(“%d”,max(a,b));
m=max(a,max(b,c));
«形参与实参
v形式参数:定义函数时函数名后面括号中的变量名
v实际参数:调用函数时函数名后面括号中的表达式
(六)预处理
1、对源程序编译之前做一些处理,生成扩展C源程序
2、种类
①宏定义 #define
②文件包含 #include
③条件编译 #if–#else–#endif等
3、格式:
①“#”开头
②占单独书写行
③语句尾不加分号
在源程序中这些命令都放在函数之外,而且一般都放在源文件的前面,它们被称为预处理部分
4、文件包含
①#include “stdio.h”
n默认在当前目录中找头文件,一般自己写的头文件,用””包含
②#include <stdio.h>
n在由系统指定的文件目录(/usr/include)中找头文件
5、宏定义define
①一般形式: #define 宏名(参数表) 宏体
②优点:a、节约空间(不需要给形参分配空间)
b、执行效率高(不需要根据地址找到函数入门)
③缺点:a、编译效率低(第一步预处理需替换)
b、不安全,只是简单的替换,没有语法检查
例 #define S(a,b) a
b
…………
area=S(3,2);
result=(3+1,2+1)
宏展开: area=32;
result=3+1
2+1=6而不是12
二、指针
1、指针是什么?起什么作用?
指针是变量的一种,里面是一个地址,通过这个地址找到要找的数据。
实质:单元的地址就是指针内容;
2、指针运算符
&是取地址的运算符,*是表示指针运算符
例:
int *p1,a;
p1=&a;
*p1 =3;
3.指针作函数参数
函数的参数不仅可以是整型、实型、字符型等数据,还可以是指针类型。作用是将变量的地址传送到另一个函数中。
参考例程:p1swapp2, aswapb ;abcswap ;
注意:变量的地址赋予指向相同类型的指针变量
4.指针的运算–赋值运算:
指针变量初始化赋值;
把一个变量的地址赋予指向相同数据类型的指针变量;
例如:int a, *pa ;
pa = &a ; //把a的地址给pa,都是整型
把一个指针变量的值赋予相同类型的另一个指针变量;
int a, *pa = &a, *pb ; pb = pa; // 把a的地址给pb;
3、指针与NULL的比较
空指针是对指针变量赋予0值得到的:
#define NULL 0
int *p=NULL; 空指针
p为指针变量,p=NULL表示空指针,不指向任何变量。
P !=NULL表示p不是空指针;
4、不同类型零值比较
①int:if(n == 0)或者 if (n != 0)
②float:const float EPSINON = 0.00001;
if ((n >= -EPSINON ) && (n <= EPSINON ))
③bool类型:if (flag)或者if (!flag)
④指针类型:if (n == NULL)或者if (n != NULL)
⑤注意:
a、指针变量未赋值时,可以是任意值,是不能使用的,会造成意外错误。而指针变量给NULL值后,则是可以使用的,只是不指向具体的变量。

b、指针变量的使用步骤:
1. 定义指针变量;
2.给指针变量赋地址;
3.正常使用指针进行运算;
(二)指针与数组
1、a.数组元素和指针
数组的指针是指数组的起始地址,数组元素的指针是数组元素的地址。
例如:
int a[10]; /定义a为包含10个整型数据的数组/
int p; /定义p为指向整型变量的指针/
p=&a[0]; 把a[0]元素的地址赋给指针变量p。 也就是说,p指向a数组的第0号元素。
2、用指针引用数组元素
①C语言规定:如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素。
例:
P的初值为&a[0] :
p+i和a+i都是a[i]的地址。
(p+i)和*(a+i)都是p+i和a+i所指向的数组元素,即a[i].
例如:
*(p+5), (a+5)就是a[5].
指向数组的指针变量也可以带下标。p[i]和
(p+i)等价。

3、引用一个数组:
下标法:用a[i]来表示;
指针法:用*(a+i),*(p+i)表示。
4、字符数组和字符串的区别
① 字符串指针变量本身是一个变量,用于存放字符串的首地址。而字符串本身是存放在以该首地址为首的一块连续的内存空间中并以‘\0’作为串的结束。
②字符数组是由于若干个数组元素组成的,它可用来存放整个字符串。
③对字符串指针方式 char *ps=“C Language”;
可以写为:
char *ps; ps=“C Language”;
而对数组方式: char st[]={“C Language”};
不能写为:
char st[20]; st={“C Language”};
而只能对字符数组的各元素逐个赋值。
5.前面说过,当一个指针变量在未取得确定地址前使用是危险的,容易引起错误。
但是对指针变量直接赋值是可以的。因为C系统对指针变量赋值时要给以确定的地址。
因此, char *ps=“C Langage”;
或者 char *ps; ps=“C Language”; 都是合法的。

猜你喜欢

转载自blog.csdn.net/qq_44578883/article/details/86688035