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 required
for our two binary search functions. We search for
the element -1, to time the functions' worst case
performance (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);
else
printf("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);
else
printf("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;
else
return 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;
else
low = mid + 1;
mid = (low+high) / 2;
}
if ( x == v[mid] )
return mid;
else
return -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 special
characters into their appropriate escape sequences.
The "complete set of escape sequences" found in
K&R Chapter 2 is used, with the exception of:
\? \' \ooo \xhh
as 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 sequences
into their appropriate special characters. See the comment
for escape() for remarks regarding which escape sequences
are 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 escape
sequence, 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 1000
void 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 100
int 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;
else
s[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;
}
}