目录
思维导图
学习目标:
学习内容:
1. 值传递与地址传递(非常重要)
1.1 值传递
1.2 地址传递
2. 递归函数
2.1 递归的概念
2.2 递归条件
2.3 递归思想
3. 指针
3.1 指针相关概念
3.2 指针变量的定义
3.2.1. 定义格式
3.2.2. 指针变量的初始化
3.3 指针变量的使用
课内练习:
课外作业:
思维导图
学习目标:
- 一周掌握 C基础知识
学习内容:
1. 值传递与地址传递(非常重要)
1.1 值传递
说明:
值传递过程中,形参与实参操作的是不同的内存空间
当普通变量作为函数参数传递时,是单向的值传递,仅仅只是将实参的值,复制一份给形参使用,形参的改变不会影响到实参的值
例如:
#include<stdio.h>
//定义交换函数
void swap_1(int m, int n)
{
//完成两个数的交换
int temp = m;
m = n;
n = temp;
printf("交换后,swap_1:: m = %d, n = %d\n", m, n);
}
/*********************主程序*********************/
int main(int argc, const char *argv[])
{
//定义两个变量
int num = 520;
int key = 1314;
//调用交换函数
swap_1(num, key);
printf("交换后,main:: num = %d, key = %d\n", num, key);
return 0;
}
1.2 地址传递
说明:
当实参传递的是数组名、指针或变量的地址(&num)时,可以理解成是地址传递
地址传递过程中,形参与实参操作的是同一块内存空间
形参对内存空间进行改变时,实参也跟着一起改变
例如:
#include<stdio.h>
//定义冒泡排序函数
void sort_up(int brr[], int n)
{
printf("sizeof(brr) = %ld\n", sizeof(brr)); //
//进行冒泡排序
for(int i=1; i<n; i++)
{
for(int j=0; j<n-i; j++)
{
if(brr[j] > brr[j+1])
{
int temp = brr[j];
brr[j] = brr[j+1];
brr[j+1] = temp;
}
}
}
printf("排序结束\n");
}
/****************主程序********************/
int main(int argc, const char *argv[])
{
//定义一个一位数组并初始化
int arr[5] = {2,8,1,6,7};
printf("sizeof(arr) = %ld\n", sizeof(arr)); //20
//调用冒泡排序函数,完成升序排序
sort_up(arr, 5);
//输出排序后的结果
printf("排序后:");
for(int i=0; i<5; i++)
{
printf("%d\t", arr[i]);
}
printf("\n");
return 0;
}
2. 递归函数
2.1 递归的概念
所谓递归,就是一个函数直接或间接的形式调用自身,这样的函数调用,我们称为递归调用
2.2 递归条件
1. 递归出口:用于终止递归进行进行的条件
2. 递归表达式:能够让递归继续进行的函数调用
2.3 递归思想
当直接解决规模比较大的问题不能进行时,需要先解决规模较小的原理一致的问题后,大的问题得以解决时,可以考虑使用递归
逐层分解,逐层合并
例如:
#include<stdio.h>
int jiecheng(int n)
{
if(n==0){
return 1;
}else
return n*jiecheng(n-1);
}
/****************主程序********************/
int main(int argc, const char *argv[])
{
int res = jiecheng(5);
printf("%d",res);
return 0;
}
3. 指针
3.1 指针相关概念
1. 引入目的:能够从地址的角度,找到内存中的数据,而不是以变量的角度去找,效率较高
2. 指针:就是内存地址编号
3. 指针变量:由于指针这个地址编号很难记忆,我们引入指针变量存储指针
存储地址的变量称为指针变量
4. 指针变量中,只能存储地址,作为一个特殊的数据类型,其大小是固定的 8 字节
3.2 指针变量的定义
3.2.1. 定义格式
数据类型 * 指针名;
例如:int * ptr;
3.2.2. 指针变量的初始化
1、使用一个相同数据类型的变量的地址为其进行初始化
int num = 520; int * ptr = &num //将num的地址赋值个指针变量 ptr //定义一个指针变量ptr,指向num
2、使用一个已经初始化了的指针变量给一个新的指针变量进行初始化
int * qtr = ptr; //此时表示两个指针变量同时存储了num的地址 int *qtr =&num
3、使用地址的0 就是 NULL为其初始化
int *wtr = NULL;
4、注意:没有初始化的指针变量不能直接使用,因为该指针变量中存储了一个随机地址,如果对其进行更改,可能会导致系统瘫痪
5、野指针:指向非法内存的指针称为野指针 产生情况:
1)定义指针时,没有为其进行初始化
2) 指向了一个内存空间,但是随着程序的进行,该内存空间被回收了,那么该指针也是野指针(悬空指针)
3) 数组下标越界时,访问的地址也是野指针
3.3 指针变量的使用
使用运算符 ‘ * ’来取得指针变量中的值,我们也称该运算为 取值运算
&与*在指针的方面,互为逆运算
int num = 520; int *ptr = #
1) *&num ==> *(&num) ==> *(ptr) ==> num
2) &*ptr ==> &(*ptr) ==> &(num) ==> ptr
3) *&ptr ==>*(&ptr) ==> *(ptr的二级地址) ==> ptr
4) &*num ==>报错
课内练习:
1.求n!结果
解析:
2.求斐波那契数列第n项的值
1 1 2 3 5 8 13 21 。。。
解析:
课外作业:
1.使用递归实现 求 n 的 k 次方
解析:
#include<stdio.h>
//函数
int jiecheng(int n,int k)
{
if(k==0){
return 1;
}else
return n*jiecheng(n,k-1); //返回n*n*......*n(k个n)
}
/****************主程序********************/
int main(int argc, const char *argv[])
{
int k=0,n=0;
printf("请输入底数n与指数k:");
scanf("%d%d",&n,&k);
int res = jiecheng(n,k); //调用函数
printf("值为:%d",res);
return 0;
}
2.使用递归实现 strlen 的功能
解析:
#include<stdio.h>
int rec(char *str) {
// 基本情况:如果字符串为空,则长度为0
if (*str == '\0') {
return 0;
} else {
// 递归步骤:当前字符加上剩余字符串的长度
return 1 + rec(str + 1);
}
}
int main(int argc, char const *argv[])
{
char str[101]; // 假设输入的字符串长度不超过100
printf("请输入一个字符串:");
gets(str); //获取字符串
int len = rec(str); //调用函数
printf("字符串的长度是:%d\n", len);
return 0;
}
3.使用递归实现汉诺塔问题
解析:
#include<stdio.h>
int hanuo(int n) {
if (n == 1) {
return 1;
} else {
return hanuo(n-1)*2+1;
}
}
int main(int argc, char const *argv[])
{
int n=0;
printf("请输入n的值:");
scanf("%d",&n);
int sum=hanuo(n);
printf("次数为%d\n",sum);
return 0;
}
4.定义一个函数将一个字符串从大到小排序
解析:
#include <stdio.h>
#include<string.h>
#define MAX 50
// 函数声明
int change(char a[]);
int main() {
char a[MAX];
printf("请输入字符串:");
scanf("%s",a);
change(a); //调用函数
printf("字符串从大到小排序为:%s\n",a);
return 0;
}int change(char a[]){
int len=0;
len= strlen(a); //定义数组长度
int max=0;
for (int i = 1; i < len; i++)
{
for(int j=0;j <len-i;j++ ){
if(a[j] > a[j+1]){ //判断大小,进行交换三部曲
char temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
}
}
}
}
5.实现一个函数,用于检查一个字符串是否是回文字符串(正序和反序都相同)
解析:
#include <stdio.h>
#include<string.h>
#define MAX 50
int huiwen(char s[]){
int left=0; //定义最左边下标
int right = strlen(s)-1; //定义最右边下标
while (left <= right)
{
if(s[left] == s[right]){ //判断是否相等
return 1;
left++; //逐渐向右递增
right--; //逐渐向左递增
}else
{
return 0;
}
}
}
int main() {
char a[MAX];
printf("请输入字符串:");
scanf("%s",a);
if(huiwen(a)==1){
printf("是回文字符串\n");
}else
{
printf("不是回文字符串\n");
}
return 0;
}
6.使用指针完成判断自己的主机存储多字节整数时,是大端存储还是小端存储
解析:
#include<stdio.h>
int main(int argc, char const *argv[])
{
int a=0x12345678;
char *p=&a;
if(*p == 0x78){
printf("为小端存储\n");
}else if(*p ==0x12 ){
printf("为大端存储\n");
}
return 0;
}
7.
解析:
#include<stdio.h>
#include<string.h>
#define MAX 50
int count(char a[MAX]){
int sum=0;
int inWord=0;
gets(a);
for (int i = 0; a[i] != '\0'; i++) {
if ((a[i] >= 'A' && a[i] <= 'Z') ||(a[i] >= 'a' && a[i] <= 'z')) { // 检查当前字符是否为字母
if (inWord==0) { // 如果之前不在单词中,现在是单词的开始
sum++; // 增加单词计数
inWord = 1; // 标记现在在单词中
}
} else {
// 如果当前字符不是字母或数字,不在单词中
inWord = 0;
}
}
printf("单词数为%d个\n",sum);
}
int main(int argc, char const *argv[])
{
char a[MAX];
count(a);
return 0;
}