
java和c使用教程:新手完成第一张作品的方法
第一次学编程,不一定要从复杂的计算器或网页开始。把字符放到指定位置,画出一间小房子,既能得到一件看得见的“作品”,也能练习变量、数组、循环、函数和编译运行。
本文用同一个目标分别编写 Java 和 C 程序:在终端绘制一幅字符画。程序不依赖图形库,不需要联网,也不读写文件。只要安装相应的开发工具,就能复制代码、编译并运行。
一、先明确这类作品适合什么场景
这里的“作品”是一张由普通字符组成的终端图案,不是 PNG 图片,也不是带窗口的图形界面。它适合用来:
- 练习程序的基本结构,以及如何编译、运行代码;
- 理解二维数组、行列坐标和循环;
- 快速验证环境是否配置成功;
- 制作简单的命令行标识、边框或文字布局。
它不适合直接代替专业绘图软件,也不会自动生成高分辨率图片。终端字体、字符宽度和窗口尺寸可能影响图案观感。尤其是中文字符在不同环境中的显示宽度不一定一致,所以示例只用 ASCII 字符。
二、开始前准备
Java 环境
先安装 JDK。在终端或命令提示符中执行 java -version 和 javac -version,确认运行环境与编译器可用。下面的程序使用基础语法,适用于常见的现代 JDK。
C 环境
需要一个 C 编译器,例如 GCC 或 Clang。执行 gcc --version 可以检查 GCC 是否可用。示例采用 C11 常见语法,不调用操作系统接口。
请把 Java 和 C 代码分别保存为文件,不要放进同一个源文件:Java 文件名为 Main.java,C 文件名可用 house.c。
三、先理解画布与坐标
程序会创建一个宽 15 个字符、高 10 行的画布。可以把它想成一张表格:左上角是坐标 (0, 0),向右增加的是列坐标 x,向下增加的是行坐标 y。因此,合法位置满足:
0 <= x < 150 <= y < 10
数组下标从 0 开始,是新手常见的混淆点。宽度为 15 的画布,最后一列下标是 14,而不是 15。示例中的 putPixel 函数会先检查坐标是否在范围内;超出范围时直接忽略,避免访问画布以外的位置。
这里的“像素”只是便于理解的叫法:每个位置存放一个字符,并不是真正的屏幕像素。
四、Java 版本:用二维字符数组画房子
把下面代码保存为 Main.java。程序先用空格填满画布,再画屋顶、墙体、窗户和门,最后逐行输出。
public class Main {
private static final int WIDTH = 15;
private static final int HEIGHT = 10;
private static void putPixel(char[][] canvas, int x, int y, char ch) {
if (y >= 0 && y < canvas.length
&& x >= 0 && x < canvas[y].length) {
canvas[y][x] = ch;
}
}
public static void main(String[] args) {
char[][] canvas = new char[HEIGHT][WIDTH];
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
canvas[y][x] = ' ';
}
}
// 屋顶两侧
for (int i = 0; i <= 4; i++) {
putPixel(canvas, 7 - i, i, '/');
putPixel(canvas, 7 + i, i, '\\');
}
// 墙体顶部、左右墙和底边
for (int x = 3; x <= 11; x++) {
putPixel(canvas, x, 4, '-');
putPixel(canvas, x, 9, '-');
}
for (int y = 5; y <= 9; y++) {
putPixel(canvas, 3, y, '|');
putPixel(canvas, 11, y, '|');
}
// 窗户
putPixel(canvas, 5, 6, '+');
putPixel(canvas, 6, 6, '-');
putPixel(canvas, 7, 6, '+');
putPixel(canvas, 5, 7, '|');
putPixel(canvas, 6, 7, ' ');
putPixel(canvas, 7, 7, '|');
// 门
putPixel(canvas, 8, 7, '+');
putPixel(canvas, 9, 7, '-');
putPixel(canvas, 10, 7, '+');
putPixel(canvas, 8, 8, '|');
putPixel(canvas, 10, 8, '|');
// 输出画布
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
System.out.print(canvas[y][x]);
}
System.out.println();
}
}
}
在 Main.java 所在目录打开终端,执行:
javac Main.java
java Main
javac 负责编译,java 负责运行。类名是 Main,所以源文件应命名为 Main.java。若收到“找不到符号”或类名错误,先检查文件名、大小写和当前目录。
五、C 版本:使用固定大小的二维数组
把下面代码保存为 house.c。绘制步骤与 Java 版本相同。C 中的画布是一个固定大小的字符数组,put_pixel 在写入之前检查坐标范围。
#include <stdio.h>
#define WIDTH 15
#define HEIGHT 10
static void put_pixel(char canvas[HEIGHT][WIDTH],
int x, int y, char ch) {
if (x >= 0 && x < WIDTH
&& y >= 0 && y < HEIGHT) {
canvas[y][x] = ch;
}
}
int main(void) {
char canvas[HEIGHT][WIDTH];
// 用空格清空画布
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
canvas[y][x] = ' ';
}
}
// 屋顶两侧
for (int i = 0; i <= 4; i++) {
put_pixel(canvas, 7 - i, i, '/');
put_pixel(canvas, 7 + i, i, '\\');
}
// 墙体顶部、左右墙和底边
for (int x = 3; x <= 11; x++) {
put_pixel(canvas, x, 4, '-');
put_pixel(canvas, x, 9, '-');
}
for (int y = 5; y <= 9; y++) {
put_pixel(canvas, 3, y, '|');
put_pixel(canvas, 11, y, '|');
}
// 窗户
put_pixel(canvas, 5, 6, '+');
put_pixel(canvas, 6, 6, '-');
put_pixel(canvas, 7, 6, '+');
put_pixel(canvas, 5, 7, '|');
put_pixel(canvas, 6, 7, ' ');
put_pixel(canvas, 7, 7, '|');
// 门
put_pixel(canvas, 8, 7, '+');
put_pixel(canvas, 9, 7, '-');
put_pixel(canvas, 10, 7, '+');
put_pixel(canvas, 8, 8, '|');
put_pixel(canvas, 10, 8, '|');
// 输出画布
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
putchar(canvas[y][x]);
}
putchar('\n');
}
return 0;
}
在终端中进入 house.c 所在目录,使用 GCC 编译并运行:
gcc -std=c11 -Wall -Wextra -pedantic house.c -o house
./house
在 Windows 命令提示符中,编译命令可用 gcc -std=c11 -Wall -Wextra -pedantic house.c -o house.exe,然后执行 house.exe。不同编译器对命令选项和可执行文件后缀的处理可能不同;如果使用 Clang,把命令中的 gcc 换成 clang 即可。
六、两种语言的代码分别做了什么
1. 创建画布并初始化
Java 的 char[][] 和 C 的二维字符数组都按“行、列”保存字符。代码把每个位置都设为空格。初始化很重要:如果没有这一步,画布中可能出现默认值或未按预期设置的内容,输出就会不整齐。
Java 新建字符数组时,元素默认值是空字符 '\u0000',并不是普通空格;C 的局部数组也不能假设已经自动填成空格。因此两个版本都明确初始化。
2. 按坐标放置字符
putPixel 和 put_pixel 把“检查坐标并写入字符”封装起来。以 Java 为例,访问 canvas[y][x] 时,必须先保证行和列有效;C 也必须避免数组越界。C 数组访问越界可能导致未定义行为,程序结果不可依赖,甚至可能造成安全问题。
坐标检查只保护这两个函数里的画布写入,并不意味着任意 C 程序都因此安全。真实项目还需要检查数据来源、数组长度、字符串操作和其他内存访问。
3. 用循环画重复结构
屋顶每一层都向两侧扩展一格,所以用 i 表示层数,分别在 7 - i 和 7 + i 的位置画斜线。墙体上下边则通过循环重复放置横线。把重复操作交给循环,可以减少重复代码,也能看出图案与坐标之间的关系。
4. 按行输出
内层循环从左到右输出一行,外层循环从上到下处理每一行。Java 使用 System.out.print 输出字符,完成一行后用 println 换行;C 使用 putchar 输出字符和换行符。
七、如何把图案改成自己的设计
- 改字符:将屋顶的
/、\换成其他 ASCII 字符;把墙壁的|换成#或!。 - 改位置:修改传给放置函数的
x、y坐标。每次改动后注意图案不要超出画布。 - 改画布:Java 修改
WIDTH和HEIGHT;C 修改#define的值。扩大画布后,应重新检查图案坐标。 - 增加细节:先确定窗户、烟囱或树的坐标,再逐行调用放置函数。画布可以重复写入同一位置,后写入的字符会覆盖先前的字符。
目前画布大小由代码固定,不接受用户输入。这样可以让第一个示例保持简单,也避免新手在还没学会输入校验时就处理任意尺寸。若之后要让用户输入宽高,需要检查输入是否成功,并设置合理的范围;分配动态内存时,还要验证计算出的容量没有溢出,并保证分配和释放正确。
八、新手常见错误及排查方法
坐标写反
二维数组通常先写行、再写列,也就是 canvas[y][x]。如果误写成 canvas[x][y],图案可能转置;当宽和高不相等时,还可能越界。记住:横向是 x,纵向是 y。
把边界当成有效位置
宽度为 15 时,列坐标是 0 到 14;高度为 10 时,行坐标是 0 到 9。循环条件应使用小于号,例如 x < WIDTH,不应写成 x <= WIDTH。后一种写法会多访问一个不存在的位置。
反斜杠没有正确转义
在 Java 和 C 字符串、字符常量中,反斜杠用于引入转义序列。要表示一个实际的反斜杠字符,代码需要写成 '\\'。如果只写一个反斜杠,编译器可能报告语法错误,或把后面的字符解释为转义内容。
输出看起来没有换行
应在每行末尾输出换行。Java 示例在每行使用 System.out.println(),C 示例使用 putchar('\n')。如果误把换行放进内层循环,每个字符都会换行,作品就会变成一列。
编译命令在错误目录执行
编译器会根据当前工作目录查找源文件。若提示文件不存在,先用 cd 进入文件所在目录,或在命令中提供正确路径。文件名大小写也应与实际名称一致。
混淆编译和运行
Java 需要先用 javac 编译,再用 java 按类名运行;C 则先由编译器生成可执行文件,再运行该文件。两种语言的命令形式不同,不能把 Java 的 java Main 用于运行 C 源文件。
九、参数限制与安全边界
示例的宽、高是固定常量:Java 中分别为 15 和 10,C 中通过宏定义指定。代码没有读取命令行参数或用户输入,因此不涉及对外部输入的解析。画布很小,适合练习;这不代表任意增大尺寸都没有代价。
Java 数组受可用内存与数组实现限制,创建过大的数组可能导致内存不足。C 示例把固定数组放在函数局部,尺寸扩大后会增加局部存储需求;具体限制取决于运行环境,不能把很大的数组照搬到局部栈空间。需要大画布时,应结合目标平台和内存管理方式设计,而不是简单地把常量改成极大数值。
程序只在终端输出字符,没有文件、网络、系统命令或权限操作。它不能用来防病毒、加密数据、保护账户,也不构成安全控制。学习和运行代码仍应遵守常规习惯:只编译自己理解或信任来源的源码,不要为了运行陌生示例而随意使用管理员权限。
十、完成后的下一步
运行成功后,先尝试移动一扇窗或修改屋顶字符,再新增一个烟囱。每次只改一处,编译并观察结果,这比整段代码一起改更容易定位问题。熟悉坐标和循环后,可以练习让图案根据参数变化,或将字符画保存到文件;这些都需要额外处理输入范围、文件错误和资源管理。
这张小房子虽然简单,但已经包含了一个完整程序的基本流程:创建数据、初始化内容、按规则修改数据、检查访问边界并输出结果。把这些步骤弄明白,就是开始使用 Java 和 C 制作程序作品的可靠起点。









