#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 函數中聲明的,因此其它函數不能直接訪問它們。
外部變量必須定義在所有函數之外,且只能定義一次。由於外部變量可以在全局範圍內訪問,因此,函數間可以通過外部變量交換數據,而不必使用參數表。