这里是刚考完c语言期中考试的Mikazsuki,考试中被一道复习了很久的双重循环的类金字塔题型的编程题硬控了40分钟,任凭我抓耳挠腮也想不出解法,最后只能作罢。考完试后瞬间就明白了如何解决,故写这篇博客,固定一下我想到的两种其他方法以及最标准的解法。
1.题目
题目很简单,要求输入一个大于0小于等于9的正整数n ,按如下的顺序输出。唉,牢油条肯定想到这用双重循环可以秒杀了!但对于我这个c语言菜鸟来说,请听我娓娓道来。
1
12
123
1234
......2.考场上想到的方法
我们都知道c语言中存在一个标准库string.h ,其中包含了一个叫做strcat(str,src) 的函数,它可以将src 拼接到str 的末尾。但这个函数只能实现字符串的拼接,当时就是在这里吃了亏,一直编译错误。后面询问了AI才知道解法,总结就是将取出来的单个字符装进一个带有\0 的数组里面,伪装成一个长度为1 的字符串,然后再使用strcat 函数进行拼接。代码实现如下:
#include <stdio.h>
#include <string.h> // strcat函数在这里面
int main() {
int n;
scanf("%d", &n);
if (n < 1 || n > 9) return 0;
// 1. 直接用字符串形式定义最方便,但当时没想到可以这样实现
char arr[10] = "123456789";
// 2. 准备一个空字符串,作为最终拼接的底板
char result[15] = "";
// 3. 这种方法的好处是只有一次循环,i 代表去arr[10]这个字符串数组中拿第几个字符
for (int i = 0; i < n; i++) {
// 这一步是我没想到的:把取出来的单个字符 arr[i] 包装成字符串
// temp[0] 放取出的字符,temp[1] 放 '\0' 充当结束符
char temp[2] = {arr[i], '\0'};
// 现在 temp 是一个合法的字符串了,安全地拼接到 result 尾部
strcat(result, temp);
// 打印出当前拼接好的进度
printf("%s\n", result);
}
return 0;
}运转逻辑也很简单,假设我们输入n=3 ,那么在准备阶段,我们定义了arr = "123456789"(指代为“仓库”), result = "" ,接下来会有三层循环:
第 1 次循环 (i=0):
去仓库拿 arr[0],也就是 '1'。
包装成临时字符串 temp = "1"。
strcat 把 "1" 拼接到 result 后面 result 变成 "1"。
打印:1
第 2 次循环 (i=1):
去仓库拿 arr[1],也就是 '2'。
包装成临时字符串 temp = "2"。
strcat 把 "2" 拼接到现在的 "1" 后面 result 变成 "12"。
打印:12
第 3 次循环 (i=2):
仓库拿 arr[2],也就是 '3'。
包装成临时字符串 temp = "3"。
strcat 把 "3" 拼接到 "12" 后面 result 变成 "123"。
打印:123
可见,这种方法虽然只需要使用一次循环,但实现起来是较为麻烦且很容易出错的。
3.AI提供的使用字符串数组的解决方法
这个方法我认为比上个方法更加复杂,仅仅贴出来供参考
1. 怎么定义和存入这 9 个字符?
有两种标准的写法:
写法一:逐个字符存入(最标准的基础写法)
char arr[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
// 此时 arr[0] 是 '1',arr[8] 是 '9'
写法二:用字符串直接存入(更省事,但要注意隐藏的 \0)
char arr[10] = "123456789";
// 为什么开 10 个格子?因为双引号会自动在最后加一个 '\0'!
// arr[0] 依然是 '1',arr[8] 依然是 '9'
2. 怎么用 i 控制取出来?
注意:数组的下标永远是从 0 开始的!
如果想取出第 1 个字符 '1',要用 arr[0]。
如果想取出第 n 个字符,要用 arr[n-1]。
基本遍历演示:
#include <stdio.h>
int main() {
char arr[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
// 用 i 从 0 循环到 8,把它们依次取出来
for(int i = 0; i < 9; i++) {
// 注意打印字符要用 %c
printf("下标 %d 里面装的是: %c\n", i, arr[i]);
}
return 0;
}
实际使用:用这个数组完成 1 12 123 的打印任务
如果用这个“查表”的思路来做刚才那道题,代码会变得非常直观。我们依然需要双重循环:外层循环控制行数。内层循环去数组里“拿”字符并打印。
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
if (n < 1 || n > 9) return 0;
// 1. 定义我们的“字符仓库”
char arr[9] = {'1', '2', '3', '4', '5', '6', '7', '8', '9'};
// 2. 外层循环:控制行数 (比如输入 3,就循环 3 次)
for (int i = 1; i <= n; i++) {
// 3. 内层循环:负责去仓库里拿字符
// 比如第 3 行,我们需要去拿仓库里前 3 个字符(即下标 0, 1, 2)
// 所以 j 从 0 开始,走到 i-1 结束
for (int j = 0; j < i; j++) {
printf("%c", arr[j]);
}
// 拿完这一行的字符后,换行
printf("\n");
}
return 0;
}
【考点总结】
当用这种方法时,一定要在草稿纸上画一下映射关系,千万别让下标越界:
第 1 行 需打印 1 个数 需要取数组的 arr[0]
第 2 行 需打印 2 个数 需要取数组的 arr[0], arr[1]
第 i 行 需打印 i 个数 需要取数组的 arr[0] 一直到 arr[i-1]
4.最标准也是最简单的双重循环解决方法
下面这种方法才是真正的标准答案。
#include <stdio.h>
int main() {
int n = 0;
scanf("%d", &n);//输入需要打印的行数
for (int i = 1; i <= n; i++) { //外层循环,控制打印到第i行
for (int j = 1; j <= i; j++) { //内层循环,控制第i行内要将1~j打印出来
printf("%d",j);
}
printf("\n");//循环结束后打印换行符,合乎题目的评判要求
}
return 0;
}5.评论区提供的方法补充
感谢@鱿鱼总会败北 提供的新方法!在这里分享出来供读者思考!
思路很简单:使用单层for循环,以i=1为初始,用临时变量t储存本次输出的数乘以10;当i=2时,输出t+i=12; 当i=3时,t+=i即120+3=123。
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int t = 0;
for(int i = 1; i <= n; i++)
{
t = t * 10 + i; // 核心公式:1→12→123→...
printf("%d\n", t);
}
return 0;
}6.总结
这次总结下来,发现在设计算法方面,很容易复杂化,归根结底是对双重循环的知识不牢固。反正博主这12.5分已经没有了,希望整理出来的资料可以对读者有所裨益。感谢阅读!
