E x c e r c i s e 3 − 1 Excercise\quad 3-1 Excercise3−1:输出结果如图1所示,这里故意让二分搜索算法去寻找一个在数组中不存在在的数,然后去看两种二分搜索算法分别所花费的时间的大小,为了使得所花费的时间更具有可分辨性,这里让搜索过程重复执行了 100000000 100000000 100000000次。
/* Solution by Paul Griffiths (mail@paulgriffiths.net) *//*EX3_1.C=======Suggested solution to Exercise 3-1*/#include <stdio.h>
#include <time.h>int binsearch(int x, int v[], int n); /* Original K&R function */
int binsearch2(int x, int v[], int n); /* Our new function */#define MAX_ELEMENT 200000/* Outputs approximation of processor time requiredfor our two binary search functions. We search forthe element -1, to time the functions' worst caseperformance (i.e. element not found in test data) */int main(void)
{int testdata[MAX_ELEMENT];int index; /* Index of found element in test data */int n = -1; /* Element to search for */int i;clock_t time_taken;/* Initialize test data */for ( i = 0; i < MAX_ELEMENT; ++i )testdata[i] = i;/* Output approximation of time taken for 100000000 iterations of binsearch() */for ( i = 0, time_taken = clock(); i < 100000000; ++i ) {index = binsearch(n, testdata, MAX_ELEMENT);}time_taken = clock() - time_taken;if ( index < 0 )printf("Element %d not found.\n", n);elseprintf("Element %d found at index %d.\n", n, index);printf("binsearch() took %lu clocks (%lu seconds)\n",(unsigned long) time_taken,(unsigned long) time_taken / CLOCKS_PER_SEC);/* Output approximation of time taken for 100000000 iterations of binsearch2() */for ( i = 0, time_taken = clock(); i < 100000000; ++i ) {index = binsearch2(n, testdata, MAX_ELEMENT);}time_taken = clock() - time_taken;if ( index < 0 )printf("Element %d not found.\n", n);elseprintf("Element %d found at index %d.\n", n, index);printf("binsearch2() took %lu clocks (%lu seconds)\n",(unsigned long) time_taken,(unsigned long) time_taken / CLOCKS_PER_SEC);return 0;
}/* binsearch:find x in v[0] <= v[1] <= ... v[n-1] */int binsearch(int x, int v[], int n)
{int low, mid, high;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;elsereturn mid;}return -1;
}/* binsearch2:find x in v[0] <= v[1] <= ... v[n-1] */int binsearch2(int x, int v[], int n)
{int low, mid, high;low = 0;high = n - 1;mid = (low+high) / 2; while (( low < high ) &&(x != v[mid])){if ( x < v[mid] )high = mid - 1;elselow = mid + 1;mid = (low+high) / 2; }if ( x == v[mid] )return mid;elsereturn -1;
}
E x c e r c i s e 3 − 2 Excercise\quad 3-2 Excercise3−2:输出结果如图2所示
#include <stdio.h>void escape(char s[], char t[]);
void unescape(char s[], char t[]);
int main(void)
{char text1[100] = "\aHello,\n\tWorld! Mistakee\b was \"Extra 'e'\"!\n";char text2[100];char text3[100]; printf("Original string:\n%s\n", text1);escape(text2, text1);printf("Escaped string:\n%s\n", text2);unescape(text2, text3);printf("Unescaped string:\n%s\n", text3);return 0;
}/* Copies string t to string s, converting specialcharacters into their appropriate escape sequences.The "complete set of escape sequences" found inK&R Chapter 2 is used, with the exception of:\? \' \ooo \xhhas these can be typed directly into the source code,(i.e. without using the escape sequences themselves)and translating them is therefore ambiguous. */
void escape(char s[], char t[])
{int i=0;int j=0;while ( t[i]!='\0' ) {switch (t[i]){case '\t':s[j++]='\\';s[j++]='t'; break;case '\n':s[j++]='\\';s[j++]='n'; break; case '\a':s[j++]='\\';s[j++]='a'; break;case '\b':s[j++]='\\';s[j++]='b'; break;case '\f':s[j++]='\\';s[j++]='f'; break;case '\r':s[j++]='\\';s[j++]='r'; break;case '\v':s[j++]='\\';s[j++]='v'; break; case '\"':s[j++]='\\';s[j++]='\"'; break;case '\\':s[j++]='\\';s[j++]='\\'; break; default:s[j++]=t[i]; break; }i++;}s[j]='\0';
}/* Copies string s to string t, converting escape sequencesinto their appropriate special characters. See the commentfor escape() for remarks regarding which escape sequencesare translated. */
void unescape(char s[], char t[])
{int i=0;int j=0;while ( s[i]!='\0' ) {switch (s[i]){case '\\':switch (s[++i]){case 't':t[j++]='\t'; break;case 'n':t[j++]='\n'; break; case 'a':t[j++]='\a'; break;case 'b':t[j++]='\b'; break;case 'f':t[j++]='\f'; break;case 'r':t[j++]='\r'; break;case 'v':t[j++]='\v'; break;case '\"':t[j++]='\"'; break;case '\\':t[j++]='\\'; break;default:/* We don't translate this escapesequence, so just copy it verbatim */ t[j++] = '\\';t[j++] = t[i]; } break; default:t[j++]=s[i]; break; }++i;}t[j]='\0';
}
E x c e r c i s e 3 − 3 Excercise\quad 3-3 Excercise3−3:输出结果如图3所示。
#include <stdio.h>#define MAXIMUM 1000void expand(char s1[], char s2[]);
int is_valid(char c);int main()
{char s1[MAXIMUM] = "-A-C-E-I first a-z0-9 second -a-z third 9-2 fourth 6-6- end-"; char s2[MAXIMUM];printf("%s\n", s1);expand(s1, s2);printf("%s\n", s2);return 0;
}void expand(char s1[], char s2[])
{char c, d;int i, j;i = j = 0;while ('\0' != (c = s1[i++])) {if (is_valid(c) && '-' == s1[i] && is_valid(s1[i + 1])) {i++;d = s1[i];if (c > d) {while (c > d) {s2[j++] = c--;}}else {while (c < d) {s2[j++] = c++;}}}else {s2[j++] = c;}}s2[j] = '\0';
}int is_valid(char c)
{if(((c>='a') && (c<='z')) || ((c>='A') && (c<='Z')) || ((c>='0') && (c<='9'))){return 1;}else{return 0;}
}
E x c e r c i s e 3 − 4 Excercise\quad 3-4 Excercise3−4:下面我们首先来看一段代码以及输出,输出结果如图4所示。这里 i n t int int型变量能表示的数的最大范围是 [ − 2147483648 , 2147483647 ] [-2147483648,2147483647] [−2147483648,2147483647],这里我们可以看到 i n t int int型可以表示的最大负数的绝对值要比 i n t int int型可以表示的最大正数的值大一(其它类型的有符号数的类型也是一样的),当我们在尝试使用书中的那个版本的 i t o a itoa itoa接口来将 i n t int int型可以表示的最大负数 − 2147483648 -2147483648 −2147483648转换为字符串的时候会出现问题。书中的那个版本的 i t o a itoa itoa接口会首先将要转换的负数变成正数,但是对于 i n t int int型,它可以表示的最大正数是 2147483647 2147483647 2147483647,因此从图4中我们可以看到 i n t u = − i ; int u=-i; intu=−i;操作之后 u u u的值还是 − 2147483648 -2147483648 −2147483648,因此书中的那个版本的 i t o a itoa itoa接口中的 d o w h i l e do\quad while dowhile循环只会运行一次且就算是这一次对个位数的转换也是错误的,这是因为这一次循环中 n % 10 n\%10 n%10操作的结果是 − 8 -8 −8,因此 n % 10 + ′ 0 ′ n\%10+'0' n%10+′0′操作的结果是 40 40 40(字符 ′ 0 ′ '0' ′0′的 A S C I I ASCII ASCII码值是48,字符 ′ ( ′ '(' ′(′的 A S C I I ASCII ASCII码值是40,),因此这里并没有得到我们所预期的字符 ′ 8 ′ '8' ′8′。为了能够成功实现对 i n t int int型可以表示的最大负数的转换,改进后的程序在判断 d o w h i l e do\quad while dowhile循环的执行的时候改为 w h i l e ( n / = 10 ) ; while ( n /= 10 ); while(n/=10);,而不是 w h i l e ( ( n / = 10 ) > 0 ) ; while( ( n /= 10 )>0); while((n/=10)>0);也就是不为0就可以继续执行循环,且改进后的程序在求余数之后做了绝对值的操作。
#include <stdio.h>
#include <limits.h>int main(void)
{char c='\0';printf("sizeof(int)=%d\n",sizeof(int));printf("Signed int[%d to %d]\n", INT_MIN, INT_MAX);printf("Unsigned int[0 to %u]\n", UINT_MAX);int i=-2147483648;int u=-i; printf("i=%d\n",i); printf("u=%d\n",u); c=(u%10)+'0';printf("c=%d\n",c); printf("c=%c\n",c); return 0;
}
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>void itoa_myself(int n, char s[]);
void reverse(char s[]);int main(void)
{char buffer[100];printf("INT_MIN: %d\n", INT_MIN);itoa_myself(INT_MIN, buffer);printf("Buffer : %s\n", buffer);return 0;
}void itoa_myself(int n, char s[])
{int i, sign;sign = n;i = 0;do {s[i++] = abs(n % 10) + '0';} while ( n /= 10 );if (sign < 0)s[i++] = '-';s[i] = '\0';reverse(s);
}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;}
}
E x c e r c i s e 3 − 5 Excercise\quad 3-5 Excercise3−5:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>void itob(int n , char s[], int b);
void reverse(char s[]);#define MAXIMUM 100int main(){int b = 16;char s[MAXIMUM];itob(-2147483648,s,b);printf("Base %d = %s\n",b,s);return 0;
}void itob(int n, char s[], int b)
{int i = 0;int negative=0;if(n<0){negative=-1; }if((b!=2) && (b!=8) && (b!=16)) { printf("base error\n"); } do{if (abs(n%b)>9)s[i++]= abs(n%b) +'A'-10;elses[i++] = abs(n%b) +'0';} while ((n/=b));if(negative==-1){s[i++]='-'; }s[i] = '\0'; reverse(s);
}void reverse (char s[])
{int i , j , c;for (i = 0, j = strlen(s)-1; i < j; i++,j--)c = s[i], s[i]=s[j], s[j]=c;
}
E x c e r c i s e 3 − 6 Excercise\quad 3-6 Excercise3−6:
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <string.h>void itoa_myself(int n, char s[], int minmum);
void reverse(char s[]);int main(void)
{char buffer[100];printf("INT_MIN: %d\n", INT_MIN);itoa_myself(INT_MIN, buffer,25);printf("Buffer : %s\n", buffer);return 0;
}void itoa_myself(int n, char s[], int minmum)
{int i, sign;sign = n;i = 0;do {s[i++] = abs(n % 10) + '0';} while ( n /= 10 );if (sign < 0)s[i++] = '-';while(i<minmum){s[i++] = ' '; } s[i] = '\0';reverse(s);
}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;}
}