本章問題
1.Is the following statement legal?If so,what does it do?
(下面的語句是否合法,如果合法,它做了什么)
3 * x * x - 4 * x + 6;
answer:It is legal,but it doesn't affect the program's state,None of the operators involved(有關) have any side effects and the result that is computed is not assigned to any variable.
(這條語句是合法的,不過它在程序里不起任何作用,沒有有關操作符有任何副作用,計算的結果將不會賦值給任何變量)
2.What is the syntax of the assignment statement?
(賦值語句的語法是怎樣的?)
answer:Trick Question! There is no "assignment statement" in C,Assignments are done with an expression that uses the assignment operator,as in:
(這個問題是個陷阱,在C里面沒有賦值語句,賦值操作是用賦值操作符的表達式實現,就像:)
x = y + z;
3.Is it legal to use a block in this manner(風格)? If so,why would you ever want to use it?
(用這種風格使用代碼塊合法嗎?如果合法,為什么你打算使用它?)
...
statement
{
statement
statement
}
statement
answer : Yes,it is legal,This is useful if you need to introduce(引用) a temporary variable for the enclosed(封閉的) statements,but wish to restrict(限制) access to the variable to only those statement.
(這個語句是合法的,如果你需要在封閉的語句中引用臨時變量,這個語句相當有用,不過你被限制只能在代碼塊中使用它們)
4.How would you write an if statement that had no statements in the then clause(子句) but had statements in the else clause?How else,could an equivalent statement be written?
(你會怎樣寫一個then子句為空而else語句不為空的條件語句?如果是else為空呢,可以用一樣的語句嗎?)
answer:
if(condition)
;
else{ statements; } //equivalently, you can invert the condition to omit the empty else clause. if(!(condition)){ statements; }
5.What output is produced frome the loop below?
(下面循環將輸出什么?)
int i;
...
for(i = 0; i < 10; i += 1) printf("%d\n",i);
answer:
//The integers starting at 0 and ending with 9,The value 10 is not printed. 0 1 2 3 4 5 6 7 8 9
6.When might a while statement be more appropriate(恰當) than a for statement?
(什么時候使用while語句可能比使用for語句更恰當)
answer:When there are no initialization or adjustment expressions.
(當不用初始化或者調整語句時)
7.The code fragment below is supposed to copy the standard input to the standard output and compute a checksum of the characters,What is wrong with it?
(下面這個代碼片段想要從標准輸入計算所有字符的總值並復制到標准輸出,有什么錯誤嗎?)
while((ch = getchar()) != EOF)
checksum += ch; purchar(ch); printf("checksum = %d\n",checksum);
answer:Despite the indentation(縮進),the call to putchar is not in the loop because there are no braces.as a result,the input is not printed,only the checksum,note that the only thing printed by putchar is the end of file indicator(標志);on most systems,this is not a valid(有效) character.
(盡管有縮進,但是putchar不會在循環里調用,因為沒有用大括號,所以不會被打印出來,只打印checknum的值,唯一被putchar打印的是文件結尾標志,在大多數系統中它不是一個有效的字符)
8.When is the do statement more appropriate than a while or a for statement?
(什么情況下do語句比while和for語句更合適)
answer:When the body of the loop must be executed once even if the condition is initially false.
(即便條件不滿足也要先至少執行一邊循環體的時候)
9.What output is produced from this code fragment?Note:The % operator divides its left operand by its right operand and gives you the remainder.
(下面這個代碼段將輸出什么?提示:%操作符用來取余數)
for(i = 1; i <= 4; i += 1){
switch(i % 2){ case 0: printf("even\n"); case 1: printf("odd\n"); } }
answer:There are no break statement,so both messages are printed for each even number.
(沒有break語句,所以當為偶數時將打印所有的語句)
odd
even
odd
odd
even
odd
10.Write statements that read an integer value frome the standard input and then print that many blank lines.
(寫一個語句從標准輸入中讀取一個整數,然后打印出那么多空行)
answer:
//可以用for或者while,不能用do
int n;
scanf("%d",&n); while(n >= 0){ printf("\n"); }
11.Write statements to validate(確認) and report on some values that have already been read,If x is less than y,print the word "wrong",also,if a is greater than or equal to b,print "wrong",otherwise,print the order "right",note:In case you need it,|| is the "or" operator.
(寫語句確認並報告一些已經被讀取的值,如果x小於y或者a大於等於b,就打印單詞“wrong”,否則打印單詞“right”,提示“你可能需要”||“操作符,表示或運算)
answer:
if(x < y || a >= b)
printf("wrong"); else printf("right");
12.Years that are divisible by four are leap years;except,that years that are divisible by 100 are not.However,years that are divisible by 400 are leap years,Write statements to determine whether the value in year is a leap year,and set the variable leap_years to one if it is a leap year,and zero if it is not.
(年份能被4整除的被稱為潤年,除了能被100整除而不 能被400整除的不是潤年,寫語句判斷是否為潤年,用leap_years來表示,如果是潤年則置1,否則置0)
answer:
/*標准答案上是這么寫的,利用了if語句篩選,初看下可能會覺得不對,細看之后覺得很有道理*/
if(year % 400 == 0)
leap_years = 1; else if(year % 100 == 0) leap_years = 0; else if(year % 4 == 0) leap_years = 1; else leap_years = 0; /*下面這兩個程序是我自己寫的,一個是判斷是潤年,一個是判斷不是潤年,相比前面的答案可能反倒有些冗余,不過比較直觀*/ //is leap_years if(year % 4 == 0 && year % 100 != 0) leap_years = 1; else if(year % 100 == 0 && year % 400 == 0) leap_years = 1; else leap_years = 0; //is not leap_years if(year % 4 != 0) leap_years = 0; else if(year % 100 == 0 && year % 400 != 0) leap_years = 0; else leap_years = 1;
13.Newspaper reporters are trained to ask who,what,when,where and why,Write statements that will print who if the variable which_word is one,what if the variable is two,and so forth,if the value is not in the range one through five,print don't know instead.
(新聞記者被訓練提問who,what when where why,寫一個語句,如果變量which_word 為1,則打印who,如果變量為2,則打印what,其他的依次類推,如果不再1到5的范圍內,則打印不知道)
answer:
switch(which_word){
case 1: printf("who"); break; case 2: printf("what"); break; case 3: printf("when"); break; case 4: printf("where"); break; case 5: printf("why"); break; default:
printf("don't know"); break; }
//也可以用數組的方法
char word[5] = {"who","what","when","where","why"};
if(which_one <= 5 && which_one >= 1) printf("%s\n",word[which_one - 1]); else printf("don't know");
14.Pretend that a "program” controls you, and this program contains two function,eat_hamburger() makes you eat a hamburger,and hunger() returns a true or a false value depending on whether you are hungry,Write the statement that allow you to eat as many hamburgers as you want until you're no longer hungry.
(假定有一個程序可以控制你,這個程序包括兩個函數,一個是eat_hamburger控制你吃一個漢堡包,hunger函數返回一個真假值,這個值取決於你是否吃飽,寫一個語句允許你吃足夠的漢堡包直到你不再餓)
answer:
if(hunger())
eat_hamburger();
15.Modify your answer to question 14 to satisfy(使滿意) your grandmother-you've got to eat something!-so that you always eat at least one hamburger.
(在問題14中修改你的答案,為了使你的祖母滿意,你不得不吃點東西,所以你至少吃一個漢堡包)
answer:
do
eat_hamburger();
while(hunger());
16.Write statements to print a capsule(簡約的) summary of the current weather according to the values of the variables precipitating(降雨) and temperature(溫度).
(寫一個語句,根據溫度和降雨變量做一個簡單的總結並打印)
If precipitating is ... | and temperature is... | then print... |
true | <32 >=32 |
snowing raining |
false | <60 >= 60 |
cold warm |
answer:
if(precipitaing){
if(temperature < 32) printf("snowing"); else printf("raining"); }else{ if(temperature < 60) printf("cold"); else printf("warm"); }
本章練習
1.The square root(平方根) of a positive number n can be computed as a series of approximations(近似值),each more accurate(正確) than the last,The first approximation is one;successive(接連的) approximations are given by the following formula(公式).
ai+1 = (ai + (n/ai))/2
Write a program to read a value and compute and print its square root,if you print all of the approximations,you can see how quickly this method converges(收斂) on the correct value,In practice,though,the restricted(受限的) precision(精准度) of floating-poing variables prevents the program from continuing.Have your program stop computing when an approximation is equal to the previous one.
(計算一個正數n的平方根,用連續的近似值計算,計算的值會越來越逼近正確值,第一個近似值是1,后面的近似值由下面的公式計算,寫一個程序讀取一個值計算並打印出它的平方根,如果你把所有的近似值打印出來,你可以看到它們快速的逼近正確值,在練習中,程序被浮點型的數據精准度限制,如果一個近似值與前一個相等,那么就停止運算)
answer:
#include <stdio.h>
float sq_root(float );
int main(void) { float value; scanf("%f",&value); if(value <= 0){ printf("the value is not positive!"); return 1; } printf("%f",sq_root(value)); return 0; } float sq_root(float value) { float p,n; p = 1; n = 0; while(1){ n = (p + (value/p)) / 2; if(p != n) p = n; else break; } return n; }
2.An integer is called prime if it is not evenly divisible by any integer other than itself and one,Write a program to print those numbers in the range 1-100 that are prime.
(質數不能被除了它自己和1的其他任何值整除,寫一個程序打印出1-100內所有的質數)
answer:
//code 1
#include <stdio.h>
int is_prime(int );
int main(void) { int n; for(n = 1; n <= 100; n++) if(is_prime(n)) printf("%d\n",n); return 0; } int is_prime(int n) { int flag = 1; int i; if(n == 1) flag = 0; for(i = 2; i < n; i++){ if(n % i == 0) flag = 0; } return flag; }
//code 2 任何一個整數不可能被比它的一半還大的數整除,所以可以將除數縮小
#include <stdio.h>
int is_prime(int );
int main(void) { int n; for(n = 1; n <= 100; n++) if(is_prime(n)) printf("%d\n",n); return 0; } int is_prime(int n) { int flag = 1; int i; if(n == 1) flag = 0; for(i = 2; i < n/2 + 1; i++){ if(n % i == 0) flag = 0; } return flag; }
//code3篩選法 /*先把N個自然數按次序排列起來。1不是質數,也不是合數,要划去。
第二個數2是質數留下來,而把2后面所有能被2整除的數都划去。
2后面第一個沒划去的數是3,把3留下,再把3后面所有能被3整除的數都划去。
3后面第一個沒划去的數是5,把5留下,再把5后面所有能被5整除的數都划去。
這樣一直做下去,就會把不超過N的全部合數都篩掉,留下的就是不超過N的全部質數。
因為希臘人是把數寫在塗臘的板上,每要划去一個數,就在上面記以小點,
尋求質數的工作完畢后,這許多小點就像一個篩子,
所以就形象地把埃拉托斯特尼的方法叫做“埃拉托斯特尼篩”,簡稱“篩法”。*/ #include <stdio.h> #define MAX 101 int main(void) { int n[MAX]; int i,j; for(i = 1; i < MAX; i++){ n[i] = 1; } n[1] = 0; // 1 is not prime n[2] = 1; // 2 is prime for(i = 2; i < MAX; i++){ if(n[i] == 1){ for(j = i + i; j < MAX; j += i) n[j] = 0; } } for(i = 1; i < MAX; i++){ if(n[i] != 0) printf("%d\n",i); } return 0; }
3.All three side of equilateral triangles are the same length,but only two of the sides of an isosceles(等腰) triangle are equal.If all of the sides of a triangle are different lengths it is called scalene(不等邊的),Write a program to prompt(提示) for and read three numbers that are the lengths of the three side of triangle,The program should than determine what type of triangle the numbers represent,Hint:What else should the program be looking for?
(三條邊都相等的三角形叫等邊三角形,有兩條邊相等的三角形的等腰三角形,三條邊都不相等叫做不等邊三角形,寫一個程序提示輸入三角形的三條變長,程序需要判斷這些數字代表的是什么三角形,提示:什么是程序另外要檢查的?)
#include <stdio.h>
int main(void)
{
float a,b,c; printf("please input the triangle's three side length:\n"); scanf("%f %f %f",&a,&b,&c); if(a <= 0 || b <= 0 || c <= 0){ printf("the length of triangle side is not positive!"); return 1; } if( a + b <= c || a + c <= b || b + c <= a){ printf("whatever two side must be less than other side"); return 1; } if(a == b && b == c) printf("equilateral"); else if(a == b || a == c || b == c) printf("isosceles"); else printf("scalene"); return 0; }
//你也可以像標准答案一樣,把三條邊按照大小順序排好之后再判斷
4.Write the function copy_n whose prototype is shown below:
void copy_n(char dst[], char scr[], int n);
The function is to copy a string from the array src to the array dst but with the following requirement:exactly n characters must be stored into dst,no more,no less,If the length of the string in src is less than n,then you must add enough NUL characters after the copied characters to get a total of n characters stored.If the length of the string in src is greater than or equal to n,then stop after you have stored the n'th character;in this case dst will not be NUL-terminated.Note that a call to copy_n should store something into dst[0] through dst[n-1],and only those locations,regardless of the length of src.If you planning on using the library routine strncpy to implement your program you are congratulated for reading ahead,but the goal here if for you to figure out the logic yourself,so you may not use any of the library string routines.
(寫一個函數,它的原型如下所示,這個函數將數組src中的字符串復制到數組dst但是有這些要求:剛好n個字符被存儲到dst數組,如果src字符串的長度比n小,那么你需要添加足夠的NUL字符使得有n個字符被存儲,如果src中字符串的長度大於或等於n,那么復制n個字符后停止,這種情況下不是以NUL結尾,注意調用copy_n時應該在dst[0]到dst[n-1]存儲,與src的長度無關,如果你計划使用strncpy來實現你的程序,祝賀你提前學到了這個知識,但在這里我的目的是讓你自己規划程序的邏輯,所以你最好不要使用那些處理字符串的庫函數)
answer:
void copy_n(char src[],char dst[], int n)
{
int len = 0; int i; for(i = 0; src[i] != '\0'; i++) len++; for(i = 0; i < n; i++){ if(i < len){ dst[i] = src[i]; }else dst[i] = '\0'; } }
5.Write a program that reads the standard input line by line and docs the following:for each set of two or more indentical(相同的),adjacent(相鄰) lines in the file,one line from the set should be printed out;nothing else should be printed out,you may assume that the lines in the file will not exceed 128 characters in length(127chararcters plus one for the newline that terminates(結束) each line)
(寫一個程序從標准輸入中一行一行的讀取,相鄰行有一行或多行相同則打印,其他的都不打印,你可能要假定每一行不超過128個字符,長度不超過127個字符,每一行以換行符結尾)
Consider the input file shown below.
(考慮輸入下面的文件)
This is the first line.
Another line.
And another;
And another;
And another;
And another;
Still more;
Almost down now - Almost down now - Anoter line. Still more. Finished!
Assuming that there are no trailing blanks or tabs on any of the lines(which wouldn't be visible but would make the line different from its neightbors),this program would produce the following output from this input file.
(假定結尾沒有空格或tab鍵,這個程序將會產生以下輸出)
And another.
Almost down now -
One line from each set of adjacent identical lines is printed.Notice that "Anohter line."and "Still more" are not printed because,although there are two of each in the file,they are not adjacent.hints:Use gets to read the input lines,and strcpy to copy them,there is a routine called strcmp that takes two strings as arguments and compares them,it returns zero if they are equal and a nonzero value if they are not.
(每一個相鄰行相同都會被輸出,注意Another line和Still more這兩行不應該被打印出來,因為盡管它們出現兩次但是不相鄰,提示:使用gets來讀取行,使用strcpy來復制,使用strcmp進行比較,如果兩個字符串相等則返回0,否則返回非零值)
answer:
/*
標准答案中給定的方法,有兩行一樣就打印出來,后面與前面一樣,不予理會
*/
/*
下面這種方法與答案稍有不同,如果有兩行一樣,暫且不理會,直到遇見不一樣的一行,才輸出之前行的內容
*/
#include <stdio.h> #include <string.h> int main(void) { int flag = 0; char previou[128]; char next[128]; gets(previou); while(gets(next) != EOF){ if(strcmp(next,previou) != 0 && flag == 1){ printf("%s",next); flag = 0; } if(strcmp(next,previou) == 0) flag = 1; else flag = 0; strcpy(previou,next); } }
6.Write a function that extracts(提取) a substring from a string,The function should have the following prototype:
int substr(char dst[],char src[],int start,int len)
It should copy the string that begins start characters past the beginning of the string in src into the array dst,At most len non-NUL characters should be copied from src,After copying,dst must be NUL-terminated,The function should return the length of the string stored in dst.If start specifies a position beyond the end of the string in src,or either start or len are negative,then dsc should be given the empty string.
(編寫一個函數從字符串中提取子字符串,函數原型如下,從src數組其實位置向后偏移start個字符的位置開始,最多復制len個非NUL字符,dst必須以NUL字符結尾,函數的返回值是存儲於dst數組中的字符串長度,如果start所指定的位置超過了src的尾部,或者start,len的值為負,那么復制到dst數組的字符串為空)
answer:
int substr(char dst[], char src[], int start, int len)
{
int i; int src_len = strlen(src); if(start < 0 || len < 0 || start >= src_len){ dst[0] = '\0'; i = 0; } else{ for(i = 0; i < len; i++){ if(i+start < src_len) dst[i] = src[i+start]; else break; } dst[i] = '\0'; printf("%s:%d",dst,i); } return i; }
7.Write a function that removes excess while space from a string of characters,The function should have this prototype:
(編寫一個函數從一個字符串中除去多余的空白,函數原型如下)
void deblank(char string[]);
Every run of one or more white space characters should be replaced by one space character.Be sure that hte string is terminated with a NUL byte When you're through with it.
(當函數發現一個或多個地方有一個或連續多個的空格組成,就把它們改成單個字符,注意當你遍歷整個字符串時要確保它以NUL字符結尾)
/*程序僅限於去除空格符,如果是制表符或者換行符或其他可能不行,這可能需要用到指針,就像標准答案中的那樣*/
void deblank(char string[])
{
int i,j; int flag = 0; for(i = 0; string[i] != '\0'; i++){ while(string[i] == ' ' && flag == 1){ for(j = i; string[j] != '\0'; j++) string[j] = string[j+1]; string[j] = '\0'; } if(string[i] == ' ') flag = 1; else flag = 0; } }