本章问题
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;
}
}