以下是对图片中二维数组相关知识的总结与补充:
类型说明符 数组名[行数][列数];
,比如 int a[3][4];
,表示定义了一个 3 行 4 列的整型二维数组 ,用于存储按行和列排列的数据。数组名[行下标][列下标]
来访问元素,下标从 0 开始计数 。若下标超出定义的范围(比如行数定义为 3,却用 a[3][0]
访问 ),会造成数组越界,可能引发程序错误 。二维数组在内存中是按行优先的顺序连续存储的 。可将其理解为 “数组的数组” ,比如 a[3][4]
,可看作是 3 个长度为 4 的一维整型数组(a[0]
、a[1]
、a[2]
)依次存储,体现了单一性(元素类型统一 )、连续性(内存存储连续 )、有序性(按行下标、列下标有序排列 ) 。
数组名
(如 a
)代表二维数组的首地址,等价于 &a[0]
,是指向包含若干列元素的一维数组的指针 。a[i]
代表第 i
行一维数组的首地址,等价于 &a[i][0]
,是指向该行第一个元素的指针 。a[i][j]
就是具体存储的元素值,可通过指针运算等方式灵活操作其读写 。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 行 4 列的数组 ,但列数必须明确指定,保证每行元素个数一致的规则 。若要输出二维数组内容,可结合循环:
#include
int main() {
int a[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("%d ", a[i][j]);
}
printf("\n");
}
return 0;
}
通过嵌套循环,外层控制行,内层控制列,逐个输出元素,并用 printf("\n");
实现每行结束后换行 ,类似地,输入也可借助循环,用 scanf
逐个为 a[i][j]
赋值 。
二维数组可作为函数参数传递 ,不过传递时一般需指定列数(或通过其他方式让函数知晓列数 ),常见形式如 void func(int a[][4], int row)
(row
用于接收行数 ),在函数内部按行、列下标操作数组元素,实现数据处理,比如对二维数组求和、找最大值等功能 。
#include //计算二维数组所有元素之和:
#if 0
int main(void)
{
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int line=sizeof(a)/sizeof(a[0]);
int row=sizeof(a[0])/sizeof(a[0][0]);
int i,j,sum=0;
for(i=0;i
这段代码的逻辑是通过嵌套循环遍历二维数组的所有元素,并计算它们的总和,具体步骤如下:
定义并初始化二维数组:
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
定义了一个3行4列的二维数组a
,并初始化了12个整数元素。
计算数组的行数和列数:
int line = sizeof(a) / sizeof(a[0]);
sizeof(a)
获取整个二维数组的总字节数,除以一行元素的字节数sizeof(a[0])
,得到行数(结果为3)。int row = sizeof(a[0]) / sizeof(a[0][0]);
sizeof(a[0])
,除以一个元素的字节数sizeof(a[0][0])
,得到列数(结果为4)。初始化求和变量:
int i, j, sum = 0;
定义循环变量i
(行索引)、j
(列索引),以及累加和变量sum
并初始化为0。
嵌套循环遍历数组并求和:
for(i=0; i:控制行索引,从0遍历到行数-1(0~2)。
for(j=0; j:控制列索引,从0遍历到列数-1(0~3)。
sum += a[i][j];
,将当前元素a[i][j]
的值累加到sum
中。输出结果并结束程序:
printf("%d\n", sum);
return 0;
打印累加得到的总和(1+2+…+12=78),然后程序正常退出。
整个逻辑通过动态计算行列数(而非硬编码3和4),使代码更灵活——当数组的行数或列数改变时,循环条件会自动适配,无需手动修改。
注:代码被#if 0
和#endif
包裹,这会让预处理器忽略中间的代码(相当于暂时注释掉)。如果要运行程序,需要删除这两行。
int main(void) //计算二位数组外围元素之和。
{
int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int line=sizeof(a)/sizeof(a[0]);
int rows=sizeof(a[0])/sizeof(a[0][0]);
int i,j;
int sum=0;
for(i=0;i
这段代码的功能是计算二维数组外围元素的总和,逻辑清晰且正确,具体分析如下:
通过判断元素是否位于数组的"外围"(即第一行、最后一行、第一列或最后一列),将符合条件的元素值累加求和。
数组定义与初始化:
int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12};
定义了一个3行4列的二维数组(行数由初始化元素个数自动推导)
计算行列数:
line = sizeof(a)/sizeof(a[0])
:得到行数(3行)rows = sizeof(a[0])/sizeof(a[0][0])
:得到列数(4列)外围元素判断逻辑:
if(0==i||0==j||i==line-1||j==rows-1)
这个条件判断元素是否位于:
求和过程:
对所有满足外围条件的元素进行累加,最终得到外围元素总和。
对于这个3×4的数组,外围元素包括:
总和为:1+2+3+4+5+8+9+10+11+12 = 65
这段代码的优点是通过动态计算行列数,使程序可以适应不同大小的二维数组,只需保证数组定义正确即可。
int main(void) //二维数组同行逆序
{
int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12};
int line=sizeof(a)/sizeof(a[0]);
int rows=sizeof(a[0])/sizeof(a[0][0]);
int i,j;
for(i=0;i
这段代码的功能是实现二维数组中每行元素的逆序排列(即每行内部的元素首尾互换),具体逻辑如下:
对二维数组的每一行,将该行的第1个元素与最后1个元素交换、第2个元素与倒数第2个元素交换……以此类推,直到完成该行所有元素的逆序。
数组定义与初始化:
int a[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
定义了一个3行4列的二维数组,初始值为:
1 2 3 4
5 6 7 8
9 10 11 12
计算行列数:
line = sizeof(a)/sizeof(a[0])
:得到行数(3行)rows = sizeof(a[0])/sizeof(a[0][0])
:得到列数(4列)每行逆序的核心逻辑:
for(i=0; i<line; ++i) // 遍历每一行
{
for(j=0; j<rows/2; ++j) // 遍历每行前半部分元素
{
// 交换当前元素与对称位置的元素
int t = a[i][j];
a[i][j] = a[i][rows-1-j];
a[i][rows-1-j] = t;
}
}
i
控制):逐个处理每一行j
控制):只需要遍历到每行的中间位置(rows/2
),因为每个交换操作会同时处理两个元素a[i][j]
与a[i][rows-1-j]
互换(例如第1行中,j=0
时交换a[0][0]
和a[0][3]
,j=1
时交换a[0][1]
和a[0][2]
)输出结果:
逆序后的数组为:
4 3 2 1
8 7 6 5
12 11 10 9
rows/2
次(对于4列数组,只需循环2次),避免重复交换这种实现方式高效且简洁,时间复杂度为O(行数×列数/2),是处理二维数组每行逆序的经典方法。
#include
int main(void) //在二维字符型数组内找最大的一维字符型数组
{
char s[][100]={"hello","world","china"};
int rows = sizeof(s)/sizeof(s[0]);
int i;
char max[100];
for(i=1;i
这段代码的意图是在二维字符数组中找到"最大"的字符串(按字典序比较),但代码存在逻辑缺陷,具体分析如下:
数组定义:
char s[][100]={"hello","world","china"};
定义了一个二维字符数组,包含3个字符串:“hello”、“world”、“china”
计算行数:
int rows = sizeof(s)/sizeof(s[0]); // 结果为3,即有3个字符串
查找"最大"字符串的逻辑:
max
字符数组用于存储结果i=1
开始遍历数组(跳过了第一个元素s[0]
)strcmp
比较max
和s[i]
:
strcmp(max, s[i]) < 0
,表示s[i]
字典序大于max
strcpy
将s[i]
复制到max
中max
代码的关键缺陷是max
数组未初始化就直接使用:
max
中是随机的垃圾值strcmp(max, s[1])
时,是用随机值和"world"比较,结果不可控应先将第一个字符串s[0]
初始化给max
,再从第二个字符串开始比较:
char max[100];
strcpy(max, s[0]); // 先初始化max为第一个字符串
for(i=1; i<rows; ++i)
{
if(strcmp(max, s[i]) < 0) // 若当前字符串更大
{
strcpy(max, s[i]); // 更新max
}
}
strcmp
函数的比较规则:
对于示例中的三个字符串,正确的比较结果是"world"(最大),因为字典序:“china” < “hello” < “world”。
#include
int main(void) //二维字符型数组的逆序。
{
char s[][100]={"hello","world","china"};
int rows = sizeof(s)/sizeof(s[0]);
int i;
for(i=0;i
这段代码的功能是对二维字符数组中的字符串进行整体逆序排列(即交换数组中字符串的位置,使整个数组的顺序反转),具体逻辑如下:
通过对称交换二维字符数组中的字符串元素,将数组的整体顺序反转。例如,原数组为 ["hello", "world", "china"]
,逆序后变为 ["china", "world", "hello"]
。
数组定义与初始化:
char s[][100]={"hello","world","china"};
定义了一个二维字符数组,包含3个字符串:"hello"
、"world"
、"china"
,每个字符串最多可存储99个字符(加结束符\0
共100字节)。
计算字符串数量:
int rows = sizeof(s)/sizeof(s[0]); // 结果为3,即数组中有3个字符串
通过sizeof
计算数组总行数(字符串数量),sizeof(s)
是整个二维数组的总字节数,sizeof(s[0])
是单个字符串的字节数(100)。
逆序交换的核心逻辑:
for(i=0; i<rows/2; ++i) // 循环到数组中间位置
{
char t[100]; // 临时字符串,用于交换
strcpy(t, s[i]); // 步骤1:将s[i]复制到临时变量t
strcpy(s[i], s[rows-1-i]); // 步骤2:将对称位置的字符串复制到s[i]
strcpy(s[rows-1-i], t); // 步骤3:将临时变量t(原s[i])复制到对称位置
}
rows/2
),避免重复交换。对于3个元素的数组,rows/2
为1,即只需要交换1次。i
个字符串与第rows-1-i
个字符串互换(例如i=0
时,交换第1个和第3个字符串)。strcpy
函数复制字符串内容,因为直接赋值(如t = s[i]
)无法复制字符串内容(只会传递地址)。输出逆序后的结果:
for(i=0; i<rows; ++i)
{
puts(s[i]); // 逐个输出逆序后的字符串
}
原数组经过逆序后,输出结果为:
china
world
hello
strcpy
),不能直接用赋值运算符,因为字符数组名代表首地址,直接赋值会导致地址操作错误。i < rows/2
是高效实现的关键,确保每个元素只参与一次交换。这段代码通过对称交换的方式实现了二维字符数组的整体逆序,逻辑清晰且高效,时间复杂度为O(rows/2),适用于任意数量字符串的二维字符数组逆序场景。
#include
#include
int main(void)
{
char s[][100]={"hello","world","china"};
int rows = sizeof(s)/sizeof(s[0]); // 3个字符串
int i,j;
// 外层循环:控制排序轮次(共rows-1轮)
for(i=0;i s[j](字典序),则交换两者
if(strcmp(s[i],s[j])>0)
{
char t[100];
strcpy(t,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],t);
}
}
}
// 排序完成后,统一输出结果
for(i=0;i
这段代码实现了对二维字符数组中的字符串按字典序进行升序排序(从小到大排列),采用的是类似选择排序的思路,具体逻辑如下:
通过嵌套循环遍历二维字符数组,比较字符串的字典序,将较小的字符串交换到前面,最终使整个数组按字典序从小到大排列。
数组定义与初始化
char s[][100]={"hello","world","china"};
定义了一个二维字符数组,包含3个字符串:"hello"
、"world"
、"china"
,每个字符串最多可存储99个字符(加上结束符\0
共100字节)。
计算字符串数量
int rows = sizeof(s)/sizeof(s[0]); // 结果为3
通过sizeof
运算符计算数组中字符串的数量:
sizeof(s)
是整个二维数组的总字节数sizeof(s[0])
是单个字符串(一行)的字节数(100)排序核心逻辑
// 外层循环:控制排序轮次(共rows-1轮)
for(i=0;i<rows-1;++i)
{
// 内层循环:比较第i轮未排序的元素
for(j=i+1;j<rows;++j)
{
// 比较字符串字典序
if(strcmp(s[i],s[j])>0)
{
// 交换两个字符串
char t[100];
strcpy(t,s[i]);
strcpy(s[i],s[j]);
strcpy(s[j],t);
}
}
}
外层循环(i控制):从0到rows-2
(共2轮),每轮确定一个位置的元素
内层循环(j控制):从i+1
开始到数组末尾,负责与外层循环指定的位置元素进行比较
比较与交换:
strcmp(s[i], s[j])
比较两个字符串的字典序:
s[i]
的字典序大于s[j]
strcpy
函数复制字符串内容(不能直接用赋值运算符,因为字符数组名是地址)输出排序结果
for(i=0;i<rows;++i)
{
puts(s[i]);
}
排序完成后,遍历数组并输出每个字符串,结果为:
china
hello
world
(字典序规则:china
< hello
< world
)
strcmp
函数是核心,它按照ASCII码值逐个比较字符,直到遇到不同字符或结束符strcpy
函数复制整个字符串内容,不能直接用=
赋值(数组名是常量地址,不能被赋值)j=i+1
的设计减少了一半的比较次数,比简单的双重循环(j从0开始)更高效这段代码逻辑清晰,正确实现了二维字符数组的升序排序功能,对于理解字符串排序和二维数组操作很有帮助。
#include
int main(void) //二维字符型数组查找字符串:
{
char s[][100]={"hello","world","china"};
int rows = sizeof(s)/sizeof(s[0]);
int begin = 0;
int end=rows -1;
int mid;
char n[100];
scanf("%s",n);
while(begin<=end)
{
mid = (begin+end)/2;
if(strcmp(s[mid],n)<0)
{
begin=mid +1;
}
else if(strcmp(s[mid],n)>0)
{
end=mid-1;
}
else
{
break;
}
}
if(begin<=end)
{
printf("found\n");
}
else
{
printf("nofound\n");
}
return 0;
}
这段代码的意图是在二维字符数组中使用二分查找法查找指定字符串,但存在一个关键前提条件未满足,导致查找逻辑可能失效。具体分析如下:
代码尝试通过二分查找(折半查找) 算法在字符串数组中查找用户输入的目标字符串,基本流程是:
begin
为起始索引,end
为结束索引)数组定义与初始化
char s[][100]={"hello","world","china"};
定义了包含3个字符串的二维字符数组,初始值为"hello"
、"world"
、"china"
。
计算数组长度与初始化变量
int rows = sizeof(s)/sizeof(s[0]); // 结果为3(数组中有3个字符串)
int begin = 0; // 查找范围起始索引(初始为0)
int end = rows - 1; // 查找范围结束索引(初始为2)
int mid; // 中间位置索引
char n[100]; // 存储用户输入的目标字符串
获取用户输入
scanf("%s",n); // 读取用户输入的目标字符串
二分查找核心逻辑
while(begin <= end) // 当查找范围有效时循环
{
mid = (begin + end)/2; // 计算中间位置索引
// 比较中间字符串与目标字符串
if(strcmp(s[mid], n) < 0)
{
// 中间字符串字典序小于目标字符串,缩小左范围
begin = mid + 1;
}
else if(strcmp(s[mid], n) > 0)
{
// 中间字符串字典序大于目标字符串,缩小右范围
end = mid - 1;
}
else
{
// 找到目标字符串,跳出循环
break;
}
}
查找结果判断与输出
if(begin <= end)
{
printf("found\n"); // 找到目标(循环因break退出)
}
else
{
printf("nofound\n"); // 未找到目标(范围无效)
}
二分查找的前提条件是数组必须已按升序排序,但当前数组s
的初始顺序是["hello", "world", "china"]
,未按字典序排序(正确升序应为["china", "hello", "world"]
)。这会导致:
例如:若用户查找"china"
,由于初始数组无序,二分查找会错误判定为"nofound"。
要使这段代码正常工作,必须先确保二维字符数组已按字典序升序排列。修改数组初始化部分即可:
char s[][100]={"china","hello","world"}; // 已升序排序
此时查找任意存在的字符串(如"hello"
)会返回"found",查找不存在的字符串(如"test"
)会返回"nofound"。
代码实现了二分查找的基本逻辑,但忽略了二分查找对有序数组的依赖。在数组无序的情况下,查找结果不可靠;若数组已按字典序升序排列,则能高效(时间复杂度O(log n))地完成字符串查找。
int maxOfThreeNumbers(int a,int b,int c)
{
int max;
max=a>b?a:b;
max=max>c?max:c;
return max;
}
int main(void)
{
int max;
max=maxOfThreeNumbers(10,20,5);
printf("%d\n",max);
return 0;
}
这段代码的功能是定义一个函数用于求三个整数中的最大值,并在主函数中调用该函数进行测试,逻辑清晰且正确。具体分析如下:
maxOfThreeNumbers
该函数的作用是接收三个整数参数,返回其中的最大值,实现逻辑如下:
int maxOfThreeNumbers(int a, int b, int c)
{
int max;
// 第一步:比较a和b,将较大值存入max
max = a > b ? a : b;
// 第二步:比较max(a和b中的较大值)与c,更新max为三者中的最大值
max = max > c ? max : c;
return max; // 返回最大值
}
a
和b
中取较大值,再将这个较大值与c
比较,最终得到三个数中的最大值。condition ? expr1 : expr2
的作用:若condition
为真,返回expr1
;否则返回expr2
,适合简单的二选一逻辑。main
的执行流程主函数负责调用上述函数并输出结果,步骤如下:
int max;
用于存储函数返回的最大值。max = maxOfThreeNumbers(10, 20, 5);
10
、20
、5
,函数内部计算后返回最大值20
,并赋值给max
。printf("%d\n", max);
打印最大值20
。return 0;
表示程序正常退出。对于输入的三个数10
、20
、5
,函数的计算过程为:
10
和20
,max
暂存20
;20
和5
,max
保持20
;20
,主函数输出20
。函数的通用性:该函数不仅限于这三个数,对于任意三个整数(如-3
、0
、5
)都能正确返回最大值,体现了函数的复用性。
变量作用域:函数内部的max
与主函数中的max
是不同作用域的变量,互不干扰(函数内的max
仅在maxOfThreeNumbers
中有效,主函数的max
仅在main
中有效)。
这段代码通过函数封装了“求三数最大值”的逻辑,主函数负责调用和输出,结构清晰,符合模块化编程思想。核心逻辑利用三目运算符简化了比较过程,代码简洁高效,能正确处理任意三个整数的最大值求解。
int div3(int input)
{
int panduan;
panduan=input%3?0:1;
return panduan ;
}
int main(void)
{
int input;
scanf("%d",&input);
div3(input);
printf("%d\n",div3(input));
return 0;
}
这段代码的功能是判断一个整数是否能被3整除,并返回判断结果。具体逻辑分析如下:
div3
该函数用于判断输入的整数是否能被3整除,返回值为判断结果:
int div3(int input)
{
int panduan;
// 核心判断逻辑:利用取余运算
panduan = input % 3 ? 0 : 1;
return panduan;
}
input % 3
计算输入值除以3的余数。若能被3整除,余数为0;否则余数为非0值。input % 3 ? 0 : 1
的含义是:
input % 3
结果为非0(不能被3整除),则 panduan
赋值为0input % 3
结果为0(能被3整除),则 panduan
赋值为1main
的执行流程int input;
用于存储用户输入的整数。scanf("%d", &input);
读取用户从键盘输入的整数。div3(input);
:计算结果但未使用(此调用可省略,不影响最终输出)div3(input);
:将返回值作为printf
的参数,用于输出结果printf("%d\n", div3(input));
打印判断结果(1或0)。6
(能被3整除),函数返回1,输出 1
7
(不能被3整除),函数返回0,输出 0
代码中存在一次多余的函数调用 div3(input);
(仅调用未使用结果),可删除以提高效率,优化后的主函数如下:
int main(void)
{
int input;
scanf("%d", &input);
printf("%d\n", div3(input)); // 仅保留一次必要的调用
return 0;
}
这段代码通过封装判断逻辑到函数中,实现了“判断整数能否被3整除”的功能,逻辑清晰,利用取余运算和三目运算符使代码简洁高效。
int maxOfTwoNumbers(int a,int b)
{
int max;
max=a>b?a:b;
return max;
}
int maxOfThreeNumbers(int a,int b,int c)
{
int max;
max=a>b?a:b;
max=max>c?max:c;
return max;
}
int main(void)
{
int max;
max=maxOfThreeNumbers(10,20,maxOfTwoNumbers(29,39));
printf("%d\n",max);
return 0;
}
这段代码的功能是通过嵌套调用函数来求解多个数中的最大值,具体逻辑如下:
maxOfTwoNumbers
函数:
int maxOfTwoNumbers(int a, int b)
{
int max;
max = a > b ? a : b; // 三目运算符比较a和b,取较大值
return max;
}
功能:接收两个整数参数,返回其中的最大值。
maxOfThreeNumbers
函数:
int maxOfThreeNumbers(int a, int b, int c)
{
int max;
max = a > b ? a : b; // 先比较a和b,取较大值
max = max > c ? max : c; // 再用前一步结果与c比较,取最大值
return max;
}
功能:接收三个整数参数,返回其中的最大值。
main
的执行流程函数嵌套调用:
max = maxOfThreeNumbers(10, 20, maxOfTwoNumbers(29, 39));
执行顺序是从内到外:
maxOfTwoNumbers(29, 39)
:maxOfThreeNumbers(10, 20, 39)
:结果输出:
printf("%d\n", max); // 输出变量max的值39
maxOfTwoNumbers
的返回值作为maxOfThreeNumbers
的第三个参数,实现了“求四个数(10、20、29、39)中最大值”的效果。maxOfTwoNumbers
函数被嵌套调用,体现了函数的可复用性,避免了代码重复。这段代码展示了函数嵌套调用的用法,能够灵活处理多个数值的最大值求解,逻辑简洁且高效。
int year(int n)
{
return(n%4==0&&n%100!=0||n%400==0);
}
void print(int a,int b)
{
int i;
for(i=a;i<=b;++i)
{
if( year(i) )
{
printf("%d\n",i);
}
}
}
int main(void)
{
print(1900,2100);
return 0;
}
这段代码的功能是判断并打印指定年份范围内的所有闰年,具体逻辑如下:
year
函数:
int year(int n)
{
return (n%4==0 && n%100!=0 || n%400==0);
}
功能:判断一个年份是否为闰年,返回判断结果(1表示是闰年,0表示不是)。
闰年判断规则(通过逻辑表达式实现):
(n%4==0 && n%100!=0 || n%400==0)
完美体现了这一规则,结果为真(非0)时返回1,为假时返回0。print
函数:
void print(int a,int b)
{
int i;
for(i=a;i<=b;++i) // 遍历从a到b的所有年份
{
if( year(i) ) // 调用year函数判断是否为闰年
{
printf("%d\n",i); // 是闰年则打印该年份
}
}
}
功能:接收两个参数(起始年份a
和结束年份b
),遍历该范围内的所有年份,调用year
函数判断并打印其中的闰年。
main
的执行流程int main(void)
{
print(1900,2100); // 调用print函数,打印1900到2100年之间的闰年
return 0;
}
print
函数,传入参数1900
和2100
,指定要查询的年份范围。print
函数负责具体的遍历和判断工作,最终在控制台输出1900到2100年间所有的闰年。year
函数通过一个逻辑表达式即可完成闰年判断,高效且易读。print
函数通过参数接收年份范围,可灵活查询任意区间的闰年,不限于1900-2100。这段代码正确实现了闰年判断的逻辑,通过函数分工使代码结构清晰,能够准确输出指定范围内的所有闰年。
#include
int min(int a,int b)
{
int minmin;
if(a==0&&b==0)
{
printf("这两个数无最大公约数\n");
return -1;
}
else if(a==0||b==0)
{ minmin=a==0?abs(b):abs(a);
return minmin;
}
else
{
int ava=abs(a);
int avb=abs(b);
minmin=ava>avb?avb:ava;
return minmin;
}
}
int GCD(int a,int b)
{
int mm=min(a,b);
int i;
for(i=mm;i>0;--i)
{
if(a%i==0&&b%i==0)
{
printf("能找到最大公约数:%d\n",i);
break;
}
}//注释:两个非0整数(不管正负),必能找到它们的最大公约数。
}
int main(void)
{
int a,b;
printf("请输入两个数字:\n");
scanf("%d%d",&a,&b);
GCD(a,b);
return 0;
}
这段代码的功能是计算并输出两个整数的最大公约数(GCD),整体逻辑分为函数分工协作完成,具体分析如下:
min
函数:预处理输入的两个数,确定公约数的查找范围
int min(int a, int b)
{
int minmin;
// 情况1:两数均为0,无最大公约数
if(a==0 && b==0)
{
printf("这两个数无最大公约数\n");
return -1;
}
// 情况2:其中一个数为0,另一个数的绝对值即为最大公约数
else if(a==0 || b==0)
{
minmin = a==0 ? abs(b) : abs(a); // 三目运算符简化判断
return minmin;
}
// 情况3:两数均非0,返回两数绝对值中的较小值(作为查找上限)
else
{
int ava = abs(a); // 取绝对值,处理负数情况
int avb = abs(b);
minmin = ava > avb ? avb : ava; // 取较小值
return minmin;
}
}
abs
函数取绝对值,确保负数不影响公约数计算(公约数与正负无关)。GCD
函数:查找并输出最大公约数
int GCD(int a, int b)
{
int mm = min(a, b); // 调用min函数获取查找上限或特殊情况结果
int i;
// 从上限mm向下遍历,找到第一个能同时整除两数的数(即最大公约数)
for(i = mm; i > 0; --i)
{
if(a % i == 0 && b % i == 0)
{
printf("能找到最大公约数:%d\n", i);
break; // 找到后立即退出循环
}
}
}
a
和b
的数就是最大公约数,确保高效性。min
函数的返回值:mm
要么是查找上限(两数绝对值较小者),要么是0的特殊情况中有效的那个数的绝对值。main
的执行流程int main(void)
{
int a, b;
printf("请输入两个数字:\n");
scanf("%d%d", &a, &b); // 获取用户输入的两个整数
GCD(a, b); // 调用GCD函数计算并输出最大公约数
return 0;
}
GCD
处理,无需额外逻辑。两数均为0:
min
函数输出“这两个数无最大公约数”,GCD
函数中的循环不执行(mm=-1
,循环条件i>0
不满足)。
其中一个数为0:
例如输入0
和6
,min
函数返回6
(abs(6)
),GCD
函数循环中i=6
时满足0%6==0 && 6%6==0
,输出“能找到最大公约数:6”。
两数均非0(含负数):
例如输入-12
和18
:
min
函数取绝对值后为12
和18
,返回较小值12
;GCD
函数从12
向下遍历,第一个能同时整除-12
和18
的数是6
,输出结果为6。优点:
min
预处理,GCD
查找),结构清晰。可优化点:
GCD
函数未定义返回值(实际应返回找到的公约数),虽然当前仅打印结果,但返回值可增强函数复用性;这段代码通过min
和GCD
函数协作,完整实现了两个整数的最大公约数求解,涵盖了特殊情况(含0、负数)的处理,逻辑正确且实用。核心思路是“确定查找范围→从大到小遍历验证”,适合理解最大公约数的基本求解逻辑。
#include
#include // 用于abs函数
// 计算最大公约数(辅助函数)
int gcd(int a, int b) {
a = abs(a); // 取绝对值,处理负数
b = abs(b);
// 辗转相除法求最大公约数
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
// 计算最小公倍数
int lcm(int a, int b) {
// 检查是否有零输入
if (a == 0 || b == 0) {
printf("错误:输入不能为零,最小公倍数无意义\n");
return -1;
}
// 利用公式:最小公倍数 = 两数乘积的绝对值 / 最大公约数
int abs_product = abs(a) * abs(b); // 先计算乘积的绝对值
int common_divisor = gcd(a, b); // 获取最大公约数
int result = abs_product / common_divisor; // 计算最小公倍数
printf("最小公倍数是:%d\n", result);
return result;
}
int main(void) {
int a, b;
printf("请输入两个整数(用空格分隔):");
scanf("%d %d", &a, &b);
lcm(a, b); // 调用函数计算并输出结果
return 0;
}
int isLeapyear(int year)
{
return (year%4==0&&year%100!=0||year%400==0);
}
int daysOfTheMonth(int year,int month)
{
int a[]={31,0,31,30,31,30,31,31,30,31,30,31};
if(month<=0||month>=12)
{
return -1;
}
if(month!=2)
{
return a[month-1];
}
else
{
return isLeapyear(year)?29:28;
}
}
int main(void)
{
int year,month;
printf("请输入要确认天数的年月\n");
scanf("%d%d",&year,&month);
int ret;
ret=daysOfTheMonth(year,month);
if(ret<0)
{
puts("error");
}
else
{
printf("%d\n",daysOfTheMonth(year,month));
}
return 0;
}