news 2026/5/8 22:05:19

PTA L1-039 古风排版:用C语言二维数组模拟竖排文字,保姆级图解教程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PTA L1-039 古风排版:用C语言二维数组模拟竖排文字,保姆级图解教程

PTA L1-039 古风排版:二维数组与文字竖排的艺术

第一次看到古风排版题目时,我盯着那个"asa T st ih e tsi ce s"的输出样例发了十分钟呆。作为习惯了从左到右阅读的现代人,要理解这种从右向左、从上到下的文字排列方式,确实需要一些思维转换。不过当我用二维数组模拟出整个过程后,一切都变得清晰起来。

1. 理解古风排版的本质

古风排版的核心在于文字排列方向的改变。现代排版是水平方向优先,而古代排版则是垂直方向优先。这种差异直接影响了我们处理字符串的方式。

关键特征:

  • 文字从右向左排列(列顺序)
  • 每列的文字从上向下排列(行顺序)
  • 最后一列可能不足N个字符时需要补空格

举个例子,对于输入"Hello World"(N=3),应该这样思考:

H e l l o W o r l d

我们需要把这个字符串按3行分割后,从右向左排列:

原字符串分段: Hel lo Wor ld 竖排后: l oW lo H d

2. 二维数组的结构设计

用二维数组模拟这种排版,关键在于确定数组的行列关系。这里有一个思维转换:

  • 数组的行数= 用户输入的N(每列字符数)
  • 数组的列数= ceil(字符串长度 / N)
int len = strlen(input_str); int cols = len / rows; if (len % rows != 0) { cols++; // 不能整除时需要额外一列 }

这个计算确保了即使字符串长度不是N的整数倍,我们也有足够的空间存储所有字符(最后一列不足的部分用空格填充)。

3. 填充算法的逆向思维

最让初学者困惑的是填充顺序——为什么要从最后一列开始?让我们用ASCII图示来说明:

假设输入是"This is a test case",N=4:

原始字符串索引: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 T h i s i s a t e s t c a s e

我们需要创建一个4行x5列的数组(因为18个字符/4行=4.5→5列),填充顺序如下:

列号: 4 3 2 1 0 --------------------- 行0 | a | s | a | | T | 行1 | s | t | | i | h | 行2 | e | | t | s | i | 行3 | | c | s | | e |

对应的填充代码:

char grid[100][100] = {0}; int index = 0; for (int col = cols - 1; col >= 0; col--) { for (int row = 0; row < rows; row++) { if (input_str[index] != '\0') { grid[row][col] = input_str[index++]; } else { grid[row][col] = ' '; // 不足部分补空格 } } }

4. 调试技巧与常见陷阱

在实现这个算法时,我踩过几个典型的坑:

  1. 数组越界:没有正确计算列数导致访问非法内存

    • 解决方法:打印中间计算结果验证
    printf("字符串长度=%d, 需要列数=%d\n", len, cols);
  2. 空格处理:忘记处理最后一列不足时的空格补全

    • 关键检查:
    if (input_str[index] != '\0') { // 正常赋值 } else { // 补空格 }
  3. 填充顺序混淆:误从左到右填充导致顺序错误

    • 记忆技巧:想象真的在竹简上写字,从最右侧开始

调试时可以打印中间状态:

// 在填充循环内加入调试输出 printf("填充 col=%d, row=%d, char=%c\n", col, row, grid[row][col]);

5. 完整代码实现与优化

结合上述分析,这是经过优化的完整实现:

#include <stdio.h> #include <string.h> #define MAX_STR 1001 #define MAX_GRID 100 int main() { int rows; scanf("%d ", &rows); // 注意空格吸收换行 char input_str[MAX_STR]; fgets(input_str, MAX_STR, stdin); input_str[strcspn(input_str, "\n")] = '\0'; // 去除换行符 int len = strlen(input_str); int cols = len / rows; if (len % rows != 0) cols++; char grid[MAX_GRID][MAX_GRID] = {0}; int index = 0; // 从右向左填充列 for (int col = cols - 1; col >= 0; col--) { for (int row = 0; row < rows; row++) { grid[row][col] = (index < len) ? input_str[index++] : ' '; } } // 输出结果 for (int row = 0; row < rows; row++) { for (int col = 0; col < cols; col++) { putchar(grid[row][col]); } putchar('\n'); } return 0; }

优化点:

  1. 使用fgets替代不安全的gets
  2. 用三元运算符简化条件判断
  3. 添加了数组大小宏定义,提高可维护性
  4. 更安全的换行符处理

6. 可视化理解工具

为了更直观地理解这个过程,我设计了一个简单的文本可视化方法:

void visualize_filling(int rows, int cols, const char grid[][MAX_GRID]) { printf("\n填充过程可视化:\n"); for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { printf("%2d:%-2c ", i * cols + j, grid[i][j]); } printf("\n"); } }

调用这个函数可以看到字符是如何被填入二维数组的,对于调试特别有帮助。

7. 性能分析与扩展思考

虽然这个问题规模很小(N<100,字符串<1000),但思考优化方案是很好的练习:

  1. 空间优化:可以直接计算输出位置,不需要二维数组
    • 公式:输出字符位置 = (cols - 1 - col) * rows + row
  2. 边界情况
    • 空字符串输入
    • N=1的情况(变成简单的字符串反转)
    • N大于字符串长度的情况

尝试实现这些优化是理解算法本质的好方法。比如无二维数组版本:

for (int row = 0; row < rows; row++) { for (int col = cols - 1; col >= 0; col--) { int index = col * rows + row; putchar(index < len ? input_str[index] : ' '); } putchar('\n'); }

这种实现直接计算字符位置,节省了O(N²)的空间,但可读性稍差。在算法竞赛中,这种优化往往很有价值。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/8 22:05:18

程序员的中年危机不是年龄,而是“技能负债”

在软件测试这个领域&#xff0c;我们每天都在和“缺陷”打交道。我们擅长发现系统的漏洞、逻辑的断裂、性能的瓶颈&#xff0c;却很少有机会停下来审视自己职业生涯中那些悄然累积的“隐性缺陷”。当“中年危机”这个词像幽灵一样盘旋在每一个三十岁之后的测试工程师头顶时&…

作者头像 李华
网站建设 2026/5/8 22:04:29

304不锈钢螺杆锁止棒 | 莱图加工程师实录

上海裕诗实业发来这张图纸&#xff0c;零件名叫螺杆锁止棒&#xff08;Leadscrew锁止杆&#xff09;&#xff0c;材质304不锈钢&#xff0c;数量1件。图纸比例1:1&#xff0c;效果图一看就明白——这是一根细长杆顶着一个圆饼底座的"T形"结构&#xff0c;整体光滑&am…

作者头像 李华
网站建设 2026/5/8 21:44:31

芯片低功耗设计实战:从概念到签核的全流程解析与避坑指南

1. 低功耗设计&#xff1a;一个被营销文案耽误的宝藏作为一名在芯片设计领域摸爬滚打了十几年的工程师&#xff0c;我见过太多“金玉其外&#xff0c;败絮其中”的技术资料&#xff0c;也见过不少“其貌不扬&#xff0c;内藏乾坤”的干货。今天想聊的&#xff0c;就是后者——一…

作者头像 李华
网站建设 2026/5/8 21:42:32

RV1126双摄IMX577驱动移植避坑指南:从RK3588源码到稳定运行的完整流程

RV1126双摄IMX577驱动移植实战&#xff1a;从RK3588源码到稳定运行的避坑全流程 在嵌入式视觉系统开发中&#xff0c;Rockchip RV1126凭借其出色的图像处理能力和低功耗特性&#xff0c;成为智能摄像头、工业检测等场景的热门选择。而索尼IMX577作为一款高性能1200万像素传感器…

作者头像 李华
网站建设 2026/5/8 21:38:07

速看|营销智脑 V6 本周上线,四大维度焕新,解锁全域营销新玩法

在 AI 技术飞速迭代的当下&#xff0c;人人都在谈AI商业化&#xff0c;却很少有人真正看透其底层逻辑。从通用大模型横空出世&#xff0c;到各行各业落地AI应用&#xff0c;看似纷繁复杂的技术变革、商业转型&#xff0c;归根结底只在做一件事&#xff1a;把人类漫长积累的认知…

作者头像 李华
网站建设 2026/5/8 21:36:53

最后30天,PMP救命冲刺法:我是如何在考前一个月提分40%的

大家好&#xff0c;我是一个去年刚考过PMP的过来人。前几天有人问我&#xff1a;“距离6月14日PMP考试只有一个月了&#xff0c;我才刚开始看PMBOK第七版&#xff0c;但越看越困&#xff0c;还有戏吗&#xff1f;”说实话&#xff0c;我看见这条消息的时候&#xff0c;恍惚间看…

作者头像 李华