循环例题:C 语言解决 “数位之和” 问题讲义
一、题目解析
1. 题目要求
给定一个整数,计算其所有数位之和。若该整数为负数,需先取其绝对值再进行计算。
2. 输入输出描述
- 输入:在一行中输入一个整数,整数的取值范围未明确限制,但需满足常规整数存储范围。
- 输出:输出一个整数,表示输入整数的所有数位之和。
3. 示例分析
示例:输入为 12,12 是正整数,直接将各位数字相加,1+2=3,所以输出 3
二、解题思路
要计算一个整数的数位之和,核心思路是将整数的每一位数字分离出来,然后进行累加。具体步骤如下:
- 分离每一位数字:通过循环,利用取余运算(%10)获取整数的最后一位数字,例如对于整数 123,123%10=3,即可得到最后一位数字 3。
- 累加数字:将每次分离出的最后一位数字累加到一个总和变量中。
- 去除已处理的位:通过整除运算(/10)将整数的最后一位去除,例如 123/10=12,这样下一次循环就能处理新的最后一位数字 2。
- 循环终止条件:当整数经过多次整除运算后变为 0 时,说明所有数位都已处理完毕,循环结束,此时总和变量中存储的就是该整数的数位之和。
三、完整代码实现
1 |
|
数组例题:矩阵转置
一、核心概念:什么是矩阵转置
矩阵转置就是把原矩阵的”行”和”列”互换。比如原矩阵是 2行3列,转置后变成 3行2列;原矩阵中第 i行第j列 的数字,转置后会出现在新矩阵的 第j行第i列。
举个例子:
原矩阵(2行3列):
1 | 1 2 3 // 第1行 |
转置后(3行2列):
1 | 1 4 // 原矩阵第1列的两个数 |
二、题目要求拆解
1. 输入规则
第一步:先输入两个整数 n 和 m(n 是原矩阵行数,m 是原矩阵列数),用空格分隔。
第二步:接着输入 n 行数据,每行有m个整数(用空格分隔),这就是原矩阵的内容。
2. 输出规则
输出转置后的矩阵,共m行(原矩阵的列数变行数),每行有 n 个整数(原矩阵的行数变列数)。
每个整数后面必须跟一个空格,每行结束后换行。
三、解题思路
分3步完成,核心是”先存原矩阵,再按转置顺序输出”:
- 定义变量和数组:用二维数组存储原矩阵(题目中矩阵规模小,定义 10x10的数组足够用),再定义循环变量 i(控制行)和 j(控制列)。
- 读取输入数据:先读 n 和 m,再用双重循环读n行、每行m个数字,存入二维数组。
- 转置输出:再用双重循环,按”原矩阵的列优先”输出——外层循环遍历原矩阵的列(从0到 m-1),内层循环遍历原矩阵的行(从0到 n-1),这样就能把原矩阵的”列”变成新矩阵的”行”。
四、完整代码示例
1 |
|
函数详解
一、函数的核心概念
函数是C语言中过程封装的核心载体,它将实现特定功能的代码块封装成独立模块,可被重复调用,是结构化程序设计的基本单元。
一个C程序由一个主函数(main函数)和若干个自定义函数组成,main函数是程序的唯一入口,程序从main函数开始执行,其他函数需被调用才能执行。
函数的核心价值体现在三点:
- 代码复用:避免重复编写相同功能代码,如多次计算圆面积时,只需编写一次计算函数并反复调用。
- 模块化编程:将复杂程序拆解为多个小功能函数,如学生成绩管理系统可拆分为成绩录入、计算、查询等函数,结构更清晰。
- 降低维护成本:修改功能时只需调整对应函数,无需改动整个程序,例如修改排序逻辑仅需更新排序函数。
二、函数的定义
1. 定义语法结构
1 | 返回值类型 函数名(形式参数列表) { |
- 返回值类型:指定函数执行后返回数据的类型,如int(整型)、float(浮点型);若无需返回值,需指定为void。
- 函数名:遵循标识符规则(字母/下划线开头,含字母、数字、下划线),需”见名知意”,如calculateSum表示求和函数。
- 形式参数列表(形参):接收外部传入的数据,格式为”类型 变量名”,多个参数用逗号分隔;无参数时可写void或空括号。
- 函数体:用{}包裹的代码块,包含变量声明、逻辑运算等语句,实现函数核心功能。
- return语句:将结果返回给调用者,非
void类型函数必须包含;void类型可省略,或仅写return;用于提前结束函数。
2. 典型定义示例
示例1:无参无返回值函数(输出欢迎信息)
1 |
|
示例2:有参有返回值函数(计算两数之和)
1 |
|
三、函数的调用与声明
1. 函数调用
调用语法
1 | 函数名(实际参数列表); |
- 实际参数(实参):传递给形参的数据,需与形参的数量、类型、顺序完全匹配,可是常量、变量或表达式,如calculateSum(2+3, 5)。
调用场景:
- 无返回值函数:作为独立语句调用,如printWelcome();。
- 有返回值函数:可赋值给变量或直接参与运算,如int max = getMax(10, 20);或printf(“最大值:%d”, getMax(10, 20));。
调用过程
- 参数传递:将实参的值复制给形参(默认值传递)。
- 执行函数体:程序跳转至函数,依次执行代码。
- 返回结果:若有返回值,将结果带回调用处;无返回值则直接回到调用处继续执行。
2. 函数声明
当函数定义在调用之后时,需提前声明函数,告知编译器函数的”签名”(返回值类型、函数名、参数列表),否则编译器会报错。
声明语法
1 | 返回值类型 函数名(形式参数列表); |
与函数定义的区别:无函数体,末尾加**;**,参数列表可仅写类型(建议写参数名以增强可读性)。
声明示例
1 |
|
四、函数的参数传递
C语言中参数传递有两种核心方式:值传递和地址传递(通过指针实现),核心区别在于是否能修改实参的值。
1. 值传递(默认方式)
原理:将实参的值复制一份给形参,形参和实参占用不同内存空间,形参的修改不会影响实参。
示例:尝试交换两数(值传递失效)
1 |
|
运行结果:
1 | 交换前:a=3, b=5 |
2. 地址传递(指针传递)
原理:将实参的内存地址传递给形参(形参为指针类型),形参指向实参的内存空间,修改形参指向的内容即修改实参。
示例:实现两数交换(地址传递生效)
1 |
|
运行结果:
1 | 交换前:a=3, b=5 |
五、变量的作用域与存储类型
1. 局部变量与全局变量
局部变量
- 定义位置:函数内部或代码块(如if、for内部)。
- 作用域:仅在定义它的函数/代码块内有效,外部无法访问。
- 生命周期:函数调用时分配内存,函数结束后释放,再次调用重新初始化(值不保留)。
示例:
1 |
|
全局变量
- 定义位置:所有函数外部。
- 作用域:从定义处开始,到整个源文件结束,所有后续函数均可访问。
- 生命周期:程序运行期间始终存在,内存空间固定,值可长期保留。
注意:全局变量会破坏函数独立性,增加代码耦合度,建议尽量少用。
示例:
1 |
|
运行结果:
1 | 最大值:94,最小值:8 |
章节习题:求阶乘(函数)
题目要求
定义函数计算n的阶乘(n为非负整数,0! = 1,n! = n×(n-1)×…×1),主函数输入n并输出结果。
解题思路
- 分情况处理:n=0时返回1;n≥1时通过循环累乘计算阶乘。
- 函数factorial接收int型参数n,返回long long型(避免n较大时整数溢出)。
参考代码
1 |
|
