#include <stdio.h>
/*print Fahrenheit-Celsius table for fahr=0,20,...,300;floating-point version*/
int main()
{
float fahr,celsius;
float lower,upper,step;
lower = 0; /*lower limit of temperature scale*/
upper = 300; /*upper limit*/
step = 20; /*step size*/
fahr = lower;
while(fahr<=upper)
{
celsius = (5.0/9.0) * (fahr-32.0);
printf("%3.0f %6.1f\n",fahr,celsius);
fahr = fahr + step;
}
return 0;
}
正确的缩进以及保留适当空格的程序设计风格对程序的易读性非常重要!我们建议每行只书写一条语句,并在运算符两边各加上一个空格字符,这样可以使得运算的结合关系更清楚明了。
顺便指出,printf函数并不是C语言本身的一部分,C语言本身并没有定义输入/输出功能。printf函数仅仅是标准库函数中一个有用的函数而已。
1.3
#include <stdio.h>
#define LOWER 0 /* lower limit of table */
#define UPPER 300 /* upper limit */
#define STEP 20 /* step size */
/* print Fahrenheit-Celsius table */
int main()
{
int fahr;
for(fahr = 0; fahr <= 300; fahr = fahr + 20)
printf("%3d %6.1f\n", fahr, (5.0/9.0)*(fahr-32));
return 0;
}
在允许使用某种类型变量值的任何场合,都可以使用该类型的更复杂的表达式。在实际编程过程中,可以选择while或for中的任意一种循环语句,主要要看使用哪一种更清晰。for语句比较适合初始化和增加步长都是单条语句并且逻辑相关的情形。因为它将循环控制语句集中放在一起,且比while语句更紧凑。
1.4
在程序中使用300、20等类似的“幻数”并不是一个好习惯,它们几乎无法向以后阅读该程序的人提供什么信息,而且使程序的修改变得更加空难。处理这种幻数的一种方法是赋予它们有意义的名字。#define指令可以把符号名(或称为符号常量)定义为一个特定的字符串:
#define 名字 替换文本
LOWER、UPPER 与 STEP 都是符号常量,而非变量,因此不需要出现在声明中。符号常量名通常用大写字母拼写,这样可以很容易与用小写字母拼写的变量名相区别。注意,#define指令行的末尾没有分号。
1.5
标注库提供了一次读/写一个字符的函数,其中最简单的是 getchar 和 putchar 两个函数。
#include <stdio.h>
/* copy input to output; 1st version */
int main()
{
int c;
c = getchar();
while (c != EOF)
{
putchar(c);
c = getchar();
}
return 0;
}
如何区分文件中有效数据与输入结束符的问题。C语言采取的解决方法是:在没有输入时,getchar函数将返回一个特殊值,这个特殊值与任何实际字符都不同。这个值称为EOF( end of file, 文件结束)。我们在声明变量c的时候,必须让它大到足以存放getchar函数返回的任何值。这里之所以不把c声明成char类型,是因为它必须足够大,除了能存储任何可能的字符外还要能存储文件结束符EOF。因此,我们将c声明成int类型。
EOF定义在头文件<stdio.h>中,是个整形数,其具体数值是什么并不重要,只要它与任何char类型的值都不相同即可。这里使用符合常量,可以确保程序不需要依赖于其对应的任何特定的数值。
在C语言中,类似于
c = getchar()
之类的赋值操作是一个表达式,并且具有一个值,即赋值后左边变量保存的值。也就是说,赋值可以作为更大的表达式的一部分出现。
#include <stdio.h>
/* copy input to output; 1st version */
int main()
{
int c;
while ((c = getchar()) != EOF)
putchar(c);
return 0;
}
1.5.2
#include <stdio.h>
/* count characters in input; 2nd version */
int main()
{
double nc;
for(nc = 0; getchar() != EOF; ++nc)
;
printf("%.0f\n",nc);
return 0;
}
C语言的语法规则要求for循环语句必须有一个循环体,因此用单独的分号代替。但C语言的语法规则要求for循环语句必须有一个循环体,因此用单独的分号代替。单独的分号称为空语句,把它单独放在一行是为了更加醒目。
1.5.4
#include <stdio.h>
#define IN 1 /* inside a word */
#define OUT 0 /* outside a word */
/* count lines, words, and characters in input */
int main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while((c=getchar()) != EOF)
{
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT)
{
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
return 0;
}
上面这段程序是 UNIX 系统中 wc 程序的骨干部分。
程序执行时,每当遇到单词的第一个字符,它就作为一个新单词加以统计。state 变量记录程序当前是否正位于一个单词之中。
if-else 中的两条语句有且仅有一条语句被执行。
1.6
#include <stdio.h>
/* count digits, white space, others */
int main()
{
int c, i, nwhite, nother;
int ndigit[10];
nwhite = nother = 0;
for (i = 0; i < 10; ++i)
ndigit[i] = 0;
while((c = getchar()) != EOF)
if (c >= '0' && c <= '9')
++ndigit[c-'0'];
else if (c == ' ' || c == '\n' || c == '\t')
++nwhite;
else
++nother;
printf("digits =");
for (i = 0; i < 10; ++i)
printf(" %d",ndigit[i]);
printf(", white space = %d, other = %d\n", nwhite, nother);
return 0;
}
1.7
#include <stdio.h>
int power(int m,int n);
/* test power function */
int main()
{
int i;
for (i = 0; i < 10; ++i)
printf("%d %d %d\n", i, power(2,i), power(-3,i));
return 0;
}
/* power: raise base to n-th power; n >= 0 */
int power(int base, int n)
{
int i, p;
p=1;
for (i = 1; i <= n; ++i)
p = p * base;
return p;
}
power 函数的参数使用的名字只在 power 函数内部有效,对其它任何函数都是不可见的:其它函数可以使用与之相同的参数名字而不会引起冲突。变量 i 与 p 也是这样: power 函数中的 i 与 main 函数中的 i 无关。
我们通常把函数定义中圆括号内列表中出现的变量称为形式参数,而把函数调用中与形式参数对应的值称为实际参数。程序还要向其执行环境返回状态。函数原型与函数声明中参数名不要求相同。
1.9
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
/* print the longest input line */
int main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE];/* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max)
{
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line into s, return length */
int getline(char s[], int lim)
{
int c, i;
for (i=0; i < lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\n')
++i;
}
main函数中的变量(如 line、longest 等)是 main 函数的私自变量或局部变量。由于它们是在 main 函数中声明的,因此其它函数不能直接访问它们。
外部变量必须定义在所有函数之外,且只能定义一次。由于外部变量可以在全局范围内访问,因此,函数间可以通过外部变量交换数据,而不必使用参数表。