C语言基础 3
函数(Function),数组(Array),指针(Pointer)
函数(Function)
函数是C 语言编程的核心,用于将程序解决方案作为一系列子任务来完成。
比如,之前提到的main()函数,还有熟悉的printf()函数。我们也可以定义一个自己的函数。
函数的特点如下:
- 是一个可以执行特定任务的代码块。
- 可以被多次调用。
- 可以使程序更简单的被测试。
- 在不改变调用程序的前提下,可以被修改。
语法如下:
returnType functionName(parameters);
\\ 返回数据类型 函数名 (参数);
returnType 返回的数据类型,函数名后面要跟着括号。
例子:
# include <stdio.h>
int square( int num){
int res;
res = num * num;
return(res);
}
int main(){
int res;
int x = 6;
res = square(x);
printf('%d squared is %d\n',x,res);
return 0;
}
注意:除了主函数之外,所有函数在调用之前必须先声明。
递归函数(Recursive Fucntion)
所谓递归,简单的说就是函数调用自己。
经典的案例为斐波那契数列,斐波那契数列的实现如下。斐波那契数列的基本概念再次不做赘述,读者可以自行查阅。
# include <stdio.h>
int fib(int num){
int res;
if (num == 0)
res = 0;
else if (num == 1)
res = 1;
else
res = fib(num - 1) + fib(num -2);
return res;
}
int main(){
int x = 10;
int res, i;
for (i = 0, i < x; i++){
res = fib(i);
printf("%d,", res);
}
return 0;
}
数组(Array)
数组是一种数据类型,用来储存一系列数据类型相同的数据。数组可以用一个数组名来表示相关数据,而不是使数据单独的被使用。类型Python中的list。
比如:
int array[25];//定义一个容量为25的数组
int score[5] = {60,69,59,40,90};//定义容量为5的数组和初始化
// 数组内的数据要用逗号隔开
注意:数组储存在连续的内存位置,并且在声明后不能更改大小。
访问数组
可以使用index的方法来访问数组内的数据。如果一个数组有5个元素,index从0开始到4。
以以上score数组为例:
# include <stdio.h>
int main(){
int score[5] = {60,69,59,40,90};
for (int i = 0; i < 5; i++){
printf("The index is %d and The elements in array is %d. \n",i,score[i]);
}
return 0;
}
使用for循环给数组赋值
# include <stdio.h>
int main(){
int square[5];
for (int i = 1; i <= 5; i++){
square[i] = i * i;
printf("%d squared is %d.\n",i,square[i]);
}
return 0;
}
二维数组(Two-Dimensional Arrays)
二维数组可以看成是一个表格,也可以看成是一个网格。一个二维数组的声明代表着行数和列数,类似线性代数的矩阵。
比如:
int array[2][3]// 这是一个 2 * 3 的矩阵
二维数组赋值
int array[2][3] = {
{2,3,4}
{5,6,7}
};
也可以使用一下的形式
int array[2][3] = {{2,3,4},{5,6,7}};
访问二维数组
二维数组的访问也一维数组类似。
# include <stdio.h>
int main(){
int array[2][3] = {{2,3,4},{5,6,7}};
int i,j;
for (i = 0; i < 2; i++){
for (j = 0; j < 3; j++){
printf("%d,", array[i][j]);
}
printf("\n");
}
}
指针(Pointer)
C语言被设计为低级语言,可以轻松地范围内存位置并执行与内存相关的操作。指针在C语言中非常重要,因为它可以允许人轻易的访问内存地址。
指针是数组,字符串,结构体,算法的基本。
指针的定义
指针是一个包含了另一个变量地址的变量,即用来间接访问和储存其它变量的方法,定义的时候要是使用星号 " * "。
语法如下:
pointerType *pointerName;
具体例子如下:
# include <stdio.h>
int main(){
int j = 72;
int *p = NULL; //注意 * 符号
p = &j; //将变量j的内存地址赋值给指针p
printf("The address of j is %x\n", &j);
printf("p contains address %x\n", p);
printf("The value of j is %d\n", j);
printf("p is pointing to the value %d\n", *p);
}
运行结果如下
The address of j is e7e8899c
p contains address e7e8899c
The value of j is 72
p is pointing to the value 72
表达式中的指针
指针也可以作为变量在表达式中被使用。
比如:
# include <stdio.h>
int main(){
int x = 5;
int y;
int *p = NULL;
p = &x;
y = *p + 2; /* y is assigned 7 */
y += *p; /* y is assigned 12 */
*p = y; /* x is assigned 12 */
(*p)++; /* x is incremented to 13 */
}
指针与数组
指针在数组中也是非常重要的存在。一个数组的声明,已经在内存中给数组中的元素保留了连续的地址。使用指针指向第一个元素,之后使用地址的算数操作来遍历数组中的元素。
’ + '用来向前面移动访问内存地址
’ - ’ 用来向后面移动访问内存地址
比如:
# include <stdio.h>
int main(){
int array[5] = {22,33,44,55,66};
int *p = NULL;
p = array; //因为数组的名字也是一个指针,可以直接赋值给p
//也可以看做是 ptr = &a[0]将数组第一个元素的地址赋值给p
for (int i = 0; i < 5; i++){
printf("%d,",*(p + i));
}
}
指针与函数
指针可以扩大函数的可能性,我们就可以不用只返回一个值了,有了指针,函数就可以更改实际数据而不是数据的副本。为了改变变量的实际数据,调用语句传递地址给指针。
典型的例子就是两个变量的数值互换。
比如:
# include <stdio.h>
# include <stdio.h>
void swap(int *num1, int *num2);
void exchange(int num1, int num2);
int main(){
int x = 25;
int y = 200;
printf("x is %d, y is %d\n",x,y);
swap(&x,&y);
printf("x is %d, y is %d\n",x,y);
exchange(x,y);
printf("x is %d, y is %d\n",x,y);
return 0;
}
void swap(int *num1, int *num2){
int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
void exchange(int num1, int num2){
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
运行结果:
x is 25, y is 200
x is 200, y is 25
x is 200, y is 25
从运行结果可以看出,swap()函数改变了x和y的值,而exchang()函数未能交换x和y的值。
函数与数组
带有数组参数的函数
一个数组不能传递数值给函数,然而数组的名字是一个指针,所以传递数组的名字给函数,相当于传递一个指针给函数。
比如:
# include <stdio.h>
int add_up(int *a, int num_elements);
int main(){
int a[5] = {1,2,3,4,5};
printf("Total orders is %d\n", add_up(a, 5));
return 0;
}
int add_up(int *a, int num_elements){
int total = 0;
for (int i = 0; i < num_elements; i++){
total += a[i];
}
return total;
}
返回数组的函数
就像指向数组的指针可以传递给函数一样,函数可以返回一个指向数组的指针。
比如:
# include <stdio.h>
int *get_even();
int main(){
int *a;
a = get_even();
for (int i = 0; i < 5; i++){
printf("%d\n",a[i]);
//printf("%d\n",*(a+i));
}
return 0;
}
int *get_even(){
static int num[5];
int even = 0;
for (int i; i < 5; i++){
num[i] = even += 2;
}
return num;
}
注意:
是指针被声明来存储函数返回的值,而不是数组。同时注意当本地变量被传递到函数外部的时候,需要在函数内声明为静态的。记住:a[i] 和 *(a+i) 是一个意思。