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;
}