内容正文:
第 1 章 C语言概述
内容概述
C语言的发展及特点 。
C程序的基本结构和书写风格 。
简单的C程序设计 。
C程序的上机步骤和Visual C++ 6.0的 基本用法 。
常量和变量的概念
基本输入输出函数的初步使用
通过本章的学习,读者对C程序设计要有一个初步的认识,了解C语言的发展及特点和基本结构及书写风格;熟悉C程序的开发环境,掌握Visual C++ 6.0的基本用法及上机步骤,初步了解常量和变量的概念,为学习程序设计技能奠定良好的基础。
教学目标
1.1 C语言的发展及特点
1.1.1 C语言的发展
使用计算机,必须与计算机进行沟通、交流。
计算机语言是人们定的一套与计算机沟通的规则。
计算机语言分低级语言和高级语言
机器语言:由数字0、1组合而成。
汇编语言:用助记符描述的指令系统。
高级语言:面向过程的语言或称算法语言。
如:Fortran,Basic,Pascal,C 等等。
C语言是在1972年至1973年间由美国的贝尔实验室的M.D.Ritchie和K.Thompson以及英国剑桥大学的M.Richards等为描述和实现UNIX操作系统而设计的。
经进一步改进,至1977年出现了与具体机器无关的C编译文本,从而使C语言广泛应用,各种机器皆可使用。
3. 1983年,美国标准化协会(ANSI) 制定了ANSI C。
以ANSI C 为基础:
不同机器有不同版本,尤其是函数均应参考相应的机器。
C语言的编译环境有多种,如:
DOS/Windows平台:Borland/Turbo C, Microsoft C 等Unix/Linux平台:GNU C
C语言的诞生
4.1987年,ANSI C公布了新标准——87 ANSI C
5.1990年,国际标准化组织(International Standardization Organization,ISO)接受了87 ANSI C为ISO C的标准(ISO 9899—1990)。
6.进入二十世纪八九十年代,计算机语言从面向过程转化为面向对象程序设计,可视化多媒体程序设计模式的概念得到了推广、普及。C语言在发展的同时,也朝着支持面向对象、可视化程序设计语言方向发展,如Borland C++、Visual C++、C++ Builder等先后问世。C语言已经成为编写系统软件、应用软件和进行程序设计、教学的重要编程语言,甚至许多硬件开发系统也使用C语言。C语言已经成为世界上应用最广泛的计算机语言之一。
1.1.2 C语言的特点
C语言既有高级语言的优点,又在很多方面保留了低级语言的长处。
用C语言编写的程序非常简洁。
C语言只有32个关键字,9种控制语句。
auto break case char const continue default
do double else enum extern float for
goto if int long register return short
signed static sizof struct switch typedef union
unsigned void volatile while
运算符和数据结构丰富(共有34种运算符)。
除了最基本的+、-、×、÷、%等运算外,还将括号、赋值、类型强制转换等均作为运算符。
除基本的整型、实型、字符型类型外, 还有指针, 结构体、共同体等类型。
语法灵活,不太严格。
如:数据类型可相互通用:整型、字符型通用。
允许直接访问物理内存,能实现对位的操作。
直接访问内存地址,具有“ 高”、“ 低” 级语言的功能。
生成目标代码质量高,执行效率高。
语言简洁,可移植性好
可移植性优于汇编语言。
C语言是一种过程化的语言。
C语言有优秀的实现工具。
微软公司的 Microsoft Visual C++ 6.0(VC6.0)和 Borland公司的Turbo C等。
编程集成开发环境(IDE) 。
1.2 简单的C程序设计
1.2.1 认识C语言程序
【例1.1】编写程序在显示器输出一行信息:Hello, World!
#include <stdio.h> /*文件包含*/
main()
{
printf("Hello, World!
"); /*显示文本Hello, World!*/
}
【例1.2】求长方形的周长和面积。
分析
数据
输入数据:长、宽
输出数据:周长、面积
算法
周长 = (长+宽)x 2
面积 = 长 x 宽
程序中涉及的数据有两类
常量:计算周长算法中的“2”
变量:长、宽、周长和面积
需要用变量来存储。
变量需要有名称
变量名由字母、数字和下划线构成
变量名的第一个字符不能是数字
变量需要有类型
整型变量,用 int 表示
变量定义
长、宽两个变量的名称用a和b
int a; 每行定义一个变量
int b;
周长和面积两个变量的名称用l和s
int l, s; 一行定义两个变量
算法实现
周长计算: l = (a+b)*2
面积计算: s = a*b
表达式
由变量、常量、运算符和括号构成
算术运算符:
加+ 减 – 乘 * 除 /
运算符的优先级:先乘除后加减
赋值语句
等号用于赋值,把右边表达式的值赋给左边的变量
int main() /* 定义main函数 */
{
int a; /* 定义矩形的长度变量 a*/
int b; /* 定义矩形的宽度变量 b*/
int l, s; /* 定义矩形的周长、面积变量l和s */
a = 12; /* 给长度赋值12 */
b = 8; /* 给宽度赋值8 */
l = (a+b)*2; /* 计算矩形周长 */
s = a*b; /* 计算矩形面积 */
return(0); /* main函数返回 */
}
代码如下:
程序中存在的问题
程序运行后没有看到结果
变量l和s中得到了计算结果,但是没有输出它们的值
解决办法
在程序中增加输出语句
printf("l=%d s=%d
", l, s);
printf是C语言的库函数,它的功能是把程序中变量的值输出到计算机的屏幕上。
使用printf前,需要在程序头部加入下面的语句
#include <stdio.h>
#include <stdio.h>
int main() /* 定义main函数 */
{
int a; /* 定义矩形的长度变量 a*/
int b; /* 定义矩形的宽度变量 b*/
int l, s; /* 定义矩形的周长、面积变量l和s */
a = 12; /* 给长度赋值12 */
b = 8; /* 给宽度赋值8 */
l = (a+b)*2; /* 计算矩形周长 */
s = a*b; /* 计算矩形面积 */
printf(“l=%d s=%d
”, l, s); /* 输出结果 */
return(0); /* main函数返回 */
}
运行结果:
l=40 s=96
代码如下:
程序中存在的不足
矩形长、宽在程序中通过赋值的方式给定的,如果它们的值改变了,须重新编译、连接,才能计算。
解决方法:
在程序中增加输入语句
scanf("%d%d", &a, &b);
scanf是C语言的库函数,它的功能是从键盘输入数据,把数据赋给程序中变量。
使用scanf前,需要在程序头部加入下面的语句
#include <stdio.h>
#include <stdio.h>
int main() /* 定义main函数 */
{
int a; /* 定义矩形的长度变量 a*/
int b; /* 定义矩形的宽度变量 b*/
int l, s; /* 定义矩形的周长、面积变量l和s */
scanf(“%d%d”, &a, &b); /* 从键盘输入长、宽 */
l = (a+b)*2; /* 计算矩形周长 */
s = a*b; /* 计算矩形面积 */
printf(“l=%d s=%d
”, l, s); /* 输出结果 */
return(0); /* main函数返回 */
}
运行结果:
10 12
l=44 s=120
代码如下:
1.数据类型
为了使程序设计语言能充分有效地表达各种数据,一般将数据分为若干类型。
C语言中最常用的基本数据类型
整型(int)
实型(float、double)
字符型(char)
1.2.2 数据类型、常量与变量
常量:程序运行过程中不能被改变的量。
在程序中,数据显式写法均表示常量
如s=2*3.14*r中的2和3.14都是常量;
符号常量:
#define PRICE 586 ;
2.常量
3.变量
变量:程序执行过程中可以改变它的值。变量包括变量名和变量值。
变量名:用标识符命名,对应一定数量的内存存贮单元,其单元数视变量类型而定。
在【例1.1】中 :
c = a+b; /*计算和*/
a、b、c是三个变量,而且是整型变量。
在C语言中,变量须先定义,后使用。
如: int total ; /*变量定义*/
total =30 ;
是合法的。
若没有定义变量直接写成:
total =30;
则编译时会指出未定义错误。
变量一旦被定义,其类型便确定即可在编译时为其分配相应数量的单元。
4 标识符
标识符:由字母、数字、下划线组成且由字母或下划线开头的字符串。
如:_sum, sum, stu_name, price等为合法的标识符。
7ax,x&y,printf,va?r等为非法的标识符。
标识符的作用:可用来作为变量名、常量名、函数名、类型名、文件名等。
建议:采用具有一定意义的英文单词、拼音字母的缩写作为标识符
注意:
C语言区分大小写
如:Price 和 price,系统会认为是两个不同的标识符。
标识符的长度一般不超过31个字符
具体情况视不同系统而定。
5 变量赋值
变量的赋值有三种方法:
在定义变量的同时为变量赋初值,格式为:
<数据类型> <变量名>=<常量表达式>;
例如,int a=10;
利用赋值语句为变量赋初值 ,格式为:
<变量名>=<表达式>;
例如,a=10+3;
利用格式化输入函数为变量赋初值 ,格式为:
scanf(“格式控制字符串”,变量地址表列);
例如, scanf("%d", &a);
定义后的变量其值是随机的、不确定的,只有通过赋值操作,其值才是确定的,才能被使用。
1.2.3数据输入输出的概念及在C语言中的实现
所谓输入输出是以计算机为主体而言的。
数据输入是从标准输入设备输入,也就是键盘。
数据输出到标准输出设备,也就是显示器。DOS下整个屏幕是标准输出设备,Windows下当前窗口是标准输出设备。
在C语言中,所有的数据输入/输出都是由库函数完成的,因此都是函数语句。
在使用C语言库函数时,需要用预编译命令include包含标准输入输出头文件stdio.h,即:
#include <stdio.h>
格式输出函数printf()函数
函数功能:
按用户指定的格式,把指定的数据显示到显示器屏幕上。
一般形式:
printf(“格式控制字符串”, 输出表列);
格式字符串是以%开头的字符串,在%后面跟有各种格式字符,以说明输出数据的类型、形式、长度、小数位数等。如:“%d”表示按十进制整型输出。
输出表列中给出了各个输出项,要求格式字符串和各输出项在数量和类型上应该一一对应
格式输入函数scanf ()函数
函数功能:
按用户指定的格式从键盘上把数据输入到指定的变量之中。
一般形式
scanf(“格式控制字符串”,地址表列);
其中,格式控制字符串的作用与printf函数相同,但不能显示非格式字符串。地址表列中给出各变量的地址。
地址是由地址运算符“&”后跟变量名组成的。
例如: &a, &b 分别表示(取)变量a和变量b 的地址。
【例1.3】从键盘输入两个整数,输出它们的和。
#include <stdio.h > /*文件包含*/
int sum(int a,int b) /*子函数及其形式参数*/
{
int c; /*定义局部变量*/
c=a+b; /*计算和*/
return(c); /*返回值*/
}
1.3 C程序的基本结构和书写风格
1.3.1 C程序的基本结构
main() /*主函数名*/
{ /*函数体开始*/
int a,b,c; /*局部变量类型定义*/
printf("输入两个整数:"); /*屏幕提示信息*/
scanf("%d%d",&a,&b); /*输入两个整数*/
c=sum(a,b); /*调用计算求和的函数*/
printf("和=%d
", c); /*打印总分值*/
} /*函数体结束*/
通过实例,初步看到C的程序结构
C程序全部由一个一个的函数构成。至少有且仅有一个主函数main (),也称为主程序,其内容在其后的一对花括号{}内,其它函数可被主函数调用或相互调用。其它函数可为C 函数库中函数,也可为用户定义的函数。
main()函数的最后一条语句是
return 0;
它结束main()函数的运行,并向系统返回一个整数0,作为程序结束状态,这条语句可以省略。
实际上,主函数main()还可以定义成没有返回值的形式:
void main()
{
……
}
一个函数有两部分组成:
1)函数的首部,即函数的第一行。包括函数名、函数类型、函数参数(形参)名和参数类型。
例如: int sum(int a,int b)
2)函数体,即函数首部下面的大括弧{……}内的部分。
函数体一般包括:
声明部分:在这部分中定义所用到的变量,如果需要,也要对所调用的函数进行声明。
执行部分:有若干个语句组成。
在某些情况下也可以没有声明部分,甚至可以既无声明部分,也无执行部分。如:
dump()
{ }
一个C程序总是从main函数开始执行的,而不论main函数在整个程序中的位置如何(main函数可以放在程序最前头,也可以放在程序的最后面,或在一些函数之前,在另一些函数之后)。
函数由语句构成,语句由基本单词组成 。
C程序书写格式自由,一行也可以写几个语句,一个语句可以写在多行上。但为了程序的阅读和理解,C程序书写需按照某些书写规则,稍后将介绍。
6. 每个语句和数据定义的最后必须有一个分号。
7. C语言本身没有输入、输出语句。输入和输出的操作是由库函数scanf和printf等函数来完成。
8. 可以用“/* …… */”对C程序中的任何部分作注释;也可用“// …… ” 对C程序中的一行作注释。
1.3.2 C程序的书写风格
每一对{ }上下对齐;
每一对{ }都对应于段首和段尾;
每一行只写一条语句;
每一对{}内的语句左对齐;
不同的语句段采用缩进格式以示区别;
关键语句要有注释。
C程序的书写格式完全自由,为便于阅读,养成良好的程序书写风格。
C语言程序实例 – Apache HTTP服务器源代码片段
#include "apr.h"
#include "apr_strings.h"
#include "apr_getopt.h"
#include "apr_general.h"
#include "apr_lib.h"
#include "apr_md5.h"
#define APR_WANT_STDIO
#define APR_WANT_STRFUNC
#include "apr_want.h"
#define CORE_PRIVATE
#include "ap_config.h"
#include "httpd.h"
#include "http_main.h"
#include "http_log.h"
#include "http_config.h"
#include "http_core.h"
#include "http_vhost.h"
#include "apr_uri.h"
#include "util_ebcdic.h"
#include "ap_mpm.h"
#include "mpm_common.h"
/* WARNING: Win32 binds http_main.c dynamically to the server. Please place
* extern functions and global data in another appropriate module.
*
* Most significant main() global data can be found in http_config.c
*/
static void show_mpm_settings(void)
{
int mpm_query_info;
apr_status_t retval;
printf("Server MPM: %s
", ap_show_mpm());
retval = ap_mpm_query(AP_MPMQ_IS_THREADED, &mpm_query_info);
if (retval == APR_SUCCESS) {
printf(" threaded: ");
if (mpm_query_info == AP_MPMQ_DYNAMIC) {
printf("yes (variable thread count)
");
}
else if (mpm_query_info == AP_MPMQ_STATIC) {
printf("yes (fixed thread count)
");
}
else {
printf("no
");
}
}
retval = ap_mpm_query(AP_MPMQ_IS_FORKED, &mpm_query_info);
if (retval == APR_SUCCESS) {
printf(" forked: ");
if (mpm_query_info == AP_MPMQ_DYNAMIC) {
printf("yes (variable process count)
");
}
else if (mpm_query_info == AP_MPMQ_STATIC) {
printf("yes (fixed process count)
");
}
else {
printf("no
");
}
}
}
int main(int argc, const char * const argv[])
{
char c;
int configtestonly = 0;
const char *confname = SERVER_CONFIG_FILE;
const char *def_server_root = HTTPD_ROOT;
const char *temp_error_log = NULL;
const char *error;
process_rec *process;
server_rec *server_conf;
apr_pool_t *pglobal;
apr_pool_t *pconf;
apr_pool_t *plog; /* Pool of log streams, reset _after_ each read of conf */
apr_pool_t *ptemp; /* Pool for temporary config stuff, reset often */
apr_pool_t *pcommands; /* Pool for -D, -C and -c switches */
apr_getopt_t *opt;
apr_status_t rv;
module **mod;
const char *optarg;
APR_OPTIONAL_FN_TYPE(ap_signal_server) *signal_server;
AP_MONCONTROL(0); /* turn off profiling of startup */
apr_app_initialize(&argc, &argv, NULL);
process = create_process(argc, argv);
pglobal = process->pool;
pconf = process->pconf;
ap_server_argv0 = process->short_name;
#if APR_CHARSET_EBCDIC
if (ap_init_ebcdic(pglobal) != APR_SUCCESS) {
destroy_and_exit_process(process, 1);
}
#endif
apr_pool_create(&pcommands, pglobal);
apr_pool_tag(pcommands, "pcommands");
ap_server_pre_read_config = apr_array_make(pcommands, 1, sizeof(char *));
ap_server_post_read_config = apr_array_make(pcommands, 1, sizeof(char *));
ap_server_config_defines = apr_array_make(pcommands, 1, sizeof(char *));
error = ap_setup_prelinked_modules(process);
if (error) {
ap_log_error(APLOG_MARK, APLOG_STARTUP|APLOG_EMERG, 0, NULL, "%s: %s",
ap_server_argv0, error);
destroy_and_exit_process(process, 1);
}
ap_run_rewrite_args(process);
/* Maintain AP_SERVER_BASEARGS list in http_main.h to allow the MPM
* to safely pass on our args from its rewrite_args() handler.
*/
apr_getopt_init(&opt, pcommands, process->argc, process->argv);
while ((rv = apr_getopt(opt, AP_SERVER_BASEARGS, &c, &optarg))
== APR_SUCCESS) {
char **new;
switch (c) {
case 'c':
new = (char **)apr_array_push(ap_server_post_read_config);
*new = apr_pstrdup(pcommands, optarg);
break;
case 'C':
new = (char **)apr_array_push(ap_server_pre_read_config);
*new = apr_pstrdup(pcommands, optarg);
break;
case 'd':
def_server_root = optarg;
break;
case 'D':
new = (char **)apr_array_push(ap_server_config_defines);
*new = apr_pstrdup(pcommands, optarg);
/* Setting -D DUMP_VHOSTS is equivalent to setting -S */
if (strcmp(optarg, "DUMP_VHOSTS") == 0)
configtestonly = 1;
/* Setting -D DUMP_MODULES is equivalent to setting -M */
if (strcmp(optarg, "DUMP_MODULES") == 0)
configtestonly = 1;
break;
}
}
/* bad cmdline option? then we die */
if (rv != APR_EOF || opt->ind < opt->argc) {
usage(process);
}
apr_pool_create(&plog, pglobal);
apr_pool_tag(plog, "plog");
apr_pool_create(&ptemp, pconf);
apr_pool_tag(ptemp, "ptemp");
/* Note that we preflight the config file once
* before reading it _again_ in the main loop.
* This allows things, log files configuration
* for example, to settle down.
*/
ap_server_root = def_server_root;
if (temp_error_log) {
ap_replace_stderr_log(process->pool, temp_error_log);
}
server_conf = ap_read_config(process, ptemp, confname, &ap_conftree);
if (!server_conf) {
destroy_and_exit_process(process, 1);
}
if (ap_run_pre_config(pconf, plog, ptemp) != OK) {
ap_log_error(APLOG_MARK, APLOG_STARTUP |APLOG_ERR, 0,
NULL, "Pre-configuration failed");
destroy_and_exit_process(process, 1);
}
rv = ap_process_config_tree(server_conf, ap_conftree,
process->pconf, ptemp);
if (rv == OK) {
ap_fixup_virtual_hosts(pconf, server_conf);
ap_fini_vhost_config(pconf, server_conf);
apr_hook_sort_all();
if (configtestonly) {
ap_run_test_config(pconf, server_conf);
ap_log_error(APLOG_MARK, APLOG_STARTUP, 0, NULL, "Syntax OK");
destroy_and_exit_process(process, 0);
}
}
apr_pool_lock(pconf, 0);
destroy_and_exit_process(process, 0);
return 0; /* Termination 'ok' */
}
1.4 C程序的上机步骤
C程序上机编程过程
Microsoft Visual C++ 6.0 使用简介
创建应用项目 (Project)
编辑C语言源程序
编译
连接
运行
修改程序错误
Microsoft Visual C++ 6.0 使用简介
桌面快捷方式
创建应用项目
打开File菜单,点击New菜单项。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
创建应用项目
选择Projects为Win32 Console Application,输入项目名称,
及选择项目文件存放的目录,然后点OK按钮
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
创建应用项目
选择Console Application的类型为An Empty project,然后
点Finish按钮。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
创建应用项目
点OK按钮,系统将按照前面选择的类型创建一个新的项目。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
编辑C语言源程序
打开File菜单,点击New菜单项,弹出New对话框。
选择Files类型为C++ Source File,文件名File的扩展名为.c,
如下图中为: Sample.c,其他项目不要改变。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
输入C源程序
在下图中的文件编辑窗口中输入C语言源程序。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
编译、连接和运行C程序
点工具条上的 按钮,系统提示是否build,点 是(Y) 按钮开始
编译、连接,创建可执行程序,并运行程序。
程序运行结果
如果程序正确,编译、连接后将自动运行程序。图中的Console
窗口中显示了程序运行结果,按任何键关闭该窗口。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
修改程序错误
当程序存在错误,编译、连接过程将停止,并将错误信息显示在
信息窗口中。双击错误信息,光标将跳到发生错误的语句。
单击此处编辑母版文本样式
第二级
第三级
第四级
第五级
$$