700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > 《C程序设计语言》 第三章 控制流

《C程序设计语言》 第三章 控制流

时间:2020-01-17 20:20:23

相关推荐

《C程序设计语言》 第三章 控制流

3.1 语句与程序块

在表达式之后加上一个分号(;),它们就变成了语句。 用一对花括号“{”与“}”把一组声明和语句括在一起就构成了程序块,在语法上等价于单条语句。

3.2 if-else语句

每个else与最近的前一个没有else配对的if进行匹配。

if (n > 0) if (a > b)z = a; else z = b;

程序的缩进结构明确表明了设计意图,但编译器无法获得这一信息,它会将else部分与内层的if配对。

3.3 else-if语句

/* binsearch: find x in v[0] <= v[1] <= ... <= v[n-1] */ int binsearch(int x, int v[], int n) {int low, high, mid; low = 0; high = n - 1; while (low <= high) {mid = (low + high) / 2;if (x < v[mid]) high = mid + 1;else if (x > v[mid]) low = mid + 1;else /* found match */ return mid; } return -1; }

练习3-1 上面折半查找的例子中,while循环语句内执行了两次测试。重写该函数, 使循环内部只执行一次测试。比较两种版本函数的运行时间。 答: while (low <= high) {mid = (low + high) / 2; if (x < v[mid])high = mid +1; elselow = mid + 1; } if (x == v[mid]) return mid; else return -1;

3.4 switch语句

case的作用只是一个标号,从某个分支中的代码执行完后,程序将进入下一分支继续执行。 跳出switch语句最常用的方法是使用break和return语句。

作为一种良好的程序设计风格,在switch语句最后的default分支后面也加上一个break语句。 这样做在逻辑上没有必要,但当我们需要向该switch语句后添加其他分支时,这样会降低犯 错误的可能性。

练习3-2 编写一个函数escape(s, t),将字符串t复制到字符串s中,并在复制过程中将换行符、 制表符等不可见字符分别转换为\n、\t等相应可见的转义字符。再编写一个相反功能的函数。 答: #include <stdio.h> void escape(char s[], char t[])

{

int i, j;

for (i = 0, j = 0; s[i] != '\0'; i++) {

switch (s[i]) {

case '\n':

t[j++] = '\\';

t[j++] = 'n';

break;

case '\t':

t[j++] = '\\';

t[j++] = 't';

break;

default:

t[j++] = s[i];

break;

}

}

t[j] = '\0';

}

void escape2(char s[], char t[])

{

int i, j;

for (i = 0, j = 0; s[i] != '\0'; j++) {

switch (s[i]) {

case '\\':

if (s[i+1] == 'n') {

t[j] = '\n';

i += 2;

}

else if (s[i+1] == 't') {

t[j] = '\t';

i += 2;

}

else {

t[j] = s[i];

i++;

}

default:

t[j] = s[i++];

break;

}

}

}

main()

{

char s[] = "this is cdai";

char t[20];

escape(s, t);

printf("%s\n", t);

char t2[20];

escape2(t, t2);

printf("%s\n", t2);

}

3.5 while循环与for循环

for (表达式1; 表达式2; 表达式3) 语句

等价于=>

表达式1; while (表达式2) {语句 表达式3; }

逗号运算符“,”在for语句中经常用到。被逗号分隔的一对表达式将按照从左到右的顺序进行求值, 分隔函数参数的逗号,分隔声明中变量的逗号等不是逗号运算符,不保证从左至右顺序求值。

/* reverse: reverse string s in place */ void reverse(char s[]) {int c, i, j; for (i = 0, j = strlen(s) - 1; i < j; i++, j--)c = s[i], s[i] = s[j], s[j] = c; }

练习3-3 编写函数expand(s1, s2),将字符串s1中类似于a-z一类的速记符号在字符串s2中 扩展为等价的完整列表abc...xyz。该函数可以处理大小写字母和数字,并可以处理a-b-c、 a-z0-9与-a-z等类似的情况。作为前导和尾随的-字符原样排印。 答: #include <stdio.h>

void expand(char s1[], char s2[])

{

int i, j, k;

i = j = 0;

while (s1[i] != '\0') {

if (s1[i] == '-' && 0 < i && s1[i+1] != '\0' &&

s1[i-1] != '-' && s1[i+1] != '-') {

j--; // avoid duplicate letter

for (k = s1[i-1]; k <= s1[i+1]; k++, j++)

s2[j] = k;

i += 2;

} else {

s2[j++] = s1[i++];

}

}

s2[j] = '\0';

}

main()

{

char s1[] = "-a-b-hAbC-G0-8---";

char s2[100];

expand(s1, s2);

printf("before expand:%s\nafter expand: %s\n", s1, s2);

}

3.6 do-while循环

/* itoa: convert n to characters in s */ void itoa(int n, char s[]) {int i, sign; if ((sign = n) < 0) /* record sign and make n positive */n = -n;

i = 0; do { /* generate digits in reverse order */s[i++] = n % 10 + '0'; /* convert number to char */ } while ((n /= 10) > 0);if (sign < 0)s[i++] = '-'; s[i] = '\0'; reverse(s); }

这里使用do-while语句会方便一些,因为即使n为0,也至少要把一个字符放到数组s中。 do-while中只有一条语句,(没有必要)但扔用花括号括起来,因为可以避免将while误认为 是另个while循环的开始。

练习3-4 在数的对二的补码表示中,上面的itoa函数不能处理最大的负数-2的(字长-1)次方 的情况。解释其原因,并修改函数使它在任何机器上运行时都能打印出正确的值。 答: 例如char字长为8位,则对二补码范围为-128~127。值为-128的char,n=-n;后值仍为-128。 128的二进制源码为01111111,通过补码的负数转换规则得到10000000,即-128二进制码为80(可用prinf("%hhx);验证)。

修改函数,不将n转为正数,而是将每次取模运算的结果转为正数。从而避开无法将最大负数转为正数的问题。 #include <stdio.h> #define abs(x) ((x) < 0 ? -(x) : (x))

void itoa(int n, char s[])

{

int i, sign;

sign = n;

i = 0;

do {

s[i++] = abs(n % 10) + '0';

} while ((n /= 10) != 0);

if (sign < 0)

s[i++] = '-';

s[i] = '\0';

//reverse(s);

}

main()

{

char s[20];

itoa(10, s);

printf("%s\n", s);

itoa(-128, s);

printf("%s\n", s);

}

练习3-5 编写函数itob(n, s, b),将整数n转换为以b为底的数,并将转换结果以字符的形式 保存到字符串s中。例如,itob(n, s, 16)把整数n格式化为十六进制整数保存在s中。 答: #include <stdio.h>

#include "reverse.c"

#define abs(x) (x) < 0 ? -(x) : (x)

void itob(int n, char s[], int b)

{

int i, x, sign;

sign = n;

i = 0;

do {

x = abs(n % b);

if (x >= 10)

s[i++] = (x - 10) + 'A';

else

s[i++] = x + '0';

} while ((n /= b) != 0);

if (sign < 0)

s[i++] = '-';

s[i] = '\0';

reverse(s);

}

main()

{

char s[20];

itob(29, s, 2);

printf("%s\n", s);

itob(-257, s, 16);

printf("%s\n", s);

}

练习 3-6 修改itoa函数,使得该函数可以接收三个参数。第三个参数为最小字段宽度。 为了保证转换后结果至少具有第三个参数指定的最小宽度,必要时在结果左边填充一定的空格。 答: ... if (sign < 0) s[i++] = '-'; while (i <= w-1) // fill space s[i++] = ' '; ...

3.7 break和continue语句

3.8 goto语句与标号

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。