C程序设计语言(第2版)
这儿有一篇写的很好的读后感:http://www.cnblogs.com/xkfz007/articles/2566424.html
第1章 导言
1. 单词计数
int main(){
int c,nl,nw,nc,flag;
flag=0;
nl=nw=nc=0;
while((c=getchar())!=EOF){
++nc;
if(c=='\n')
nl++;
if(c==' '||c=='\n'||c=='\t')
flag=0;
else if(!flag){
flag=1;
++nw;
}
}
printf("%3d %3d %3d\n",nl,nw,nc);
return 0;
}
2. 函数参数——传值调用
在C语言中,所有函数参数都是通过"值"传递的。也就是说,传递给被调用函数的参数值存放在临时变量中,而不是存放在原来的变量中。这与其他某些语言是不同的。比如,Fortran等语言是通过"引用"调用,Pascal则采用var参数方式,在这些语言中,被调用的函数必须访问原始参数,而不是访问参数的本地副本。
最主要的区别在于,在C语言中,被调用函数不能直接修改主调函数中变量的值,而只能修改其私有临时副本的值。
传值调用的利大于弊。在被调用该函数中,参数可以看作是便于初始化的局部变量,因此额外使用的变量更少。这样程序可以更紧凑简洁。
3. 读入一组文本,打印出最长文本
int getline_(char s[],int lim){
int c,i;
i=0;
while(i<lim-1&&(c=getchar())!=EOF&&c!='\n'){
s[i++]=c;
}
if(c==EOF&&i==0)
return -1;
if(c=='\n')
s[i++]=c;
s[i++]='\0';
return i;
}
void copy(char str1[],char str2[]){
while((*str1++=*str2++)!='\0');
}
int main(){
char line[256];
char longest[256];
char shortest[256];
int len;
int max=0,min=256;
while((len=getline_(line,256))>-1){
if(len>=max)
{
max=len;
copy(longest,line);
}
else if(len<=min)
{
min=len;
copy(shortest,line);
}
}
if(max>0)
printf("%d:%s",max,longest);
if(min<256)
printf("%d:%s",min,shortest);
return 0;
}
下面是输出结果,输入是上面的源代码:
课后题程序:
习题1-8 编写一个统计空格、制表符和换行符个数的程序。
int main(){
int c,nb,nt,nl;
nb=0;
nt=0;
nl=0;
while((c=getchar())!=EOF){
if(c==' ')
nb++;
else if(c=='\t')
nt++;
else if(c=='\n')
nl++;
}
printf("%2d %2d %2d\n",nb,nt,nl);
}
习题1-9 编写一个将输入复制到输出的程序,并将其中连续的多个空格使用一个空格代替
int main(){
int c;
int nb;
int prec=-1;
while((c=getchar())!=EOF){
if(c==' '&&prec==' ')
continue;
else
{
putchar(c);
prec=c;
}
}
}
习题1-12 编写一个程序,以每行一个单词的形式打印其输入
int c;
int flag;
flag=0;
while((c=getchar())!=EOF){
if(c==' '||c=='\n'||c=='\t'){
if(flag){
putchar('\n');
flag=0;
}
}
else if(!flag){
flag=1;
putchar(c);
}
else{
putchar(c);
}
}
}
习题1-13 编写一个程序,打印输入中单词长度的直方图。水平方向的直方图比较容易绘制,垂直方向的直方图则要困难写。
#define MAXHIST 15
#define MAXWORD 11
int word_stats(int wl[]){
int flag;
int c,nc,i,ovflow;
flag=0;
nc=0;
ovflow=0;
for(i=0;i<MAXWORD;i++)
wl[i]=0;
while((c=getchar())!=EOF){
if(c==' '||c=='\n'||c=='\t'){
if(flag){
flag=0;
// if(nc>0)
if(nc<MAXWORD)
wl[nc]++;
else
ovflow++;
nc=0;
}
}
else if(!flag){
flag=1;
nc=1;
}
else
nc++;
}
return ovflow;
}
void hist_h(int wl[]){
int i;
int maxvlaue=0;
int len;
for(i=1;i<MAXWORD;i++)
if(wl[i]>maxvlaue)
maxvlaue=wl[i];
for(i=1;i<MAXWORD;++i){
printf("%5d - %5d :",i,wl[i]);
if(wl[i]>0){
if((len=wl[i]*MAXHIST/maxvlaue)<=0)
len=1;
}
else
len=0;
while(len>0){
putchar('*');
len--;
}
putchar('\n');
}
}
void hist_v(int wl[]){
int i,j;
int maxvlaue=0;
int len;
for(i=1;i<MAXWORD;i++)
if(wl[i]>maxvlaue)
maxvlaue=wl[i];
for(i=MAXHIST;i>0;i--){
for(j=1;j<MAXWORD;j++)
if(wl[j]*MAXHIST/maxvlaue>=i)
printf(" * ");
else
printf(" ");
putchar('\n');
}
for(i=1;i<MAXWORD;i++)
printf("%4d ",i);
putchar('\n');
for(i=1;i<MAXWORD;i++)
printf("%4d ",wl[i]);
putchar('\n');
}
int main(){
int wl[MAXWORD];
int ovflow;
ovflow=word_stats(wl);
hist_h(wl);
hist_v(wl);
if(ovflow)
printf("Overflow: %d\n",ovflow);
}
下面是以上面的源文件为输入得到的运行结果:
习题1-18 编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行
int getline_(char s[],int lim){
int c;
int i;
i=0;
while(i<lim-1&&(c=getchar())!=EOF&&c!='\n'){
s[i++]=c;
}
if(c==EOF&&i==0)
return -1;
if(c=='\n')
s[i++]=c;
s[i++]='\0';
return i;
}
int remove_(char s[]){
int i;
i=0;
while(s[i]!='\n')
++i;
--i;
while(i>=0&&(s[i]==' '||s[i]=='\t'))
--i;
if(i>=0){
s[++i]='\n';
s[++i]='\0';
}
return i;
}
int main(){
char line[256];
while(getline_(line,256)>0){
if(remove_(line)>0)
printf("%s",line);
}
}
习题1-19 编写函数rverse(s)将字符串s中的字符顺序颠倒过来。使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序。
int getline_(char s[],int lim){
int c;
int i;
i=0;
while(i<lim-1&&(c=getchar())!=EOF&&c!='\n'){
s[i++]=c;
}
if(c==EOF&&i==0)
return -1;
if(c=='\n')
s[i++]=c;
s[i++]='\0';
return i;
}
void reverse_(char s[]){
int i,j;
char c;
i=0;
while(s[i]!='\0')
i++;
i--;
if(s[i]=='\n')
i--;
j=0;
while(j<i){
c=s[i];
s[i]=s[j];
s[j]=c;
j++;
i--;
}
}
int main(){
char line[256];
while(getline_(line,256)>0){
reverse_(line);
printf("%s",line);
}
}
习题1-20
请编写程序detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止的地方。假设制表符终止的位置是固定的,比如每隔n列就会出现一个制表符终止位。n应该作为变量还是常量呢?
#define TABINC 8
int main(){
int c,nb,pos;
nb=0;
pos=1;
while((c=getchar())!=EOF){
if(c=='\t'){
nb=TABINC-(pos-1)%TABINC;
while(nb>0){
putchar(' ');
pos++;
nb--;
}
}
else if(c=='\n'){
putchar(c);
pos=1;
}
else{
putchar(c);
pos++;
}
}
}
习题1-21 编写程序entab,将空格串替换为最少数量的制表符和空格,但要保持单词之间的间隔不变。假设制表符终止位的位置与练习1-20的detab程序的情况相同。当使用一个制表符或者一个空格都可以到达下一个制表符终止位时,选用那种替换字符比较好?
#define TABINC 8
int main(){
int c,nb,nt,pos;
nb=0;
nt=0;
pos=1;
while((c=getchar())!=EOF){
if(c==' '){
if(pos%TABINC!=0)
++nb;
else{
nb=0;
nt++;
}
}
else{
while(nt>0){
putchar('\t');
nt--;
}
if(c=='\t')
nb=0;
else
while(nb>0){
putchar(' ');
nb--;
}
putchar(c);
if(c=='\n')
pos=0;
else if(c=='\t')
pos=pos+(TABINC-(pos-1)%TABINC)-1;
}
pos++;
}
}
习题1-22
#define MAXCOL 10
#define TABINC 8
char line[MAXCOL];
int exptab(int pos);
int findblnk(int pos);
int newpos(int pos);
void printl(int pos);
int main(){
int c,pos;
pos=0;
while((c=getchar())!=EOF){
line[pos]=c;
if(c=='\t')
pos=exptab(pos);
else if(c=='\n') {
printl(pos);
pos=0;
}
else if(++pos>=MAXCOL){
pos=findblnk(pos);
printl(pos);
pos=newpos(pos);
}
}
}
void printl(int pos){
int i;
for(i=0;i<pos;i++)
putchar(line[i]);
if(pos>0)
putchar('\n');
}
int exptab(int pos){
line[pos]=' ';
for(++pos;pos<MAXCOL&&pos%TABINC!=0;++pos)
line[pos]=' ';
if(pos<MAXCOL)
return pos;
else{
printl(pos);
return 0;
}
}
int findblnk(int pos){
while(pos>0&&line[pos]!=' ')
pos--;
if(pos==0)
return MAXCOL;
else
return pos+1;
}
int newpos(int pos){
int i,j;
if(pos<=0||pos>=MAXCOL)
return 0;
else{
i=0;
for(j=pos;j<MAXCOL;++j){
line[i]=line[j];
++i;
}
return i;
}
}
习题1-23 编写一个删除C语言程序中所有的注释语句。要正确处理带银行的字符串与字符常量。在C语言中,注释不允许嵌套。
void rcomment(int c);
void in_comment(void);
void echo_quote(int c);
int main(){
int c;
while((c=getchar())!=EOF)
rcomment(c);
return 0;
}
void rcomment(int c){
int d;
if(c=='/')
if((d=getchar())=='*')
in_comment();
else if(d=='/'){
putchar(c);
rcomment(d);
}
else{
putchar(c);
putchar(d);
}
else if(c=='\''||c=='"')
echo_quote(c);
else
putchar(c);
}
void in_comment(void){
int c,d;
c=getchar();
d=getchar();
while(c!='*'||d!='/'){
c=d;
d=getchar();
}
}
void echo_quote(int c){
int d;
putchar(c);
while((d=getchar())!=c){
putchar(d);
if(d=='\\')
putchar(getchar());
}
putchar(d);
}
习题1-24 编写一个程序,检查C语言程序中的基本语法错误
int brace,brack,paren;
void in_quote(int c);
void in_comment(void);
void search(int c);
int main(){
int c;
while((c=getchar())!=EOF){
if(c=='/'){
if((c=getchar())=='*')
in_comment();
else
search(c);
}
else if(c=='\''||c=='"')
in_quote(c);
else
search(c);
if(brace<0){
printf("Unbalanced braces\n");
brace=0;
}
else if(brack<0){
printf("Unbalanced brackets\n");
brack=0;
}
else if(paren<0){
printf("Unbalanced parentheses\n");
paren=0;
}
}
if(brace>0)
printf("Unbalanced braces\n");
if(brack>0)
printf("Unbalanced brackets\n");
if(paren>0)
printf("Unbalanced parentheses\n");
}
void search(int c){
if(c=='{')
++brace;
else if(c=='}')
--brace;
else if(c=='[')
++brack;
else if(c==']')
--brack;
else if(c=='(')
++paren;
else if(c==')')
--paren;
}
void in_comment(void){
int c,d;
c=getchar();
d=getchar();
while(c!='*'||d!='/'){
c=d;
d=getchar();
}
}
void in_quote(int c){
int d;
while((d=getchar())!=c)
if(d=='\\')
getchar();
}
第2章 类型,运算符与表达式
1. const限定符
任何变量的声明都可以使用const限定符限定。该限定符指定变量的值不能被修改。对于数组而言,const限定符指定数组所有元素的值都不能被修改。
const char msg[]="warning:";
const限定符也可以配合数组参数使用,它表明函数不能修改该数组元素的值。
2. char类型
char类型是小整型
3. 算术中的隐式类型转换
一般情况下,如果不含有unsigned类型,可以采用下面的方式:
注意float类型的特殊性:
当表达式中含有unsigned类型时:
函数参数中的类型转换:
4. 标准库中的伪随机数发生器函数:rand和srand
标准库中包含一个可移植的实现伪随机数发生器的函数rand以及一个初始化种子数的函数srand。rand函数中使用了强制类型转换:
/*rand:return pseudo-random integer on 0..32767*/
int rand(void)
{
next=next*1103515245+12345;
return (unsigned int)(next/65536)%32768;
}
/*srand:set seed for rand()*/
void srand(unsigned int seed){
next=seed;
}
习题2-3 编写函数htoi(s),把由十六进制数字组成的字符串(包含可选的前缀0x或0X)转换为与之等价的整型数。字符串中允许包含的数字包括:0~9,a~f以及A-F
#include <stdlib.h>
#define YES 1
#define NO 0
int htoi(char s[]){
int hexd,i,inhex,n;
i=0;
if(s[i]=='0'){
++i;
if(s[i]=='x'||s[i]=='X')
++i;
}
n=0;
inhex=YES;
while(inhex){
if(s[i]>='0'&&s[i]<='9')
hexd=s[i]-'0';
else if(s[i]>='a'&&s[i]<='f')
hexd=s[i]-'a'+10;
else if(s[i]>='A'&&s[i]<='F')
hexd=s[i]-'A'+10;
else
inhex=NO;
if(inhex==YES)
n=16*n+hexd;
i++;
}
return n;
}
int main(){
int count=10;
int i;
char s[100];
for(i=0;i<10;i++){
int num=rand()%10000;
int n;
sprintf(s,"%#0x",num);
n=htoi(s);
printf("%#0x %s %d %d \n",num,s,num,n);
}
}
一个运行结果展示:
习题2-4 重写函数squeeze(s1,s2),将字符串s1中任何与字符串s2中字符匹配的字符都删除
int i,j,k;
for(i=k=0;s1[i]!='\0';i++){
for(j=0;s2[j]!='\0'&&s2[j]!=s1[i];j++);
if(s2[j]=='\0')
s1[k++]=s1[i];
}
s1[k]='\0';
}
习题2-5
int i,j;
for(i=0;s1[i]!='\0';i++)
for(j=0;s2[j]!='\0';j++)
if(s1[i]==s2[j])
return i;
return -1;
}
5. C语言中的位操作
getbits函数:返回x中从右边数第p位开始向右数n位的字段。这里假定最右边的一位是第0位,n与p都是合理的正值。
return (x>>(p+1-n))&~(~0<<n);
}
unsigned x1=x&(~0<<(p+1));//获取x的高32-(p+1)位
unsigned x2=x&((1<<(p-n+1))-1);//获取x的低p-n+1位
unsigned y1=(y&~(~0<<n))<<(p+1-n);//获得y的最低n位,并且移动到合适的位置
return x1|x2|y1;
}
可以换一种方式写:
unsigned m1= (~0<<(p+1))| ((1<<(p-n+1))-1);//得到屏蔽码
unsigned x1=x&m1;
unsigned y1=(y&~(~0<<n))<<(p+1-n);//获得y的最低n位,并且移动到合适的位置
return x1|y1;
}
下面是一个标准答案:
这儿比较难写是就是x的屏蔽码,下面的程序是对比两种方法产生的屏蔽码:
#include <stdlib.h>
int main(){
int i;
for(i=0;i<10;i++){
int p=rand()%32;
int n=rand()%p+1;
unsigned m1=(~0<<(p+1))|((1<<(p-n+1))-1);
unsigned m2=~(~(~0<<n)<<(p+1-n));
printf("p=%d n=%d: %#0x %#0x ",p,n,m1,m2);
if(m1==m2)
printf("OK\n");
else
printf("NO\n");
}
}
一个输出结果如下:
unsigned x1=x&(~0<<(p+1));//获取x的高32-(p+1)位
unsigned x2=x&((1<<(p-n+1))-1);//获取x的低p-n+1位
unsigned x3=~x&(~(~0<<n)<<(p-n+1));//获取x的中间n位
return x1|x2|x3;
}
下面是一个标准答案
下面是一个测试:
#include <stdlib.h>
unsigned invert(unsigned x,int p,int n){
unsigned m1=(~0<<(p+1));//获取x的高32-(p+1)位
unsigned x1=x&m1;
unsigned m2=((1<<(p-n+1))-1);//获取x的低p-n+1位
unsigned x2=x&m2;
unsigned m3=(~(~0<<n)<<(p-n+1));//获取x的中间n位
unsigned x3=(~x)&m3;
printf("%#0x %#0x %#0x\n",m1,m2,m3);
return x1|x2|x3;
}
unsigned invert2(unsigned x,int p,int n){
return x^(~(~0<<n)<<(p+1-n));
}
int main(){
int i;
unsigned x=rand();
for(i=0;i<25;i++){
int p=rand()%32;
int n=rand()%p+1;
int y1=invert(x,p,n);
int y2=invert2(x,p,n);
printf("%#0x %2d %2d %#0x %#0x ",x,p,n,y1,y2);
if(y1==y2)
printf("OK\n");
else
printf("NO\n");
}
}
输出如下:
可以看到当p=31时,第一种方法就出错了。主要是将一个无符号数进行右移32位(移出所有位)时,编译器会给出一个【 warning: right shift count >= width of type】的警告。然后返回原始值,而不是0
unsigned x1=x>>n;//左移得到高32-n位
unsigned x2=x<<(sizeof(x)*8-n);//右移得到低n位
return x1|x2;
}
下面标准答案给出的解释:
int wordlength()
{
int i;
unsigned v=(unsigned)~0;
for(i=1;(v=v>>1)>0;i++)
;
return 1;
}
unsigned rightrot(unsigned x,int n){
int rbit;
while(n-->0){
rbit=(x&1)<<(wordlength()-1);
x=x>>1;
x=x|rbit;
}
return x;
}
unsigned rbits;
if((n-n%wordlength())>0){
rbits=~(~0<<n)&x;
rbits=rbits<<(wordlength()-n);
x=x>>n;
x=x|rbits;
}
return x;
}
6. 统计整型数中二进制位1的个数:
int n=0;
while(x!=0){
if(x&0x1)
n++;
x>>1;
}
return n;
}
习题 2-9 在求对二的补码时,表达式x&(x-1)可以删除x中最右边为1的一个二进制位。请解释这样做的道理。用这一方法重写bitcount函数, 以加快其执行速度。
重写的代码如下:
int b;
b=0;
while(x!=0){
b++;
x&=x-1;
}
return b;
}
第3章 程序流控制
1. 折半查找
int low,high,mid;
low=0;
high=n-1;
while(low<=high){
mid=(low+high)>>1;
if(x<v[mid])
high=mid-1;
else if(x>v[mid])
low=mid+1;
else
return mid;
}
return -1;
}
int bin_search(int x,int v[],int n){
int low,high,mid;
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;
}
2. atoi函数
字符串转换为对应数值的函数atoi
#include <ctype.h>
#include <stdlib.h>
int atoi_(char s[]){
int i,n,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(n=0;isdigit(s[i]);i++)
n=10*n+(s[i]-'0');
return sign*n;
}
int main(){
int i;
char s[20];
for(i=0;i<10;i++){
int value=rand();
int d;
if(value&0x1)
value=-value;
sprintf(s,"%d",value);
d=atoi_(s);
printf("%12d %12s %12d ",value,s,d);
if(value==d)
printf("OK\n");
else
printf("NO\n");
}
}
测试输出如下:
希尔排序shell
shell算法是D.L. Shell于1959年发明的,基本思想是:先比较近距离的元素,而不是像简单交换排序算法那样先比较相邻的元素。这样可以快速减少大量的无序情况,从而减轻后序的工作。被比较的元素之间的距离逐步减少,直到减少为1,这时编程了相邻元素的互换。
#include <stdlib.h>
void shellsort(int v[],int n){
int gap,i,j,temp;
for(gap=n/2;gap>0;gap/=2)
for(i=gap;i<n;i++)
for(j=i-gap;j>=0&&v[j]>v[j+gap];j-=gap){
temp=v[j];
v[j]=v[j+gap];
v[j+gap]=temp;
}
}
void print_arr(int v[],int n){
int i;
for(i=0;i<n;i++)
printf("%4d",v[i]);
printf("\n");
}
int main(){
int i;
for(i=0;i<10;i++){
int arr[20],j,b[20];
for(j=0;j<20;j++)
{
int val=rand()%1000;
arr[j]=val;
b[j]=val;
}
printf("before:");
print_arr(b,20);
shellsort(arr,20);
printf("after :");
print_arr(arr,20);
}
}
测试输出如下:
习题 3-3 讲些函数expand(s1,s2),将字符串s1中类似于a-z一类的速记符号在字符串s2中扩展为等价的完整列表abc...xyz。该函数可以处理大小写字母和数字,并且可以处理a-b-c,a-z0-9与a-z等类似的情况。作为前导和尾随的字符原样复制。
void expand(char s1[],char s2[]){
char c;
int i,j;
i=0;
j=0;
while((c=s1[i++])!='\0'){
if(s1[i]=='-'&&s1[i+1]>=c){
i++;
while(c<s1[i])
s2[j++]=c++;
}
else
s2[j++]=c;
}
s2[j]='\0';
}
函数itoa:将整型数转化为字符串
void itoa(int n,char s[]){
int i,sign;
int x,y;
if((sign=n)<0)
n=-n;
i=0;
do{
s[i++]=n%10+'0';
}
while((n/=10)>0);
if(sign<0)
s[i++]='-';
s[i]='\0';
for(x=0,y=i-1;x<y;x++,y--) {
char c=s[x];
s[x]=s[y];
s[y]=c;
}
}
int atoi_(char s[]){
int i,n,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(n=0;isdigit(s[i]);i++)
n=10*n+(s[i]-'0');
return sign*n;
}
int main(){
int i;
char s[20];
for(i=0;i<10;i++){
int val=rand();
int d;
itoa(val,s);
d=atoi_(s);
printf("%12d %12s %12d ",val,s,d);
if(val==d)
printf("OK\n");
else
printf("NO\n");
}
}
测试结果如下:
习题3-4
int i,sign;
int x,y;
sign=n;
i=0;
do{
s[i++]= ABS(n%10)+'0';
}
while((n/=10)!=0);
if(sign<0)
s[i++]='-';
s[i]='\0';
for(x=0,y=i-1;x<y;x++,y--) {
char c=s[x];
s[x]=s[y];
s[y]=c;
}
}
习题 3-5 编写函数itob(n,s,b),将整数n转换为以b为底的数,并将结果以字符的形式保存到字符串s中。例如,itob(n,s,16)把整数n格式化为十六进制整数保存在s中。
#define ABS(x) ((x)<0?-(x):(x))
void itob(int n,char s[],int b){
int i,j,sign;
int x,y;
sign=n;
i=0;
do{
j=ABS(n%b);
s[i++]=(j<10)?j+'0':j+'a'-10;
}
while((n/=b)!=0);
if(sign<0)
s[i++]='-';
s[i]='\0';
for(x=0,y=i-1;x<y;x++,y--) {
char c=s[x];
s[x]=s[y];
s[y]=c;
}
}
void test_10(){
int i;
char s[20];
for(i=0;i<10;i++){
int val=rand();
int d;
if(val&0x1)
val=-val;
itob(val,s,10);
sscanf(s,"%d",&d);
printf("%12d %12s %12d ",val,s,d);
if(val==d)
printf("OK\n");
else
printf("NO\n");
}
}
void test_8(){
int i;
char s[20];
for(i=0;i<10;i++){
int val=rand();
int d;
if(val&0x1)
val=-val;
itob(val,s,8);
// d=atoi_(s);
sscanf(s,"%o",&d);
printf("%#14o %14s %#14o ",val,s,d);
if(val==d)
printf("OK\n");
else
printf("NO\n");
}
}
void test_16(){
int i;
char s[40];
for(i=0;i<10;i++){
int val=rand();
int d;
if(val&0x1)
val=-val;
itob(val,s,16);
sscanf(s,"%x",&d);
printf("%#14x %14s %#14x ",val,s,d);
if(val==d)
printf("OK\n");
else
printf("NO\n");
}
}
int main(){
printf("base-10\n");
test_10();
printf("=========================\n");
printf("base-8\n");
test_8();
printf("=========================\n");
printf("base-16\n");
test_16();
}
我们在测试程序中进行8,10和16三种进制的测试。主要是C语言提供到这三种进制的转换,这样便于我们的测试。
测试结果如下:
函数trim:用于删除字符串尾部的空格、制表符与换行符。当发现最右边的字符为非空格符、非制表符、非换行符时,就使用break语句从循环中退出。
int trim(char s[]){
int i;
for(i=strlen(s)-1;i>=0;i--)
if(s[i]!=' '&&s[i]!='\t'&&s[i]!='\n')
break;
s[i+1]='\0';
return i;
}
第4章 函数与程序结构
1. 实现类似UNIX系统上的grep类似的功能:strindex
#define MAXLINE 1000
char pattern[]="line";
int getline_(char line[],int lim){
int i,c;
i=0;
while(i<lim-1&&((c=getchar())!=EOF)&&c!='\n')
line[i++]=c;
if(c==EOF&&i==0)
return -1;
if(c=='\n')
line[i++]=c;
line[i]='\0';
return i;
}
int strindex(char src[],char itm[]){
int i,j;
// int len1=strlen(src);
// int len2=strlen(itm);
for(i=0;src[i]!='\0';i++){
int k;
for(j=0,k=i;itm[j]!='\0'&&itm[j]==src[k];j++,k++);
if(itm[j]=='\0')
return i;
}
return -1;
}
int main(){
char line[MAXLINE];
int found=0;
while(getline_(line,MAXLINE)>0)
if(strindex(line,pattern)>=0){
printf("%s",line);
found++;
}
}
习题 4-1 编写函数strrindex(s,t),它返回字符串t在s中最右边出现的位置。如果s中不包含t,则返回-1
int i,j;
int pos=-1;
for(i=0;s[i]!='\0';i++){
int k;
for(j=0,k=i;t[j]!='\0'&&t[j]==s[k];j++,k++);
if(t[j]=='\0')
pos=i;
}
return pos;
}
int i,j;
int ls=strlen(s);
int lt=strlen(t);
for(i=ls-lt;i>=0;i--){
int k;
for(j=0,k=i;t[j]!='\0'&&t[j]==s[k];j++,k++);
if(t[j]=='\0')
return i;
}
return -1;
}
函数atof:将字符串转换为浮点数
#include <ctype.h>
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
return sign*val/power;
}
int main(){
int i;
for(i=0;i<25;i++){
double val=rand()%100000/100.0;
char s[20];
double val2;
sprintf(s,"%f",val);
val2=atof_(s);
printf("%10.5f %12s %10.5f\n",val,s,val2);
}
}
习题4-2 对atof函数进行扩充,使他可以处理形如:
123.45e-6
的科学表示法,其中浮点数后面可能会紧跟一个e或E以及一个指数(可能有正负号)。
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
4.3 外部变量
一个简单的计算器程序
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
#define MAXVAL 1000
int sp=0;
double val[MAXVAL];
void push(double f){
if(sp<MAXVAL)
val[sp++]=f;
else
printf("error:stack full\n");
}
double pop(void){
if(sp>0)
return val[--sp];
else
printf("error:stack empty\n");
return 0.0;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
#define MAXOP 1000
#define NUMBER '0'
int getop(char s[]){
int i,c;
while((s[0]=c=getch())==' '||c=='\t')
;
s[1]='\0';
if(!isdigit(c)&&c!='.')
return c;
i=0;
if(isdigit(c))
while(isdigit(s[++i]=c=getch()))
;
if(c=='.')
while(isdigit(s[++i]=c=getch()))
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
return NUMBER;
}
int main(){
int type;
double op2;
char s[MAXOP];
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof_(s));
break;
case '+':
push(pop()+pop());
break;
case '-':
op2=pop();
push(pop()-op2);
break;
case '*':
push(pop()*pop());
break;
case '/':
op2=pop();
if(ABS(op2)>1e-10)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '\n':
printf("\t%.8g\n",pop());
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
}
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
#define MAXVAL 1000
int sp=0;
double val[MAXVAL];
void push(double f){
if(sp<MAXVAL)
val[sp++]=f;
else
printf("error:stack full\n");
}
double pop(void){
if(sp>0)
return val[--sp];
else
printf("error:stack empty\n");
return 0.0;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
#define MAXOP 1000
#define NUMBER '0'
int getop(char s[]){
int i,c;
while((s[0]=c=getch())==' '||c=='\t')
;
s[1]='\0';
if(!isdigit(c)&&c!='.'&&c!='-')
return c;
i=0;
if(c=='-')
if(isdigit(c=getch())||c=='.')
s[++i]=c;
else
{
if(c!=EOF)
ungetch(c);
return '-';
}
if(isdigit(c))
while(isdigit(s[++i]=c=getch()))
;
if(c=='.')
while(isdigit(s[++i]=c=getch()))
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
return NUMBER;
}
int main(){
int type;
double op2;
char s[MAXOP];
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof_(s));
break;
case '+':
push(pop()+pop());
break;
case '-':
op2=pop();
push(pop()-op2);
break;
case '*':
push(pop()*pop());
break;
case '/':
op2=pop();
if(ABS(op2)>1e-10)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '%':
op2=pop();
if(ABS(op2)>1e-10)
push(fmod(pop(),op2));
else
printf("error:zero divisor\n");
break;
case '\n':
printf("\t%.8g\n",pop());
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
}
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
#define MAXVAL 1000
int sp=0;
double val[MAXVAL];
void push(double f){
if(sp<MAXVAL)
val[sp++]=f;
else
printf("error:stack full\n");
}
double pop(void){
if(sp>0)
return val[--sp];
else
printf("error:stack empty\n");
return 0.0;
}
void clear(void){
sp=0;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
#define MAXOP 1000
#define NUMBER '0'
int getop(char s[]){
int i,c;
while((s[0]=c=getch())==' '||c=='\t')
;
s[1]='\0';
if(!isdigit(c)&&c!='.'&&c!='-')
return c;
i=0;
if(c=='-')
if(isdigit(c=getch())||c=='.')
s[++i]=c;
else
{
if(c!=EOF)
ungetch(c);
return '-';
}
if(isdigit(c))
while(isdigit(s[++i]=c=getch()))
;
if(c=='.')
while(isdigit(s[++i]=c=getch()))
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
return NUMBER;
}
int main(){
int type;
double op1,op2;
char s[MAXOP];
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof_(s));
break;
case '+':
push(pop()+pop());
break;
case '-':
op2=pop();
push(pop()-op2);
break;
case '*':
push(pop()*pop());
break;
case '/':
op2=pop();
if(ABS(op2)>1e-10)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '%':
op2=pop();
if(ABS(op2)>1e-10)
push(fmod(pop(),op2));
else
printf("error:zero divisor\n");
break;
case '?':
op2=pop();
printf("\t%.8g\n",op2);
push(op2);
break;
case 'c':
clear();
break;
case 'd':
op2=pop();
push(op2);
push(op2);
break;
case 's':
op1=pop();
op2=pop();
push(op1);
push(op2);
case '\n':
printf("\t%.8g\n",pop());
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
}
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#include <string.h>
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
#define MAXVAL 1000
int sp=0;
double val[MAXVAL];
void push(double f){
if(sp<MAXVAL)
val[sp++]=f;
else
printf("error:stack full\n");
}
double pop(void){
if(sp>0)
return val[--sp];
else
printf("error:stack empty\n");
return 0.0;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
void mathfnc(char s[]){
double op2;
if(strcmp(s,"sin")==0)
push(sin(pop()));
else if(strcmp(s,"cos")==0)
push(cos(pop()));
else if(strcmp(s,"exp")==0)
push(exp(pop()));
else if(strcmp(s,"pow")==0) {
op2=pop();
push(pow(pop(),op2));
}
else
printf("error: %s not supported\n",s);
}
#define MAXOP 1000
#define NUMBER '0'
#define NAME 'n'
int getop(char s[]){
int i,c;
while((s[0]=c=getch())==' '||c=='\t')
;
s[1]='\0';
i=0;
if(islower(c)){
while(islower(s[++i]=c=getch()))
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
if(strlen(s)>1)
return NAME;
else
return c;
}
if(!isdigit(c)&&c!='.'&&c!='-')
return c;
if(c=='-')
if(isdigit(c=getch())||c=='.')
s[++i]=c;
else
{
if(c!=EOF)
ungetch(c);
return '-';
}
if(isdigit(c))
while(isdigit(s[++i]=c=getch()))
;
if(c=='.')
while(isdigit(s[++i]=c=getch()))
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
return NUMBER;
}
int main(){
int type;
double op1,op2;
char s[MAXOP];
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof_(s));
break;
case NAME:
mathfnc(s);
break;
case '+':
push(pop()+pop());
break;
case '-':
op2=pop();
push(pop()-op2);
break;
case '*':
push(pop()*pop());
break;
case '/':
op2=pop();
if(ABS(op2)>1e-10)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '%':
op2=pop();
if(ABS(op2)>1e-10)
push(fmod(pop(),op2));
else
printf("error:zero divisor\n");
break;
case '\n':
printf("\t%.8g\n",pop());
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
}
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
#define MAXVAL 1000
int sp=0;
double val[MAXVAL];
void push(double f){
if(sp<MAXVAL)
val[sp++]=f;
else
printf("error:stack full\n");
}
double pop(void){
if(sp>0)
return val[--sp];
else
printf("error:stack empty\n");
return 0.0;
}
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
#define MAXOP 1000
#define NUMBER '0'
int getop(char s[]){
int i,c;
while((s[0]=c=getch())==' '||c=='\t')
;
s[1]='\0';
if(!isdigit(c)&&c!='.'&&c!='-')
return c;
i=0;
if(c=='-')
if(isdigit(c=getch())||c=='.')
s[++i]=c;
else
{
if(c!=EOF)
ungetch(c);
return '-';
}
if(isdigit(c))
while(isdigit(s[++i]=c=getch()))
;
if(c=='.')
while(isdigit(s[++i]=c=getch()))
;
s[i]='\0';
if(c!=EOF)
ungetch(c);
return NUMBER;
}
int main(){
int type,i,var=0;
double op2, v;
char s[MAXOP];
double variable[26];
for(i=0;i<26;i++)
variable[i]=0.0;
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof_(s));
break;
case '+':
push(pop()+pop());
break;
case '-':
op2=pop();
push(pop()-op2);
break;
case '*':
push(pop()*pop());
break;
case '/':
op2=pop();
if(ABS(op2)>1e-10)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '%':
op2=pop();
if(ABS(op2)>1e-10)
push(fmod(pop(),op2));
else
printf("error:zero divisor\n");
break;
case '\n':
v=pop();
printf("\t%.8g\n",v);
break;
case '=':
pop();
if(var>='A'&&var<='Z')
variable[var-'A']=pop();
else
printf("error: no variable name\n");
break;
default:
if(type>='A'&&type<='Z')
push(variable[type-'A']);
else if(type =='v')
push(v);
else
printf("error: unknown command %s\n",s);
break;
}
var=type;
}
}
#include <string.h>
#define BUFSIZE 100
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
void ungets(char s[]){
int len=strlen(s);
while(len>0)
ungetch(s[--len]);
}
int getch(void){
int c;
if(buf!=0)
c=buf;
else
c=getchar();
buf=0;
return c;
}
void ungetch(int c){
if(buf!=0)
printf("ungetch:too many characters\n");
else
buf=c;
}
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
#define MAXVAL 1000
int sp=0;
double val[MAXVAL];
void push(double f){
if(sp<MAXVAL)
val[sp++]=f;
else
printf("error:stack full\n");
}
double pop(void){
if(sp>0)
return val[--sp];
else
printf("error:stack empty\n");
return 0.0;
}
//#define BUFSIZE 100
//char buf[BUFSIZE];
//int bufp=0;
//int getch(void){
// return bufp>0?buf[--bufp]:getchar();
//}
//void ungetch(int c){
// if(bufp>=BUFSIZE)
// printf("ungetch: too many characters\n");
// else
// buf[bufp++]=c;
//}
#define MAXLINE 100
char line[MAXLINE];
int li=0;
int getline_(char line[],int lim){
int i,c;
i=0;
while(i<lim-1&&((c=getchar())!=EOF)&&c!='\n')
line[i++]=c;
if(c==EOF&&i==0)
return -1;
if(c=='\n')
line[i++]=c;
line[i]='\0';
return i;
}
#define MAXOP 1000
#define NUMBER '0'
int getop(char s[]){
int i,c;
if(line[li]=='\0')
if(getline_(line,MAXLINE)==-1)
return EOF;
else
li=0;
while((s[0]=c=line[li++])==' '||c=='\t')
;
s[1]='\0';
if(!isdigit(c)&&c!='.'&&c!='-')
return c;
i=0;
if(c=='-')
if(isdigit(c=line[li++])||c=='.')
s[++i]=c;
else
{
if(c!=EOF)
li--;
return '-';
}
if(isdigit(c))
while(isdigit(s[++i]=c=line[li++]))
;
if(c=='.')
while(isdigit(s[++i]=c=line[li++]))
;
s[i]='\0';
li--;
return NUMBER;
}
int main(){
int type;
double op2;
char s[MAXOP];
while((type=getop(s))!=EOF){
switch(type){
case NUMBER:
push(atof_(s));
break;
case '+':
push(pop()+pop());
break;
case '-':
op2=pop();
push(pop()-op2);
break;
case '*':
push(pop()*pop());
break;
case '/':
op2=pop();
if(ABS(op2)>1e-10)
push(pop()/op2);
else
printf("error:zero divisor\n");
break;
case '%':
op2=pop();
if(ABS(op2)>1e-10)
push(fmod(pop(),op2));
else
printf("error:zero divisor\n");
break;
case '\n':
printf("\t%.8g\n",pop());
break;
default:
printf("error: unknown command %s\n",s);
break;
}
}
}
快速排序
//#include <stdlib.h>
void swap(int *x,int *y){
int temp=*x;
*x=*y;
*y=temp;
}
void qsort(int v[],int left,int right){
int i,last;
if(left>=right)
return;
swap(v+left,v+(left+right)/2);
last=left;
for(i=left+1;i<=right;i++)
if(v[i]<v[left]) {
last++;
swap(v+last,v+i);
}
swap(v+left,v+last);
qsort(v,left,last-1);
qsort(v,last+1,right);
}
void Qsort(int v[],int n){
qsort(v,0,n-1);
}
void print_arr(int v[],int n){
int i;
for(i=0;i<n;i++)
printf("%4d",v[i]);
printf("\n");
}
int main(){
int i;
for(i=0;i<10;i++){
int arr[20],j,b[20];
for(j=0;j<20;j++)
{
int val=rand()%1000;
arr[j]=val;
b[j]=val;
}
printf("before:");
print_arr(b,20);
Qsort(arr,20);
printf("after :");
print_arr(arr,20);
}
}
测试结果如下:
swap宏
第5章 指针与数组
char *bs=s;
char *bt=t;
while(*s++);
while(*t++);
while(*--s==*--t){
if(t==bt||s==st)
break;
}
if(*s==*t&&t==bt&&*s!='\0')
return 1;
else
return 0;
}
while(*t&&n-->0)
*s++=*t++;
while(n-->0)
*s++='\0';
}
void strncat(char *s,char *t,int n){
strncpy(s+strlen(s),t,n);
}
int strncmp(char* s,char* t,int n){
for(;*s==*t;s++,t++)
if(*s=='\0'||--n<=0)
return 0;
return *s-*t;
}
UNIX系统中sort程序的一个简单版本,实现对输入文本的排序。
#include <string.h>
#include <stdlib.h>
#define MAXLINES 5000
char *lineptr[MAXLINES];
#define MAXLEN 1000
int getline_(char line[],int lim){
int i,c;
i=0;
while(i<lim-1&&((c=getchar())!=EOF)&&c!='\n')
line[i++]=c;
if(c==EOF&&i==0)
return -1;
if(c=='\n')
line[i++]=c;
line[i]='\0';
return i;
}
char* alloc(int len){
char *p=(char*)malloc(len*sizeof(char));
return p;
}
int readlines(char* lineptr[],int maxlines){
int len,nlines;
char *p,line[MAXLEN];
nlines=0;
while((len=getline_(line,MAXLEN))>0)
if(nlines>=maxlines||(p=alloc(len))==NULL)
return -1;
else{
line[len-1]='\0';
strcpy(p,line);
lineptr[nlines++]=p;
}
return nlines;
}
void writelines(char *lineptr[],int nlines){
int i;
for(i=0;i<nlines;i++)
printf("%s\n",lineptr[i]);
}
void swap(char **x,char **y){
char*tmp;
tmp=*x;
*x=*y;
*y=tmp;
}
void qsort_(char *v[],int left,int right){
int i,last;
if(left>=right)
return ;
swap(v+left,v+(left+right)/2);
last=left;
for(i=left+1;i<=right;i++)
if(strcmp(v[i],v[left])<0)
{
last++;
swap(v+last,v+i);
}
swap(v+left,v+last);
qsort_(v,left,last-1);
qsort_(v,last+1,right);
}
int main(){
int nlines;
int i;
if((nlines=readlines(lineptr,MAXLINES))>0){
qsort_(lineptr,0,nlines-1);
writelines(lineptr,nlines);
for(i=0;i<nlines;i++)
free(lineptr[i]);
return 0;
}
else{
printf("error: input too big to sort\n");
return 1;
}
}
根据日期计算是一年的第几天:
,{0,31,29,31,30,31,30,31,31,30,31,30,31}};
int day_of_year(int year,int month,int day){
int i,leap;
leap=year%4==0&&year%100!=0||year%400==0;
if(month<1||month>12)
return -1;
if(day<1||day>daytab[leap][month])
return -1;
for(i=1;i<month;i++)
day+=daytab[leap][i];
return day;
}
void month_day(int year,int yearday,int *pmonth,int *pday){
int i,leap;
if(year<1){
*pmonth=-1;
*pday=-1;
return ;
}
leap=year%4==0&&year%100!=0||year%400==0;
for(i=1;i<=12&&yearday>daytab[leap][i];i++)
yearday-=daytab[leap][i];
if(i>12&&yearday>daytab[leap][12]){
*pmonth=-1;
*pday=-1;
}
else{
*pmonth=i;
*pday=yearday;
}
}
习题5-13
#include <stdlib.h>
#include <string.h>
#define DEFLINES 10
#define MAXLINES 10
#define MAXLEN 100
int getline_(char line[],int lim){
int i,c;
i=0;
while(i<lim-1&&((c=getchar())!=EOF)&&c!='\n')
line[i++]=c;
if(c==EOF&&i==0)
return -1;
if(c=='\n')
line[i++]=c;
line[i]='\0';
return i;
}
void error(char *s){
printf("%s\n",s);
exit(1);
}
int main(int argc,char* argv[]){
char *p,*buf,*bufend;
char line[MAXLEN];
char *lineptr[MAXLINES];
int first,i,last,len,n,nlines;
if(argc==1)
n=DEFLINES;
else if(argc==2&&(*++argv)[0]=='-')
n=atoi(argv[0]+1);
if(n<1||n>MAXLINES)
n=MAXLINES;
for(i=0;i<MAXLINES;i++)
lineptr[i]=NULL;
if((p=buf=malloc(MAXLINES*MAXLEN))==NULL)
error("tail:cannot allocate buf");
bufend=buf+MAXLINES*MAXLEN;
last=0;
nlines=0;
while((len=getline_(line,MAXLEN))>0){
if(p+len+1>=bufend)
p=buf;
lineptr[last]=p;
strcpy(lineptr[last],line);
if(++last>=MAXLINES)
last=0;
p+=len+1;
nlines++;
}
if(n>nlines)
n=nlines;
first=last-n;
if(first<0)
first+=MAXLINES;
for(i=first;n-->0;i=(i+1)%MAXLINES)
printf("%s",lineptr[i]);
free(buf);
return 0;
}
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define NUMERIC 1
#define DECR 2
#define FOLD 4
#define DIR 8
//#define LINES 100
#define MAXLINES 100
#define MAXLEN 1000
char option=0;
int pos1=0;
int pos2=0;
int getline_(char line[],int lim){
int i,c;
i=0;
while(i<lim-1&&((c=getchar())!=EOF)&&c!='\n')
line[i++]=c;
if(c==EOF&&i==0)
return -1;
if(c=='\n')
line[i++]=c;
line[i]='\0';
return i;
}
void error(char *s){
printf("%s\n",s);
exit(1);
}
char* alloc(int len){
char *p=(char*)malloc(len*sizeof(char));
return p;
}
int readlines(char* lineptr[],int maxlines){
int len,nlines;
char *p,line[MAXLEN];
nlines=0;
while((len=getline_(line,MAXLEN))>0)
if(nlines>=maxlines||(p=alloc(len))==NULL)
return -1;
else{
line[len-1]='\0';
strcpy(p,line);
lineptr[nlines++]=p;
}
return nlines;
}
void writelines(char *lineptr[],int nlines,int decr){
int i;
if(decr)
for(i=nlines-1;i>=0;i--)
printf("%s\n",lineptr[i]);
else
for(i=0;i<nlines;i++)
printf("%s\n",lineptr[i]);
}
void swap(void**x,void**y){
void*tmp;
tmp=*x;
*x=*y;
*y=tmp;
}
void qsort_(void*v[],int left,int right,
int(*comp)(void*,void*)){
int i,last;
if(left>=right)
return ;
swap(v+left,v+(left+right)/2);
last=left;
for(i=left+1;i<=right;i++)
if(strcmp(v[i],v[left])<0)
{
last++;
swap(v+last,v+i);
}
swap(v+left,v+last);
qsort_(v,left,last-1,comp);
qsort_(v,last+1,right,comp);
}
void readargs(int argc,char*argv[]){
int c;
while(--argc>0&&(c=(*++argv)[0])=='-'||c=='+'){
if(c=='-'&&!isdigit(*(argv[0]+1)))
while(c=*++argv[0])
switch(c){
case 'd':
option|=DIR;
break;
case 'f':
option|=FOLD;
break;
case 'n':
option|=NUMERIC;
break;
case 'r':
option|=DECR;
break;
default:
printf("sort: illegal option %c\n",c);
error("usage: sort -dfnr [+pos1] [-pos2]");
break;
}
else if(c=='-')
pos2=atoi(argv[0]+1);
else if((pos1=atoi(argv[0]+1))<0)
error("usage: sort -dfnr [+pos1] [-pos2]");
}
if(argc||pos1>pos2)
error("usage: sort -dfnr [+pos1] [-pos2]");
}
#define MAXSTR 100
void substr(char *s,char *str){
int i,j,len;
len=strlen(s);
if(pos2>0&&len>pos2)
len=pos2;
else if(pos2>0&&len<pos2)
error("substr:string too short");
for(j=0,i=pos1;i<len;i++,j++)
str[j]=s[i];
str[j]='\0';
}
#define ABS(x) ((x)<0?-(x):(x))
double atof_(char s[]){
double val,power;
int i,sign;
for(i=0;isspace(s[i]);i++);
sign=(s[i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(val=0.0;isdigit(s[i]);i++)
val=10.0*val+(s[i]-'0');
if(s[i]=='.')
i++;
for(power=1.0;isdigit(s[i]);i++){
val=10.0*val+(s[i]-'0');
power*=10;
}
val= sign*val/power;
if(s[i]=='e'||s[i]=='E'){
int exp;
sign=(s[++i]=='-')?-1:1;
if(s[i]=='+'||s[i]=='-')
i++;
for(exp=0;isdigit(s[i]);i++)
exp=10*exp+(s[i]-'0');
if(sign)
while(exp-->0)
val*=10;
else
while(exp-->0)
val/=10;
}
return val;
}
int numcmp(char *s1,char *s2){
double v1,v2;
char str[MAXSTR];
substr(s1,str);
v1=atof_(str);
substr(s2,str);
v2=atof_(str);
if(v1<v2)
return -1;
else if(v1>v2)
return 1;
else
return 0;
}
//#define FOLD 4
//#define DIR 8
int charcmp(char *s,char *t){
char a,b;
int i,j,endpos;
int fold=(option&FOLD)?1:0;
int dir=(option&DIR)?1:0;
i=j=pos1;
if(pos2>0)
endpos=pos2;
else if((endpos-strlen(s))>strlen(t))
endpos=strlen(t);
do{
if(dir){
while(i<endpos&&!isalnum(s[i])&&
s[i]!=' '&&s[i]!='\0')
i++;
while(j<endpos&&!isalnum(t[j])&&
t[j]!=' '&&t[j]!='\0')
j++;
}
if(i<endpos&&j<endpos){
a=fold?tolower(s[i]):s[i];
i++;
b=fold?tolower(t[j]):t[j];
j++;
if(a==b&&a=='\0')
return 0;
}
}
while(a==b&&i<endpos&&j<endpos);
return a-b;
}
int main(int argc,char*argv[]){
char *lineptr[MAXLINES];
int nlines;
int i;
readargs(argc,argv);
if((nlines=readlines(lineptr,MAXLINES))>0){
if(option&NUMERIC)
qsort_((void**)lineptr,0,nlines-1,
(int(*)(void*,void*))numcmp);
else
qsort_((void**)lineptr,0,nlines-1,
(int(*)(void*,void*))charcmp);
writelines(lineptr,nlines,option&DECR);
for(i=0;i<nlines;i++)
free(lineptr[i]);
return 0;
}
else{
printf("error: input too big to sort\n");
return 1;
}
}
dcl一个比较不错的程序:将声明转化为文字描述或将文字描述转化为声明
#include <string.h>
#include <ctype.h>
#define MAXTOKEN 100
enum{NAME,PARENS,BRACKETS};
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
int gettoken(){
char *p=token;
int c;
while((c=getch())==' '||c=='\t')
;
if(c=='('){
if((c=getch())==')'){
strcpy(token,"()");
return tokentype=PARENS;
}
else{
ungetch(c);
return tokentype='(';
}
}
else if(c=='['){
for(*p++=c;(*p++=getch())!=']';)
;
*p='\0';
return tokentype=BRACKETS;
}
else if(isalpha(c)){
for(*p++=c;isalnum(c=getch());)
*p++=c;
*p='\0';
ungetch(c);
return tokentype=NAME;
}
else
return tokentype=c;
}
void dcl(void);
void dirdcl(void){
int type;
if(tokentype=='('){
dcl();
if(tokentype!=')')
printf("error:missing )\n");
}
else if(tokentype==NAME)
strcpy(name,token);
else
printf("error:expected name or (dcl)\n");
while((type=gettoken())==PARENS||type==BRACKETS)
if(type==PARENS)
strcat(out," function returning");
else{
strcat(out, " array");
strcat(out,token);
strcat(out," of");
}
}
void dcl(void){
int ns;
for(ns=0;gettoken()=='*';)
ns++;
dirdcl();
while(ns-->0)
strcat(out," pointer to");
}
int main(){
while(gettoken()!=EOF){
strcpy(datatype,token);
out[0]='\0';
dcl();
if(tokentype!='\n')
printf("syntax error\n");
printf("%s: %s %s\n",name,out,datatype);
}
return 0;
}
int type;
char temp[MAXTOKEN];
while(gettoken()!=EOF){
strcpy(out,token);
while((type=gettoken())!='\n')
if(type==PARENS||type==BRACKETS)
strcat(out,token);
else if(type=='*'){
sprintf(temp,"(*%s)",out);
strcpy(out,temp);
}
else if(type==NAME){
sprintf(temp,"%s %s",token,out);
strcpy(out,temp);
}
else {
printf("invalid input at %s\n",token);
}
}
printf("%s\n",out);
return 0;
}
#include <string.h>
#include <ctype.h>
#define MAXTOKEN 100
enum{NAME,PARENS,BRACKETS};
enum{NO,YES};
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];
int prevtoken=NO;
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
void errmsg(char *msg){
printf("%s",msg);
prevtoken=YES;
}
int gettoken(){
char *p=token;
int c;
if(prevtoken==YES){
prevtoken=NO;
return tokentype;
}
while((c=getch())==' '||c=='\t')
;
if(c=='('){
if((c=getch())==')'){
strcpy(token,"()");
return tokentype=PARENS;
}
else{
ungetch(c);
return tokentype='(';
}
}
else if(c=='['){
for(*p++=c;(*p++=getch())!=']';)
;
*p='\0';
return tokentype=BRACKETS;
}
else if(isalpha(c)){
for(*p++=c;isalnum(c=getch());)
*p++=c;
*p='\0';
ungetch(c);
return tokentype=NAME;
}
else
return tokentype=c;
}
void dcl(void);
void dirdcl(void){
int type;
if(tokentype=='('){
dcl();
if(tokentype!=')')
printf("error:missing )\n");
}
else if(tokentype==NAME)
strcpy(name,token);
else
errmsg("error:expected name or (dcl)\n");
while((type=gettoken())==PARENS||type==BRACKETS)
if(type==PARENS)
strcat(out," function returning");
else{
strcat(out, " array");
strcat(out,token);
strcat(out," of");
}
}
void dcl(void){
int ns;
for(ns=0;gettoken()=='*';)
ns++;
dirdcl();
while(ns-->0)
strcat(out," pointer to");
}
int main(){
while(gettoken()!=EOF){
strcpy(datatype,token);
out[0]='\0';
dcl();
if(tokentype!='\n')
printf("syntax error\n");
printf("%s: %s %s\n",name,out,datatype);
}
return 0;
}
int type;
type=gettoken();
prevtoken=YES;
return type;
}
int main(){
int type;
char temp[MAXTOKEN];
while(gettoken()!=EOF){
strcpy(out,token);
while((type=gettoken())!='\n')
if(type==PARENS||type==BRACKETS)
strcat(out,token);
else if(type=='*'){
if((type=nexttoken())==PARENS||
type==BRACKETS)
sprintf(temp,"(*%s)",out);
else
sprintf(temp,"*%s",out);
strcpy(out,temp);
}
else if(type==NAME){
sprintf(temp,"%s %s",token,out);
strcpy(out,temp);
}
else {
printf("invalid input at %s\n",token);
}
}
printf("%s\n",out);
return 0;
}
#include <string.h>
#include <ctype.h>
#define MAXTOKEN 100
enum{NAME,PARENS,BRACKETS};
enum{NO,YES};
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];
int prevtoken=NO;
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
void errmsg(char *msg){
printf("%s",msg);
prevtoken=YES;
}
int gettoken(){
char *p=token;
int c;
if(prevtoken==YES){
prevtoken=NO;
return tokentype;
}
while((c=getch())==' '||c=='\t')
;
if(c=='('){
if((c=getch())==')'){
strcpy(token,"()");
return tokentype=PARENS;
}
else{
ungetch(c);
return tokentype='(';
}
}
else if(c=='['){
for(*p++=c;(*p++=getch())!=']';)
;
*p='\0';
return tokentype=BRACKETS;
}
else if(isalpha(c)){
for(*p++=c;isalnum(c=getch());)
*p++=c;
*p='\0';
ungetch(c);
return tokentype=NAME;
}
else
return tokentype=c;
}
int compare(char **s,char **t){
return strcmp(*s,*t);
}
int typespec(void){
static char *types[]={
"char","int","void"
};
char *pt=token;
if(bsearch(&pt,types,sizeof(types)/sizeof(char*),sizeof(char*),compare)==NULL)
return NO;
else
return YES;
}
int typequal(void){
static char *typeq[]={
"const","volatile"
};
char *pt=token;
if(bsearch(&pt,typeq,sizeof(typeq)/sizeof(char*),sizeof(char*),compare)==NULL)
return NO;
else
return YES;
}
void dcl(void);
void dclspec(void){
char temp[MAXTOKEN];
temp[0]='\0';
gettoken();
do{
if(tokentype!=NAME){
prevtoken=YES;
dcl();
}
else if(typespec()==YES){
strcat(temp," ");
strcat(temp,token);
gettoken();
}
else if(typequal()==YES){
strcat(temp," ");
strcat(temp,token);
gettoken();
}
else
errmsg("unknown type in parameter list\n");
}
while(tokentype!=','&&tokentype!=')');
strcat(out,temp);
if(tokentype==',')
strcat(out,",");
}
void parmdcl(void){
do{
dclspec();
}while(tokentype==',');
if(tokentype!=')')
errmsg("missing ) in parameter declaration\n");
}
void dirdcl(void){
int type;
if(tokentype=='('){
dcl();
if(tokentype!=')')
printf("error:missing )\n");
}
else if(tokentype==NAME) {
if(name[0]=='\0')
strcpy(name,token);
}
else
prevtoken=YES;
while((type=gettoken())==PARENS||type==BRACKETS||type=='(')
if(type==PARENS)
strcat(out," function returning");
else if(type=='('){
strcat(out," function expecting");
parmdcl();
strcat(out," and returning");
}
else{
strcat(out, " array");
strcat(out,token);
strcat(out," of");
}
}
void dcl(void){
int ns;
for(ns=0;gettoken()=='*';)
ns++;
dirdcl();
while(ns-->0)
strcat(out," pointer to");
}
int main(){
while(gettoken()!=EOF){
strcpy(datatype,token);
out[0]='\0';
dcl();
if(tokentype!='\n')
printf("syntax error\n");
printf("%s: %s %s\n",name,out,datatype);
}
return 0;
}
这个网站很不错的:http://cdecl.org/
第6章 结构体
统计关键字出现的次数
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define MAXWORD 1000
struct key {
char *word;
int count;
}
keytab[]={
"auto",0,
"break",0,
"case",0,
"char",0,
"const",0,
"continue",0,
"default",0,
"do",0,
"double",0,
"else",0,
"enum",0,
"extern",0,
"float",0,
"for",0,
"goto",0,
"if",0,
"int",0,
"long",0,
"register",0,
"return",0,
"short",0,
"signed",0,
"sizeof",0,
"static",0,
"struct",0,
"switch",0,
"typedef",0,
"union",0,
"unsigned",0,
"void",0,
"volatile",0,
"while",0,
};
#define NKEYS (sizeof keytab/sizeof(keytab[0]))
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
int binsearch(char *word,struct key tab[],int n){
int cond;
int low,high,mid;
low=0;
high=n-1;
while(low<=high){
mid=(low+high)/2;
if((cond=strcmp(word,tab[mid].word))<0)
high=mid-1;
else if(cond>0)
low=mid+1;
else
return mid;
}
return -1;
}
int comment(void){
int c;
while((c=getch())!=EOF)
if(c=='*')
if((c=getch())=='/')
break;
else
ungetch(c);
return c;
}
int getword(char *word,int lim){
char *w=word;
int c,d;
while(isspace(c=getch()))
;
if(c!=EOF)
*w++=c;
if(isalpha(c)||c=='-'||c=='#'){
for(;--lim>0;w++)
if(!isalnum(*w=getch())&&*w!='-'){
ungetch(*w);
break;
}
}
else if(c=='\''||c=='"'){
for(;--lim>0;w++)
if((*w=getch())=='\\')
*++w=getch();
else if(*w==c){
w++;
break;
}
else if(*w==EOF)
break;
}
else if(c=='/')
if((d=getch())=='*')
c=comment();
else
ungetch(d);
*w='\0';
return c;
}
int main(){
int n;
char word[MAXWORD];
while(getword(word,MAXWORD)!=EOF)
if(isalpha(word[0]))
if((n=binsearch(word,keytab,NKEYS))>=0)
keytab[n].count++;
for(n=0;n<NKEYS;n++)
if(keytab[n].count>0)
printf("%4d %s\n",
keytab[n].count,keytab[n].word);
return 0;
}
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
int comment(void){
int c;
while((c=getch())!=EOF)
if(c=='*')
if((c=getch())=='/')
break;
else
ungetch(c);
return c;
}
int getword(char *word,int lim){
char *w=word;
int c,d;
while(isspace(c=getch()))
;
if(c!=EOF)
*w++=c;
if(isalpha(c)||c=='-'||c=='#'){
for(;--lim>0;w++)
if(!isalnum(*w=getch())&&*w!='-'){
ungetch(*w);
break;
}
}
else if(c=='\''||c=='"'){
for(;--lim>0;w++)
if((*w=getch())=='\\')
*++w=getch();
else if(*w==c){
w++;
break;
}
else if(*w==EOF)
break;
}
else if(c=='/')
if((d=getch())=='*')
c=comment();
else
ungetch(d);
*w='\0';
return c;
}
struct tnode{
char *word;
int match;
struct tnode *left;
struct tnode *right;
};
#define MAXWORD 100
#define YES 1
#define NO 0
int compare(char *s,struct tnode *p,int num,int *found){
int i;
char *t=p->word;
for(i=0;*s==*t;i++,s++,t++)
if(*s=='\0')
return 0;
if(i>=num){
*found=YES;
p->match=YES;
}
return *s-*t;
}
struct tnode* talloc(void){
return (struct tnode*)malloc(sizeof(struct tnode));
}
char *strdup_(char *s){
char *p;
p=(char*)malloc(strlen(s)+1);
if(p!=NULL)
strcpy(p,s);
return p;
}
struct tnode* addtreex(struct tnode*p,char *w,int num,int *found){
int cond;
if(p==NULL){
p=talloc();
p->word=strdup_(w);
p->match=*found;
p->left=p->right=NULL;
}
else if((cond=compare(w,p,num,found))<0)
p->left=addtreex(p->left,w,num,found);
else if(cond>0)
p->right=addtreex(p->right,w,num,found);
return p;
}
void treeprint(struct tnode* p){
if(p!=NULL){
treeprint(p->left);
if(p->match)
printf("%s]n",p->word);
treeprint(p->right);
}
}
void freetree(struct tnode*p){
if(p!=NULL){
freetree(p->left);
freetree(p->right);
free(p->word);
}
}
int main(int argc,char *argv[]){
struct tnode *root;
char word[MAXWORD];
int found=NO;
int num;
num=(--argc&&(*++argv)[0]=='-')?atoi(argv[0]+1):6;
root=NULL;
while(getword(word,MAXWORD)!=EOF){
if(isalpha(word[0])&&strlen(word)>=num)
root=addtreex(root,word,num,&found);
found=NO;
}
treeprint(root);
freetree(root);
return 0;
}
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
int comment(void){
int c;
while((c=getch())!=EOF)
if(c=='*')
if((c=getch())=='/')
break;
else
ungetch(c);
return c;
}
int getword(char *word,int lim){
char *w=word;
int c,d;
while(isspace(c=getch()))
;
if(c!=EOF)
*w++=c;
if(isalpha(c)||c=='-'||c=='#'){
for(;--lim>0;w++)
if(!isalnum(*w=getch())&&*w!='-'){
ungetch(*w);
break;
}
}
else if(c=='\''||c=='"'){
for(;--lim>0;w++)
if((*w=getch())=='\\')
*++w=getch();
else if(*w==c){
w++;
break;
}
else if(*w==EOF)
break;
}
else if(c=='/')
if((d=getch())=='*')
c=comment();
else
ungetch(d);
*w='\0';
return c;
}
struct linklist{
int lnum;
struct linklist *ptr;
};
struct tnode{
char *word;
struct linklist *lines;
struct tnode *left;
struct tnode *right;
};
#define MAXWORD 100
#define YES 1
#define NO 0
struct tnode* talloc(void){
return (struct tnode*)malloc(sizeof(struct tnode));
}
struct linklist *lalloc(void){
return (struct linklist*)malloc(sizeof(struct linklist));
}
char *strdup_(char *s){
char *p;
p=(char*)malloc(strlen(s)+1);
if(p!=NULL)
strcpy(p,s);
return p;
}
void addln(struct tnode *p,int linenum){
struct linklist *temp;
temp=p->lines;
while(temp->ptr!=NULL&&temp->lnum!=linenum)
temp=temp->ptr;
if(temp->lnum==linenum){
temp->ptr=lalloc();
temp->ptr->lnum=linenum;
temp->ptr->ptr=NULL;
}
}
struct tnode* addtreex(struct tnode*p,char *w,int linenum){
int cond;
if(p==NULL){
p=talloc();
p->word=strdup_(w);
p->lines=lalloc();
p->lines->lnum=linenum;
p->lines->ptr=NULL;
p->left=p->right=NULL;
}
else if((cond=strcmp(w,p->word))<0)
p->left=addtreex(p->left,w,linenum);
else if(cond>0)
p->right=addtreex(p->right,w,linenum);
else
addln(p,linenum);
return p;
}
void treeprint(struct tnode* p){
struct linklist *temp;
if(p!=NULL){
treeprint(p->left);
printf("%10s: ",p->word);
for(temp=p->lines;temp!=NULL;temp=temp->ptr)
printf("%4d ",temp->lnum);
printf("\n");
treeprint(p->right);
}
}
void freetree(struct tnode*p){
if(p!=NULL){
freetree(p->left);
freetree(p->right);
free(p->word);
free(p->lines);
}
}
int noiseword(char *w){
static char *nw[]={
"a","an","and","are","in","is","of","or","that","the","this","to"
};
int cond,mid;
int low=0;
int high=sizeof(nw)/sizeof(char*)-1;
while(low<=high){
mid=(low+high)/2;
if((cond=strcmp(w,nw[mid]))<0)
high=mid-1;
else if(cond>0)
low=mid+1;
else
return mid;
}
return -1;
}
int main(int argc,char *argv[]){
struct tnode *root;
char word[MAXWORD];
int linenum=1;
root=NULL;
while(getword(word,MAXWORD)!=EOF){
if(isalpha(word[0])&&noiseword(word)==-1)
root=addtreex(root,word,linenum);
else if(word[0]=='\n')
linenum++;
}
treeprint(root);
freetree(root);
return 0;
}
表查找程序核心代码:
#include <string.h>
#include <stdlib.h>
struct nlist{
struct nlist *next;
char *name;
char *defn;
};
#define HASHSIZE 101
static struct nlist *hashtab[HASHSIZE];
unsigned hash(char *s)
{
unsigned hashval;
for(hashval=0;*s!='\0';s++)
hashval=*s+32*hashval;
return hashval%HASHSIZE;
}
struct nlist *lookup(char *s){
struct nlist *np;
for(np=hashtab[hash(s)];np!=NULL;np=np->next)
if(strcmp(s,np->name)==0)
return np;
return NULL;
}
struct nlist *install(char *name,char*defn){
struct nlist *np;
unsigned hashval;
if((np=lookup(name))==NULL){
np=(struct nlist *)malloc(sizeof(struct nlist));
if(np==NULL||(np->name=strdup(name))==NULL)
return NULL;
hashval=hash(name);
np->next=hashtab[hashval];
hashtab[hashval]=np;
}
else
free((void*)np->defn);
if((np->defn=strdup(defn))==NULL)
return NULL;
return np;
}
void undef(char*s){
int h;
struct nlist *prev,*np;
prev=NULL;
h=hash(s);
for(np=hashtab[h];np!=NULL;np=np->next){
if(strcmp(s,np->name)==0)
break;
prev=np;
}
if(np!=NULL){
if(prev==NULL)
hashtab[h]=np->next;
else
prev->next=np->next;
free(np->name);
free(np->defn);
free(np);
}
}
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define BUFSIZE 10
char buf[BUFSIZE];
int bufp=0;
int getch(void){
return bufp>0?buf[--bufp]:getchar();
}
void ungetch(int c){
if(bufp>=BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++]=c;
}
void ungets(char *s){
int len=strlen(s);
while(len>0)
ungetch(s[--len]);
}
char *strdup_(char *s){
char *p;
p=(char*)malloc(strlen(s)+1);
if(p!=NULL)
strcpy(p,s);
return p;
}
int comment(void){
int c;
while((c=getch())!=EOF)
if(c=='*')
if((c=getch())=='/')
break;
else
ungetch(c);
return c;
}
int getword(char *word,int lim){
char *w=word;
int c,d;
while(isspace(c=getch()))
;
if(c!=EOF)
*w++=c;
if(isalpha(c)||c=='-'||c=='#'){
for(;--lim>0;w++)
if(!isalnum(*w=getch())&&*w!='-'){
ungetch(*w);
break;
}
}
else if(c=='\''||c=='"'){
for(;--lim>0;w++)
if((*w=getch())=='\\')
*++w=getch();
else if(*w==c){
w++;
break;
}
else if(*w==EOF)
break;
}
else if(c=='/')
if((d=getch())=='*')
c=comment();
else
ungetch(d);
*w='\0';
return c;
}
struct nlist{
struct nlist *next;
char *name;
char *defn;
};
#define HASHSIZE 101
static struct nlist *hashtab[HASHSIZE];
unsigned hash(char *s)
{
unsigned hashval;
for(hashval=0;*s!='\0';s++)
hashval=*s+32*hashval;
return hashval%HASHSIZE;
}
struct nlist *lookup(char *s){
struct nlist *np;
for(np=hashtab[hash(s)];np!=NULL;np=np->next)
if(strcmp(s,np->name)==0)
return np;
return NULL;
}
struct nlist *install(char *name,char*defn){
struct nlist *np;
unsigned hashval;
if((np=lookup(name))==NULL){
np=(struct nlist *)malloc(sizeof(struct nlist));
if(np==NULL||(np->name=strdup_(name))==NULL)
return NULL;
hashval=hash(name);
np->next=hashtab[hashval];
hashtab[hashval]=np;
}
else
free((void*)np->defn);
if((np->defn=strdup_(defn))==NULL)
return NULL;
return np;
}
void undef(char*s){
int h;
struct nlist *prev,*np;
prev=NULL;
h=hash(s);
for(np=hashtab[h];np!=NULL;np=np->next){
if(strcmp(s,np->name)==0)
break;
prev=np;
}
if(np!=NULL){
if(prev==NULL)
hashtab[h]=np->next;
else
prev->next=np->next;
free(np->name);
free(np->defn);
free(np);
}
}
void error(int c,char *s){
printf("error:%s\n",s);
while(c!=EOF&&c!='\n')
c=getch();
}
void skipblanks(){
int c;
while((c=getch())==' '||c=='\t')
;
ungetch(c);
}
#define MAXWORD 100
void getdef(){
int c,i;
char def[MAXWORD],dir[MAXWORD],name[MAXWORD];
skipblanks();
if(!isalpha(getword(dir,MAXWORD)))
error(dir[0],"getdef:expecting a directive after #");
else if(strcmp(dir,"define")==0){
skipblanks();
if(!isalpha(getword(name,MAXWORD)))
error(name[0],"getdef:non-alpha -name expected");
else{
skipblanks();
for(i=0;i<MAXWORD-1;i++)
if((def[i]=getch())==EOF||
def[i]=='\n')
break;
def[i]='\0';
if(i<=0)
error('\n',"getdef:incomplete define");
else
install(name,def);
}
}
else if(strcmp(dir,"undef")==0){
skipblanks();
if(!isalpha(getword(name,MAXWORD)))
error(name[0],"getdef:non-alpha in undef");
else
undef(name);
}
else
error(dir[0],"getdef:expecting a directive after #");
}
int main(){
char w[MAXWORD];
struct nlist *p;
while(getword(w,MAXWORD)!=EOF){
if(strcmp(w,"#")==0)
getdef();
else if(!isalpha(w[0]))
printf("%s",w);
else if((p=lookup(w))==NULL)
printf("%s",w);
else
ungets(p->defn);
}
return 0;
}
第7章 输入与输出
变长参数列表
#include <stdarg.h>
void minprintf(char *fmt,...){
va_list ap;
char *p,*sval;
int ival;
double dval;
va_start(ap,fmt);
for(p=fmt;*p;p++){
if(*p!='%'){
putchar(*p);
continue;
}
switch(*++p){
case 'd':
ival=va_arg(ap,int);
printf("%d",ival);
break;
case 'f':
dval=va_arg(ap,double);
printf("%f",dval);
break;
case 's':
for(sval=va_arg(ap,char*);*sval;sval++)
putchar(*sval);
break;
default:
putchar(*p);
break;
}
}
va_end(ap);
}
int main(){
int a=3;
double d=8.7;
minprintf("%d %f\n",a,d);
}
#include <stdarg.h>
#include <ctype.h>
#define LOCALFMT 100
void minprintf(char *fmt,...){
va_list ap;
char *p,*sval;
char localfmt[LOCALFMT];
int ival,i;
unsigned uval;
double dval;
va_start(ap,fmt);
for(p=fmt;*p;p++){
if(*p!='%'){
putchar(*p);
continue;
}
i=0;
localfmt[i++]='%';
while(*(p+1)&&!isalpha(*(p+1)))
localfmt[i++]=*++p;
localfmt[i++]=*(p+1);
localfmt[i]='\0';
switch(*++p){
case 'd':
case 'i':
ival=va_arg(ap,int);
printf(localfmt,ival);
break;
case 'x':
case 'X':
case 'u':
case 'o':
uval=va_arg(ap,unsigned);
printf(localfmt,uval);
case 'f':
dval=va_arg(ap,double);
printf(localfmt,dval);
break;
case 's':
sval=va_arg(ap,char*);
printf(localfmt,sval);
break;
default:
putchar(*p);
break;
}
}
va_end(ap);
}
int main(){
int a=3;
double d=8.7;
minprintf("%d %f\n",a,d);
}
#include <stdarg.h>
#include <ctype.h>
#define LOCALFMT 100
void minscanf(char *fmt,...){
va_list ap;
char *p,*sval;
char localfmt[LOCALFMT];
int c,i,*ival;
unsigned *uval;
double *dval;
va_start(ap,fmt);
for(p=fmt;*p;p++){
if(*p!='%'){
localfmt[i++]=*p;
continue;
}
i=0;
localfmt[i++]='%';
while(*(p+1)&&!isalpha(*(p+1)))
localfmt[i++]=*++p;
localfmt[i++]=*(p+1);
localfmt[i]='\0';
switch(*++p){
case 'd':
case 'i':
ival=va_arg(ap,int*);
scanf(localfmt,ival);
break;
case 'x':
case 'X':
case 'u':
case 'o':
uval=va_arg(ap,unsigned*);
scanf(localfmt,uval);
break;
case 'f':
dval=va_arg(ap,double*);
scanf(localfmt,dval);
break;
case 's':
sval=va_arg(ap,char*);
scanf(localfmt,sval);
break;
default:
scanf(localfmt);
break;
}
}
}
下面是标准库中对fgets和fputs函数的实现:
register int c;
register char *cs;
cs=s;
while(--n>0&&(c=getc(iop))!=EOF)
if((*cs++=c)=='\n')
break;
*cs='\0';
return (c==EOF&&cs==s)?NULL:s;
}
int fputs(char*s ,FILE*iop){
int c;
while(c=*s++)
putc(c,iop);
return ferror(ip)?EOF:0;
}
#include <stdlib.h>
#include <string.h>
#define MAXLINE 100
void filecomp(FILE*fp1,FILE*fp2){
char line1[MAXLINE],line2[MAXLINE];
char*lp1,*lp2;
do{
lp1=fgets(line1,MAXLINE,fp1);
lp2=fgets(line2,MAXLINE,fp2);
if(lp1==line1&&lp2==line2){
if(strcmp(line1,line2)!=0){
printf("first difference in line\n %s\n",line1);
lp1=lp2=NULL;
}
}
else if(lp1!=line1&&lp2==line2)
printf("end of first at line\n%s\n",line2);
else if(lp1==line1&&lp2!=line2)
printf("end of first at line\n%s\n",line1);
}
while(lp1==line1&&lp2==line2);
}
int main(int argc,char *argv[]){
FILE *fp1,*fp2;
if(argc!=3){
fprintf(stderr,"comp:need two file names\n");
exit(1);
}
else{
if((fp1=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"comp:can't open %s\n",*argv);
exit(1);
}
else if((fp2=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"comp:can't open %s\n",*argv);
exit(1);
}
else{
filecomp(fp1,fp2);
fclose(fp1);
fclose(fp2);
exit(0);
}
}
}
#include <string.h>
#include <stdlib.h>
#define MAXLINE 1000
void fpat(FILE *fp,char *fname,char *pattern,int except,int number);
int main(int argc,char*argv[]){
char pattern[MAXLINE];
int c,except=0,number=0;
FILE *fp;
while(--argc>0&&(*++argv)[0]=='-')
while(c=*++argv[0])
switch(c){
case 'x':
except=1;
break;
case 'n':
number=1;
break;
default:
printf("find:illegal option %c\n",c);
argc=0;
break;
}
if(argc>=1)
strcpy(pattern,*argv);
else{
printf("Usage:find [-x] [-n] pattern [file ..]\n");
exit(1);
}
if(argc==1)
fpat(stdin,"",pattern,except,number);
else
while(--argc>0)
if((fp=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"find: can't open %s\n",*argv);
exit(1);
}else{
fpat(fp,*argv,pattern,except,number);
fclose(fp);
}
return 0;
}
void fpat(FILE *fp,char *fname,char *pattern,int except,int number){
char line[MAXLINE];
long lineno=0;
while(fgets(line,MAXLINE,fp)!=NULL){
++lineno;
if((strstr(line,pattern)!=NULL)!=except){
if(*fname)
printf("%s - ",fname);
if(number)
printf("%ld: ",lineno);
printf("%s",line);
}
}
}
#include <stdlib.h>
#define MAXBOT 3
#define MAXHDR 5
#define MAXLINE 100
#define MAXPAGE 66
int heading(char *fname,int pageno){
int ln=3;
fprintf(stdout,"\n\n");
fprintf(stdout,"%s page %d\n",fname,pageno);
while(ln++<MAXHDR)
fprintf(stdout,"\n");
return ln;
}
void fileprint(FILE*fp,char *fname){
int lineno,pageno=1;
char line[MAXLINE];
lineno=heading(fname,pageno++);
while(fgets(line,MAXLINE,fp)!=NULL){
if(lineno==1){
fprintf(stdout,"\f");
lineno=heading(fname,pageno++);
}
fputs(line,stdout);
if(++lineno>MAXPAGE-MAXBOT)
lineno=1;
}
fprintf(stdout,"\f");
}
int main(int argc,char *argv[]){
FILE *fp;
if(argc==1)
fileprint(stdin," ");
else
while(--argc>0)
if((fp=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"print:can't open %s\n",*argv);
exit(1);
}
else{
fileprint(fp,*argv);
fclose(fp);
}
return 0;
}
随机数发生器,生成浮点数的方法
第8章 UNIX系统接口
利用低级的read和write函数来构造高级函数getchar,putchar等。
char c;
return (read(0,&c,1)==1)?(unsigned char)c:EOF;
}
int getchar__(void){
static char buf[BUFSIZ];
static char *bufp=buf;
static int n=0;
if(n==0){
n=read(0,buf,sizeof buf);
bufp=buf;
}
return (--n>0)?(unsigned char )*bufp++:EOF;
}
#define NULL 0
#define EOF (-1)
#define BUFSIZ 1024
#define OPEN_MAX 20
typedef struct _iobuf{
int cnt;
char *ptr;
char *base;
int flag;
int fd;
}FILE;
extern FILE _iob[OPEN_MAX];
#define stdin (&_iob[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
enum _flags{
_READ =01,
_WRITE =02,
_UNBUF=04,
_EOF =010,
_ERR=020
};
int _fillbuf(FILE*);
int _flushbuf(int ,FILE *);
#define feof(p) (((p)->flag&_EOF)!=0)
#define ferror(p) (((p)->flag&_ERR)!=0)
#define fileno(p) ((p)->fd)
#define getc(p) (--(p)->cnt>=0\
?(unsigned char)*(p)->ptr++:_fillbuf(p))
#define putc(x,p) (--(p)->cnt>=0\
?*(p)->ptar++=(x):_flushbuf((x),p))
#define getchar() getc(stdin)
#define putchar(x) putc(x,stdout)
#include <fcntl.h>
#define PERMS 0666
FILE *fopen(char *name,char *mode)
{
int fd;
FILE *fp;
if(*mode!='r'&&*mode!='w'&&*mode!='a')
return NULL;
for(fp=_iob;fp<_iob+OPEN_MAX;fp++)
if((fp->flag&(_READ|_WRITE))==0)
break;
if(fp>=_iob+OPEN_MAX)
return NULL;
if(*mode=='w')
fd=creat(name,PERMS);
else if(*mode=='a'){
if((fd=open(name,O_WRONLY,0))==-1)
fd=creat(name,PERMS);
lseek(fd,0L,2);
}
else
fd=open(name,O_RDONLY,0);
if(fd==-1)
return NULL;
fp->fd=fd;
fp->cnt=0;
fp->base=NULL;
fp->flag=(*mode=='r')?_READ:_WRITE;
return fp;
}
int _fillbuf(FILE*fp){
int bufsize;
if((fp->flag&(_READ|_EOF|_ERR))!=_READ)
return EOF;
bufsize=(fp->flag&_UNBUF)?1:BUFSIZ;
if(fp->base==NULL)
if((fp->base=(char*)malloc(bufsize))==NULL)
return EOF;
fp->ptr=fp->base;
fp->cnt=read(fp->fd,fp->ptr,bufsize);
if(--fp->cnt<0){
if(fp->cnt==-1)
fp->flag|=_EOF;
else
fp->flag|=_ERR;
fp->cnt=0;
return EOF;
}
return (unsigned char)*fp->ptr++;
}
FILE _iob[OPEN_MAX]={
{0,(char*)0,(char*)0,_READ,0 },
{0,(char*)0,(char*)0,_WRITE,1 },
{0,(char*)0,(char*)0,_WRITE|_UNBUF,2 },
};
int _flushbuf(int x,FILE*fp){
unsigned nc;
int bufsize;
if(fp<_iob||fp>=_iob+OPEN_MAX)
return EOF;
if((fp->flag&(_WRITE|_ERR))!=_WRITE)
return EOF;
bufsize=(fp->flag&_UNBUF)?1:BUFSIZ;
if(fp->base==NULL){
if((fp->base=(char*)malloc(bufsize))==NULL){
fp->flag|=_ERR;
return EOF;
}
}
else{
nc=fp->ptr-fp->base;
if(write(fp->fd,fp->base,nc)!=nc){
fp->flag|=_ERR;
return EOF;
}
}
fp->ptr=fp->base;
*fp->ptr++=(char)x;
fp->cnt=bufsize-1;
return x;
}
int fclose(FILE *fp){
int rc;
if((rc=fflush(fp))!=EOF){
free(fp->base);
fp->ptr=NULL;
fp->cnt=0;
fp->base=NULL;
fp->flag&=(_READ|_WRITE);
}
return rc;
}
int fflush(FILE*fp){
int rc=0;
if(fp<_iob||fp>=_iob+OPEN_MAX)
return EOF;
if(fp->flag&_WRITE)
rc=_flushbuf(0,fp);
fp->ptr=fp->base;
fp->cnt=(fp->flag&_UNBUF)?1:BUFSIZ;
return rc;
}
int fseek(FILE *fp,long offset,int origin){
unsigned nc;
long rc=0;
if(fp->flag&_READ){
if(origin==1)
offset-=fp->cnt;
rc=lseek(fp->fd,offset,origin);
fp->cnt=0;
}
else if(fp->flag&_WRITE){
if((nc=fp->ptr-fp->base)>0)
if(write(fp->fd,fp->base,nc)!=nc)
rc=-1;
if(rc!=-1)
rc=lseek(fp->fd,offset,origin);
}
return (rc==-1)?-1:0;
}
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
//#define NAME_MAX 14
//typedef struct{
// long ino;
// char name[NAME_MAX+1];
//}Dirent;
//typedef struct{
// int fd;
// Dirent d;
//}DIR;
//DIR *opendir(char *dirname);
//Dirent* readdir(DIR*dfd);
//void closedir(DIR* dfd);
//char *name;
//struct stat stbuf;
//int stat(char *,struct stat*);
//#define S_IFMT 0160000
//#define S_IFDIR 0040000
//#define S_IFCHR 0020000
//#define S_IFBLK 0060000
//#define S_IFREG 001000
#define MAX_PATH 1024
void dirwalk(char *dir,void(*fcn)(char*)){
char name[MAX_PATH];
struct dirent *dp;
DIR *dfd;
if((dfd=opendir(dir))==NULL){
fprintf(stderr,"dirwalk:can't open %s\n",dir);
return;
}
while((dp=readdir(dfd))!=NULL){
if(strcmp(dp->d_name,".")==0||
strcmp(dp->d_name,"..")==0)
continue;
if(strlen(dir)+strlen(dp->d_name)+2>sizeof(name))
fprintf(stderr,"dirwalk:name %s %s too long\n",
dir,dp->d_name);
else{
sprintf(name,"%s/%s",dir,dp->d_name);
fcn(name);
}
}
closedir(dfd);
}
void fsize(char *name){
struct stat stbuf;
if(stat(name,&stbuf)==-1){
fprintf(stderr,"fsize:can't access %s\n",name);
return ;
}
if((stbuf.st_mode&S_IFMT)==S_IFDIR)
dirwalk(name,fsize);
printf("%5u %6o %3u %8ld %s\n",stbuf.st_ino,
stbuf.st_mode,stbuf.st_nlink,stbuf.st_size,name);
}
int main(int argc,char **argv){
if(argc==1)
fsize(".");
else
while(--argc>0)
fsize(*++argv);
return 0;
}
union header{
struct {
union header *ptr;
unsigned size;
}S;
Align x;
};
typedef union header Header;
static Header base;
static Header *freep=NULL;
void *malloc(unsigned nbytes){
Header *p,*prevp;
Header *moreroce(unsigned);
unsigned nuints;
nuints=(nbytes+sizeof(Header)-1)/sizeof(header)+1;
if((prevp=freep)==NULL){
base.s.ptr=freeptr=prevptr=&base;
base.s.size=0;
}
for(p=prevp->s.ptr;;prevp=p,p=p->s.ptr){
if(p->s.size>=nuints){
if(p->s.size==nuints)
prevp->s.ptr=p->s.ptr;
else{
p->s.size-=nuints;
p+=p->s.size;
p->s.size=nuints;
}
freep=prevp;
return (void*)(p+1);
}
if(p==freep)
if((p=moreroce(nuints))==NULL)
return NULL;
}
}
#define NALLOC 1024
static Header *moreroce(unsigned nu){
char *cp,*sbrk(int);
Header *up;
if(nu<NALLOC)
nu=NALLOC;
cp=sbrk(nu*sizeof(Header));
if(cp==(char*)-1)
return NULL;
up=(Header*)cp;
up->s.size=nu;
free((void*)(up+1));
return freep;
}
void free(void*ap){
Header *bp,*p;
bp=(Header*)ap-1;
for(p=freep;!(bp>p&&bp<p->s.ptr);p=p->s.ptr)
if(p>=p->s.ptr&&(bp>p||bp<p->s.ptr))
break;
if(bp+bp->size==p->s.ptr){
bp->s.size+=p->s.ptr->s.size;
bp->s.ptr=p->s.ptr->s.ptr;
}
else
bp->s.ptr=p->s.ptr;
if(p+p->size==bp){
p->s.size+=bp->s.size;
p->s.ptr=bp->s.ptr;
}
else
p->s.ptr=bp;
freep=p;
}
void *calloc(unsigned n,unsigned size){
unsigned i,nb;
char *p,*q;
nb=n*size;
if((p=q=malloc(nb))!=NULL)
for(i=0;i<nb;i++)
*p++=0;
return q;
}