目录
1.8 使用 C 语言的 7 个步骤
1.8.1 第 1 步:定义程序的目标
1.8.2 第 2 步:设计程序
1.8.3 第 3 步:编写代码
1.8.4 第 4 步:编译
1.8.5 第 5 步:运行程序
1.8.6 第 6 步:测试和调试程序
1.8.7 第 7 步:维护和修改代码
1.8.8 说明
1.8 使用 C 语言的 7 个步骤
C 是编译型语言。如果之前使用过编译型语言(如,Pascal、FORTRAN),就会很熟悉组建 C 程序的几个基本步骤。但是,如果以前使用的是解释型语言(如,BASIC、Python、JavaScript)或面向图形界面语言(如,Visual Basic),或者甚至没接触过任何编程语言,就有必要学习如何编译。别担心,这并不复杂。
首先,为了让读者对编程有大概的了解,我们把编写 C 程序的过程分解成 7 个步骤(见图1.3)。
注意,这是理想状态。在实际的使用过程中,尤其是在较大型的项目中,可能要做一些重复的工作,根据下一个步骤的情况来调整或改进上一个步骤。
1.8.1 第 1 步:定义程序的目标
在动手写程序之前,要在脑中有清晰的思路。想要程序去做什么首先自己要明确自己想做什么,思考你的程序需要哪些信息,要进行哪些计算和控制,以及程序应该要报告什么信息。在这一步骤中,不涉及具体的计算机语言,应该用一般术语来描述问题。
1.8.2 第 2 步:设计程序
对程序应该完成什么任务有概念性的认识后,就应该考虑如何用程序来完成它。例如,用户界面应该是怎样的?如何组织程序?目标用户是谁?准备花多长时间来完成这个程序?
除此之外,还要决定在程序(还可能是辅助文件)中如何表示数据,以及用什么方法处理数据。学习 C 语言之初,遇到的问题都很简单,没什么可选的。但是,随着要处理的情况越来越复杂,需要决策和考虑的方面也越来越多。通常,选择一个合适的方式表示信息可以更容易地设计程序和处理数据。
再次强调,应该用一般术语来描述问题,而不是用具体的代码。但是,你的某些决策可能取决于语言的特性。例如,在数据表示方面,C 的程序员就比 Pascal 的程序员有更多选择。
1.8.3 第 3 步:编写代码
设计好程序后,就可以编写代码来实现它。也就是说,把你设计的程序翻译成 C 语言。这里是真正需要使用 C 语言的地方。可以把思路写在纸上,但是最终还是要把代码输入计算机。
这个过程的机制取决于编程环境,我们稍后会详细介绍一些常见的环境。一般而言,使用文本编辑器创建源代码文件。该文件中内容就是你翻译的 C 语言代码。程序清单 1.1 是一个 C 源代码的示例。
程序清单 1.1 C 源代码示例:
#include <stdio.h>
int main(void)
{
int dogs;
printf("How many dogs do you have?\n");
scanf("%d", &dogs);
printf("So you have %d dog(s)!\n", dogs);
return 0;
}
在这一步骤中,应该给自己编写的程序添加文字注释。最简单的方式是使用 C 的注释工具在源代码中加入对代码的解释。第 2 章将详细介绍如何在代码中添加注释。
提示:
本专栏采用的 C 程序开发环境包括:
- 操作系统:Windows 11 (64 位)
- 集成开发环境(IDE):Visual Studio Code(VS code)
- 编译器与调试工具:MinGW,包含 GCC(GNU Compiler Collection)用于编译 C 代码,以及 GDB(GNU Debugger)用于调试。
- 命令行工具:使用 PowerShell 或命令提示符(cmd)进行编译和运行程序。
1.8.4 第 4 步:编译
接下来的这一步是编译源代码。再次提醒读者注意,编译的细节取决于编程的环境,我们稍后马上介绍一些常见的编程环境。现在,先从概念的角度讲解编译发生了什么事情。
前面介绍过,编译器是把源代码转换成可执行代码的程序(即把高级语言程序翻译成计算机能理解的机器语言指令集)。可执行代码是用计算机的机器语言表示的代码。这种语言由数字码表示的指令组成。如前所述,不同的计算机使用不同的机器语言方案。
C 编译器负责把 C 代码翻译成特定的机器语言。此外,C 编译器还将源代码与 C 库(库中包含大量的标准函数供用户使用,如 printf () 和 scanf() )的代码合并成最终的程序(更精确地说,应该是由一个被称为链接器的程序来链接库函数,但是在大多数系统中,编译器运行链接器)。其结果是,生成一个用户可以运行的可执行文件,其中包含着计算机能理解的代码。
编译器还会检查 C 语言程序是否有效。如果 C 编译器发现错误,就不生成可执行文件并报错。理解特定编译器报告的错误或警告信息是程序员要掌握的另一项技能。
扩展:
对于 C 程序的编译流程,我在一篇博客中进行了详尽的讲解,涵盖了从源代码到可执行文件的全过程,包括编译、汇编和链接等关键步骤,并具体介绍了 GCC 指令的应用。在该博客中,我还通过 Visual Studio Code 的命令行演示了这些指令的实际使用方法。对这一过程感兴趣的读者可以通过以下直达链接访问文章,深入了解并实践这些概念:C 语言的编译过程详解
1.8.5 第 5 步:运行程序
传统上,可执行文件是可运行的程序。在常见环境(包括 Windows 命令提示符模式、UNIX 终端模式和 Linux 终端模式)中运行程序要输入可执行文件的文件名,而其他环境可能要运行命令(如,在 VAX 中的 VMS)或一些其他机制。
例如,在 Windows 和 Macintosh 提供的集成开发环境(IDE)中,用户可以在 IDE 中通过选择菜单中的选项或按下特殊键来编辑和执行 C 程序。最终生成的程序可通过单击或双击文件名或图标直接在操作系统中运行。
提示:
VAX( Virtual Address eXtension )是一种可支持机器语言和虚拟地址的 32 位小型计算机。VMS(Virtual Memory System)是旧名,现在叫 OpenVMS,是一种用于服务器的操作系统,可在 VAX、Alpha 或 Itanium 处理器系列平台上运行。
扩展:
关于如何在 Visual Studio Code (VS Code) 中运行 C 程序,我在一篇博客中提供了详细的指南。该文章深入浅出地介绍了整个流程,从环境配置到编写、编译和执行代码的每一步骤。有兴趣了解更多或需要指导的读者,可以通过以下链接直接访问这篇文章:VS code 与终端模式中运行 C 程序详解
1.8.6 第 6 步:测试和调试程序
程序能运行是个好迹象,但有时也可能会出现运行错误。接下来,应该检查程序是否按照你所设计的思路运行。你会发现你的程序中有一些错误,计算机行话叫作 bug。
查找并修复程序错误的过程叫调试。学习的过程中不可避免会犯错,学习编程也是如此。因此,当你把所学的知识应用于编程时,最好为自己会犯错做好心理准备。随着你越来越老练,你所写的程序中的错误也会越来越不易察觉。
将来犯错的机会很多。你可能会犯基本的设计错误,可能错误地实现了一个好想法,可能忽视了输入检查导致程序瘫痪,可能会把圆括号放错地方,可能误用 C 语言或打错字,等等。把你将来犯错的地方列出来,这份错误列表应该会很长。
看到这里你可能会有些绝望,但是情况没那么糟。现在的编译器会捕获许多错误,而且自己也可以找到编译器未发现的错误。在学习本书的过程中,我们会给读者提供一些调试的建议。
提示:
在本专栏中,我将使用 Visual Studio Code (VS Code) 进行代码调试,并会详细记录和展示每一步操作过程。这样可以确保大家能够清晰地跟随学习,掌握调试技巧。
1.8.7 第 7 步:维护和修改代码
创建完程序后,你发现程序有错,或者想扩展程序的用途,这时就要修改程序。例如,用户输入以 Zz 开头的姓名时程序出现错误、你想到了一个更好的解决方案、想添加一个更好的新特性,或者要修改程序使其能在不同的计算机系统中运行,等等。如果在编写程序时清楚地做了注释并采用了合理的设计方案,这些事情都很简单。
1.8.8 说明
编程并非像描述那样是一个线性的过程。有时,要在不同的步骤之间往复。例如,在写代码时发现之前的设计不切实际,或者想到了一个更好的解决方案,或者等程序运行后,想改变原来的设计思路。对程序做文字注释为今后的修改提供了方便。
许多初学者经常忽略第 1 步和第 2 步(定义程序目标和设计程序),直接跳到第 3 步(编写代码)。刚开始学习时,编写的程序非常简单,完全可以在脑中构思好整个过程。即使写错了,也很容易发现。但是,随着编写的程序越来越庞大、越来越复杂,动脑不动手可不行,而且程序中隐藏的错误也越来越难找。最终,那些跳过前两个步骤的人往往浪费了更多的时间,因为他们写出的程序难看、缺乏条理、让人难以理解。要编写的程序越大越复杂,事先定义和设计程序环节的工作量就越大。
磨刀不误砍柴工,应该养成先规划再动手编写代码的好习惯,用纸和笔记录下程序的目标和设计框架。这样在编写代码的过程中会更加得心应手、条理清晰。