C基础学习

1、break,continue,return关键字的使用

1.1 break关键字

1. 和switch...case配合使用,退出switch....case分支。
2. 和循环语句配合使用,退出循环体,后边所有的循环都将不会再被执行。
#include <stdio.h>
int main(int argc, const char *argv[])
{
 for (int i = 0; i < 10; i++)
 {
  putchar('#');
  if (i == 5)
  {
   break; // 退出循环体,后边的所有的循环都将不会被执行
  }
 }

 putchar('\n');
 return 0;
}

输出结果:######
#include <stdio.h>
int main(int argc, const char *argv[])
{
 for (int i = 0; i < 5; i++)
 {
  for (int j = 0; j < 10; j++)
  {
   putchar('#');
   if (j == 5)
   {
    break; // 退出循环体,后边的所有的循环都将不会被执行
   }
  }
  putchar('*');
 }

 putchar('\n');
 return 0;
}
输出结果:######*######*######*######*######*

1.2 continue关键字

1. 和循环语句配合使用,退出本次循环,continue执行的代码不会被执行,
	而是执行下一次的循环
#include <stdio.h>
int main(int argc, const char *argv[])
{
 for (int i = 0 ; i < 10; i++)
 {
  putchar('#');
  if (i >= 5)
  {
   continue; // 退出本次循环,本次循环后边的代码不会被执行,执行下一次的循环
  }
  putchar('*');
 }
 putchar('\n');
 return 0;
}
输出结果:#*#*#*#*#*#####

1.3 return关键字

1. 常用于函数的退出,并返回一个结果。
案例:
#include <stdio.h>

int main(int argc, const char *argv[])
{
 int i,j;

 for (i = 1; i <= 9; i++)
 {
  for(j = 1; j <= 9; j++)
  {
   printf("%d * %d = %d\t", i, j, i*j);
   if ( i == j)
   {
    break;
   }
  }
  putchar('\n');
 }
 return 0;
}

2、函数

2.1 概念

	将具有特定功能的一段代码,封装成一个代码块,当使用此代码时,
	可以通过调用的方式进行使用。
	封装函数之后,需要重复被使用的代码不需要重复书写,直接通过
	函数的调用实现即可。
	
	比如:printf,scanf,putchar,getchar,puts,gets
		算法库,
	
	调用别人实现的函数,无需了解函数的内部的实现,
	只需要掌握被调用函数的(三要素):功能,参数,返回值

2.2 定义函数的语法格式


返回类型  函数名 (形参列表)
{
	函数体;
	return 返回值;
}

返回类型  函数名 (数据类型 形参变量名1, 数据类型 形参变量名2,...)
{
	函数体;
	return 返回值;
}

注:
	1. 返回类型 : 数据类型
	2. 函数名:遵循标识符的命名的规则
	3. 形参变量名 : 变量名,遵循标识符的命名的规则,
		此变量属于局部变量,只能再函数内被调用。
	
	4. 如果函数有返回值通过 return 返回值;进行返回
		如果函数没有返回值值,return;可以省略不写,
		或者写成return;
	5. 函数的形参也是可有可无,如果没有形参写成()或者(void)

2.3 函数的调用

函数没有形参,没有返回值:
	函数名();		---> ()中不可以写任何的东西

函数有形参,没有返回值:
	函数名(实参列表);	---> 比如:函数名(1,2);

函数没有形参,有返回值:
	变量名 = 函数名();

函数有形参,有返回值:
	变量名 = 函数名(实参列表);  ---> 比如:sum = 函数名(a, b);
	
如果函数的返回类型为int类型,一般使用int类型的变量接收函数的返回值,
如果使用float类型的变量接收返回类型为int类型的函数的返回值,
会发生隐式类型转换。
案例1:封装函数,打印以下图形
**************************************
*** 1. 增 2. 删 3. 改 4. 查 5. 退出 ***
**************************************

案例2:封装一个加法运算的函数

#include <stdio.h>

void print_menu(void)
{
 puts("**********************************");
 puts("*** 1.增 2.删 3.改 4.查 5.退出 ***");
 puts("**********************************");

 return; // return;可以省略
}

/*
 * 封装函数时先书写函数的名字,见名知意,确定函数的功能,
 * 在考虑函数的形参,如果需要通过外部传递那就添加对应的参数,
 * 如果函数的结果需要被外部的使用,那就通过返回值进行返回。
 *
 *
 * */

int add_func(int a, int b)
{
#if 0
 int sum = 0;
 sum = a + b;
 return sum;
#else 
 return (a + b);
#endif
}



int main(int argc, const char *argv[])
{
 // 函数的调用
 print_menu();

 int sum = 0;
 int a = 1000, b = 2000;
 sum = add_func(a, b);
 printf("sum = %d\n", sum);

 printf("sum = %d\n", add_func(123, 456));


 return 0;
}

3、数组

3.1 数组的概念

	数组属于构造类型。
	特点:
		1> 数组中的每个成员的类型都是一样的;
		2> 数组中的所有的成员在内存中地址是连续的;
	
	数组分类:一维数组,二维数组,多维数组

3.2 一维数组

3.2.1 一维数组的概念

	一维数组的下标只有一个,每个元素的下标(列)。
	一维数组中的每个成员在内存中都是连续的。

image-20230411145942681

3.3.2 定义一维数组

存储类型  数据类型   数组名[数组中成员个数];

数组中成员个数 : 定义数组时必须指定数组的长度(成员个数),
	数组一旦定义好之后,数组的长度不可以被修改。
	
数组中的每个成员进行访问时,数组的下标从0开始;
	数组的第0个元素,数组的第1个元素,数组的第2个元素.....
	数组的第0个成员,数组的第1个成员,数组的第2个成员.....


数组的使用:使用数组时一般都是使用数组的某个元素。
访问数组的某个元素: 数组名[下标];

3.3.3 定义数组并进行初始化的方式

#include <stdio.h>
/*
 * 功能:打印数组中每个元素的值
 * 参数:
 * 	@ arr : 传递一个int类型的数组的数组名,数组名表示数组的首地址
 *	@ len : 传递的数组中的长度
 * 返回值:无
 * */
void print_arr(int arr[], int len)
{
 printf("-----------------------\n");
 for(int i = 0; i < len; i++)
 {
  printf("arr[%d] = %d\n", i, arr[i]); 
 }
}

int main(int argc, const char *argv[])
{
 // 1. 定义数组的同时进行初始化
 int arr[5] = {10,20,30,40,50};
 // 打印数组中每个成员的值
 for (int i = 0; i < 5; i++)
 {
  printf("arr[%d] = %d\n", i, arr[i]);
 }

 // 2. 定义数组的同时,对部分成员进行初始化
 // 依次对数组中的每个元素进行初始化,后边的没有初始化的
 // 默认会初始化为0.
 int arr2[5] = {100, 200};
 // 如果函数的形参是一个数组类型的,传递数组的名字
 print_arr(arr2, 5);

 // 3. 定义数组时,将数组中的所有成员初始化为0
 int arr3[10] = {0};
 print_arr(arr3, 10);

 // 4. 先定义数组,然后在对每个成员分别进行初始化
 int arr4[5];  // 不进行初始化,默认初始化为随机值
 print_arr(arr4, 5);
 // 数组一旦被定义了,就不可以对其整体进行初始化,
 // 只能一个一个元素的进行初始化
 // arr4 = {1000,2000,3000,4000,5000};  // 错误
 arr4[0] = 1000;
 arr4[1] = 2000;
 arr4[2] = 3000;
 arr4[3] = 4000;
 arr4[4] = 5000;
 print_arr(arr4, 5);
 
    // 5. 定义数组时不指定数组的长度,通过初始化成员的个数,
 // 指定数组的长度
 // 如果定义数组时不指定数组的长度,必须对数组定义的同时,
 // 进行初始化
 int arr5[] = {111,222,333,444,555}; // 数组长度为5
 print_arr(arr5, 5);

 return 0;
}

3.3.4 数组的特性及使用时注意事项

#include <stdio.h>
int main(int argc, const char *argv[])
{
 int arr[10] = {0};
 int arr1[10] = {0};

 // 1. 计算数组占用内存空间的大小  sizeof(数组名)
 printf("数组的占用内存空间大小 = %ld\n", sizeof(arr));

 // 2. 计算数组中的成员个数(数组长度)
 printf("数组成员的个数 = %ld\n", sizeof(arr)/sizeof(int));

 // 3. 数组的名字就是数组的在内存分配内存空间的首地址,
 // 和数组的第0个元素的地址是一样的。
 printf("数组的首地址 = %p\n", arr);
 // & : 单目运算符,对变量进行取地址运算
 // %p : 按照十六进制形式打印地址。
 printf("数组的第0个元素的地址 = %p\n", &arr[0]);
 
 // 4. 数组名是一个常量,不可以进行赋值操作,
 // 数组名也不可以进行自增自减运算。
 // arr = arr1;			// 错误
 // arr++;				// 错误
 
 // 5. 数组中的所有的成员在内存中地址是连续的
 for(int i = 0; i < 10;i++)
 {
  // 由于数组的每个元素都是int类型的,
  // 因此每个成员的地址相差4字节。
  printf("&arr[%d] = %p\n", i, &arr[i]);
 }


 // 6. 对数组进行访问时,编译器不会对数组的越界进行检查
 // 因此在对数组进行操作时一定要注意越界的问题。
 // 如果访问数组越界,相当于操作了非法的内存空间,
 // 有可能会导致程序的运行结果不可预知,或者发生段错误。
 //	arr[2000] = 1000; // 数组越界访问,出现段错误
 arr[10] = 1000;  // 数组越界访问,没有出现段错误
 
 return 0;
}

3.3.5 练习题

1. 定义一个整型数组,数组长度为10,
 从终端输入的方式对数组的每个元素进行初始化。
 将数组中的成员进行倒叙。
 比如:int arr[10] = {1,2,3,4,5,6,7,8,9,10};
  倒叙之后的结果如下所示:
  arr[10] = {10,9,8,7,6,5,4,3,2,1};
  
 将会两个变量的值:
    int tmp;
    tmp = a;
    a = b;
    b = tmp;
    
    tmp = a + b;
    b = tmp - b;
    a = tmp - b;

#include <stdio.h>
void init_array(int arr[], int len)
{
 for (int i = 0; i < len; i++)
 {
  /*
  int tmp = 0;
  scanf("%d", &tmp);
  arr[i] = tmp;
  */
  scanf("%d", &arr[i]);
 }
}


void array_flashback(int arr[], int len)
{
#if 0
 for (int i = 0; i < len / 2; i++)
 {
  int tmp;
  tmp = arr[i];    // 0 1 2 3 4
  arr[i] = arr[len - i - 1]; // 9 8 7 6 5 
  arr[len - i - 1] = tmp;
 }
#endif 
 for (int i = 0, j = len - 1; i < j; i++, j--)
 {
  int tmp;
  tmp = arr[i];    // 0 1 2 3 4
  arr[i] = arr[j]; // 9 8 7 6 5 
  arr[j] = tmp;
 
 }
}

void print_array(int arr[], int len)
{
 for (int i = 0; i < len;i++)
 {
  printf("%d ", arr[i]);
 }
 putchar('\n');
}

int main(int argc, const char *argv[])
{
 int arr[10] = {0};
 init_array(arr, sizeof(arr)/sizeof(int));
 array_flashback(arr, sizeof(arr)/ sizeof(int));
 print_array(arr,sizeof(arr)/sizeof(int));
 
 return 0;
}

2. 定义一个整型数组,数组长度为10,
 从终端输入的方式对数组的每个元素进行初始化,
 求获取数组中最大成员的值;
 求数组中最大成员的下标。
        
 #include <stdio.h>
void init_array(int arr[], int len)
{
 for (int i = 0; i < len; i++)
 {
  /*
  int tmp = 0;
  scanf("%d", &tmp);
  arr[i] = tmp;
  */
  scanf("%d", &arr[i]);
 }
}

int get_array_max_value(int arr[], int len)
{
 int max_value = arr[0];  // 假设第0个元素的值最大
 for (int i = 1; i < len; i++)
 {
  if (max_value < arr[i])
  {
   max_value = arr[i]; // 把最大元素的值赋值给max_value
  }
 }
 return max_value;
}
int get_array_max_index(int arr[], int len)
{
 int max_value = arr[0];  // 假设第0个元素的值最大
 int index = 0; // 假设第0个元素最大
 for (int i = 1; i < len; i++)
 {
  if (max_value < arr[i])
  {
   max_value = arr[i]; // 把最大元素的值赋值给max_value
   index = i;
  }
 }
 return index;
}



void print_array(int arr[], int len)
{
 for (int i = 0; i < len;i++)
 {
  printf("%d ", arr[i]);
 }
 putchar('\n');
}

int main(int argc, const char *argv[])
{
 int arr[10] = {0};
 init_array(arr, sizeof(arr)/sizeof(int));
 print_array(arr,sizeof(arr)/sizeof(int));
 
 int max, index;
 max = get_array_max_value(arr, sizeof(arr)/sizeof(int));
 index = get_array_max_index(arr, sizeof(arr)/sizeof(int));
 printf("arr[%d] = %d\n", index, max);
 return 0;
}
       

4、二维数组

4.1 二维数组的概念

二维数组有行和列下标。

4.2 定义二维数组的格式

存储类型  数据类型  二维数组名[行数][列数];

特点:
	1> 二维数组的所有的成员在内存中依然是连续的
	2> 二维数组的行和列的下标都是从0开始
	3> 数组的每个成员都和定义二维数组时,数据类型一致。
	
	int arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};

如何访问数组中的每一个元素:
	二维数组名[行下标][列下标];

image-20230411164756621

image-20230411164805671

image-20230411164819547

4.3 定义二维数组并进行初始化

#include <stdio.h>

int main(int argc, const char *argv[])
{
 // 1. 定义二维数组的同时进行初始化
 short two_arr[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}};
 
 for (int i = 0; i < 3; i++) // 遍历二维数组的行
 {
  for (int j = 0; j < 4; j++) // 遍历二维数组的列
  {
   printf("two_arr[%d][%d] = %d ", i, j, two_arr[i][j]);
  }
  putchar('\n');
 }

 // 2. 定义数组,将二维数组的所有元素初始化为0
 short two_arr2[3][4] = {0};  // 将二维数组的所有的元素初始化为0

 // 3. 定义数组的同时进行初始化,
 // 逐行进行初始化,如果没有指定则初始化为0
 short two_arr3[3][4] = {1,2,3,4,5,6,7,8};
 for (int i = 0; i < 3; i++) // 遍历二维数组的行
 {
  for (int j = 0; j < 4; j++) // 遍历二维数组的列
  {
   printf("two_arr3[%d][%d] = %d ", i, j, two_arr3[i][j]);
  }
  putchar('\n');
 }

 // 4. 定义数组的同时进行初始化,指定每行的元素的值
 // 每行中没有进行初始化的则初始化为0
 short two_arr4[3][4] = {{1,2,3},{4,5},{6}};
 for (int i = 0; i < 3; i++) // 遍历二维数组的行
 {
  for (int j = 0; j < 4; j++) // 遍历二维数组的列
  {
   printf("two_arr4[%d][%d] = %d ", i, j, two_arr4[i][j]);
  }
  putchar('\n');
 }
 
 // 5. 定义二维数组时,不指定数组的行数,通过初始化时指定数组的行数
 // 注:定义数组时不能省略列数
 short two_arr5[][4] = {1,2,3,4,5,6,7,8,9};
 for (int i = 0; i < 3; i++) // 遍历二维数组的行
 {
  for (int j = 0; j < 4; j++) // 遍历二维数组的列
  {
   printf("two_arr5[%d][%d] = %d ", i, j, two_arr5[i][j]);
  }
  putchar('\n');
 }

 // 6. 先定义二维数组,后进行初始化
 short two_arr6[2][3]; // 局部变量,默认初始化为随机值
 for (int i = 0; i < 2; i++)
 {
  for (j = 0; j < 3; j++)
  {
   two_arr[i][j] = i+j;
  }
 }

 // 注:一定定义了二维数组之后,不可以整体进行访问,赋值或者读值
 // 数组一旦被定义之后,只能使用单个元素的方式进行访问
 // two_arr6 = {{1,2},{3,4},{5,6}}; // 错误
 return 0;
}

4.4 二维数组的特性及使用注意事项

#include <stdio.h>
int main(int argc, const char *argv[])
{
 short two_arr[3][4] = {0};

 // 1. 获取二维数组占用内存空间的大小 sizeof(short) * 行数 * 列数
 printf("二维数组占用内存空间的大小 = %ld\n", sizeof(two_arr));
 
 // 2. 获取二维数组有多少个成员
 printf("二维数组成员的个数 = %ld\n", sizeof(two_arr)/sizeof(short));
 

 // 3. 获取二维数组的行数
 // sizeof(two_arr[0]) : 计算二维数组一行占用的内存空间的大小
 // two_arr[0] : 表示二维数组的第0行的首地址
 printf("二维数组的行数 = %ld\n", sizeof(two_arr)/sizeof(two_arr[0]));
 
 // 4. 获取二维数组的列数 
    // two_arr[1] : 表示二维数组的第1行的首地址
    // sizeof(two_arr[1]) : 计算二维数组一行占用的内存空间的大小
 printf("二维数组的列数 = %ld\n", sizeof(two_arr[1])/sizeof(short));
 

 // 5. 数组名相关的使用
 // 5.1 二维数组名是一个常量,不可以进行赋值运算,
 // 也不可以进行自增自减运算
 
 // 5.2 二维数组的名表示二维数组的首地址,此地址和第0行第0列元素的地址相等。
 printf("two_arr = %p\n", two_arr);
 printf("&two_arr[0][0] = %p\n", &two_arr[0][0]);

 // 5.3 数组名[行下标] : 每一行的第0个元素的地址
 printf("two_arr[0] = %p\n", two_arr[0]);
 printf("&two_arr[0][0] = %p\n", &two_arr[0][0]);

 printf("two_arr[1] = %p\n", two_arr[1]);
 printf("&two_arr[1][0] = %p\n", &two_arr[1][0]);

 printf("two_arr[2] = %p\n", two_arr[2]);
 printf("&two_arr[2][0] = %p\n", &two_arr[2][0]);
 
 // 6. 二维数组越界的问题,编译器不会检查数组越界的问题,
 // 需要程序员在编写代码时,要思考代码越界的问题。


 return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值