hello world!
分类: C/C++
2011-07-18 07:50:29
7.1 Standard Input and output:
The library implements a simple model of text input and output. A text stream consists of a sequence of lines; each line ends with a newline character. If the system doesn't operate that way, the library does whatever necessary to make it appear as if does.
Exercise 7-1: Write a program that converts upper case to lower or lower case to upper, depending on the name it is invoked with, as found in argv[0].
#include
#include
#include
int main(int argc, char *argv[])
{
int c ;
if(strcmp(argv[0],"lower")==0)
while((c=getchar())!=EOF)
putchar(tolower(c));
else
while((c=getchar())!=EOF)
putchar(toupper(c));
return 0;
}
7.2 Standard Input and output:
int printf(char *format, arg1, arg2, ...);
printf converts, formats, and prints its arguments on the standard output under control of the format. It returns the number of characters printed.
The function sprintf does the same conversions as printf does, but stores the output in a string:
int sprintf(char *string, char *format, arg1, arg2, ...);
sprintf formats the arguments in arg1, arg2, etc., according to format as before, but places the result in string instead of the standard output; string must be big enough to receive the result.
Exercise 7-2. Write a program that will print arbitrary input in a sensible way. As a minimum, it should print non-graphic characters in octal or hexadecimal according to local custom, and break long text lines.
#include
#include
#define MAXLINE 100 /* max number of chars in ine line */
#define DCTLEN 6 /* length of an octal value */
int inc(int pos,int n);
/***
main: print arbitrary input in a sensible way
***/
int main(int argc, char *argv[])
{
int c,pos;
pos=0;
while((c=getchar())!=EOF){
if(iscntrl(c) || c==' '){ /* non-graphic or blank */
pos=inc(pos,DCTLEN);
printf("\\%03o",c); /* unsigned octal hex */
if(c=='\n'){ /* newline character */
pos=0;
putchar('\n');
}
}else {
pos=inc(pos,1);
putchar(c);
}
}
return 0;
}
/***
inc: increment position counter for output
***/
int inc(int pos,int n)
{
if(pos+n
return pos+n;
else {
putchar('\n');
return n;
}
}
7.3 Variable-length Argument Lists:
The proper declaration for printf is
int printf(char *fmt, ...)
where the declaration ... means that the number and types of these arguments may vary. The declaration ... can only appear at the end of an argument list. Our minprintf is declared as
void minprintf(char *fmt, ...)
since we will not return the character count that printf does. The tricky bit is how minprintf walks along the argument list when the list doesn't even have a name. The standard header
The type va_list is used to declare a variable that will refer to each argument in turn; in minprintf, this variable is called ap, for ``argument pointer.'' The macro va_start initializes ap to point to the first unnamed argument. It must be called once before ap is used. There must be at least one named argument; the final named argument is used by va_start to get started.
Each call of va_arg returns one argument and steps ap to the next; va_arg uses a type name to determine what type to return and how big a step to take. Finally, va_end does whatever cleanup is necessary. It must be called before the program returns.
Exercise 7-3. Revise minprintf to handle more of the other facilities of printf.
#include
#include
#include
#define LOCALFMT 100
void minprintf(char *fmt,...);
int main(int argc, char *argv[])
{
int good=888;
double f=1000.888;
minprintf("dream! %d\n",good);
minprintf("%f\n",f);
return 0;
}
/***
minprintf: a simple printf with variable argument list.
***/
void minprintf(char *fmt,...)
{
va_list ap; /* points to each unnamed arg in turn */
char *p,*sval; /* typedef char * va_list */
int i,ival;
double dval;
unsigned uval;
char localfmt[LOCALFMT];
va_start(ap,fmt); /* make ap point to 1st unnamed arg */
for(p=fmt;*p;p++){
if(*p!='%'){
putchar(*p);
continue;
}
i=0;
localfmt[i++]='%'; /* start local fmt */
while(*(p+1)&&!isalpha(*(p+1))) /* until encounter char */
localfmt[i++]=*++p; /* collect chars */
localfmt[i++]=*(p+1); /* format letter */
localfmt[i]='\0';
switch(*++p){ /* format letter */
case 'd':
case 'i':
ival=va_arg(ap,int); /* point to next arg and offset int*/
printf("%d",ival);
break;
case 'x':
case 'X':
case 'u':
case 'o':
uval=va_arg(ap,unsigned);
printf(localfmt,uval);
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(localfmt);
break;
}
}
va_end(ap); /* clean up */
}
7.4 Formatted Input-Scanf:
The function scanf is the input analog of printf, providing many of the same conversion facilities in the opposite direction.
int scanf(char *format, ...)
The format argument is described below; the other arguments, each of which must be a pointer, indicate where the corresponding converted input should be stored.
There is also a function sscanf that reads from a string instead of the standard input:
int sscanf(char *string, char *format, arg1, arg2, ...)
It scans the string according to the format in format and stores the resulting values through arg1, arg2, etc. These arguments must be pointers.
Literal characters can appear in the scanf format string; they must match the same characters in the input.
Exercise 7-4. Write a private version of scanf analogous to minprintf from the previous section.
#include
#include
#include
#define LOCALFMT 100
void minscanf(char *fmt,...)
{
va_list ap;
char *p,*sval;
char localfmt[LOCALFMT];
float *dval;
int c,i,*ival;
unsigned *uval;
i=0;
va_start(ap,fmt); /* make ap point to 1st unnamed arg*/
for(p=fmt;*p;p++){
if(*p!='%'){
localfmt[i++]=*p;
continue;
}
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, float *);
scanf(localfmt,dval);
break;
case 's':
sval=va_arg(ap,char *);
scanf(localfmt,sval);
break;
default:
scanf(localfmt);
break;
}
i=0;
}
va_end(ap);
}
int main(int argc, char *argv[])
{
float v=0;
minscanf("%f\n",&v);
printf("%.2f\n",v);
return 0;
}
7.5 File Access:
This pointer, called the file pointer, points to a structure that contains information about the file, such as the location of a buffer, the current character position in the buffer, whether the file is being read or written, and whether errors or end of file have occurred. Users don't need to know the details, because the definitions obtained from
FILE *fp;
FILE *fopen(char *name, char *mode);
This says that fp is a pointer to a FILE, and fopen returns a pointer to a FILE. Notice that FILE is a type name, like int, not a structure tag; it is defined with a typedef.
The call to fopen in a program is
fp = fopen(name, mode);
The first argument of fopen is a character string containing the name of the file. The second argument is the mode, also a character string, which indicates how one intends to use the file allowable modes include read ("r"), write ("w"), and append ("a"). Some systems distinguish between text and binary files; for the latter, a "b" must be appended to the mode string.
int getchar() = getc(stdin)
int putchar(c) = putc((c),stdput)
int getc(FILE *fp) //从文件中返回fp指向的输入流中的下一个字符
int ungetc(int c,FILE *fp) //将字符C写回到文件fp中
int putc(int c,FILE *fp) //将字符c写入到fp指向的文件中:都是宏实现
7.6 Error Handling-Stderr and Exit:
The treatment of errors in cat is not ideal. The trouble is that if one of the files can't be accessed for some reason, the diagnostic is printed at the end of the concatenated output. That might be acceptable if the output is going to a screen, but not if it's going into a file or into another program via a pipeline.
To handle this situation better, a second output stream, called stderr, is assigned to a program in the same way that stdin and stdout are. Output written on stderr normally appears on the screen even if the standard output is redirected.
Let us revise cat to write its error messages on the standard error.
#include
void fileCopy(FILE *, FILE *);
/***
cat: concatenate files, version 1
***/
int main(int argc, char *argv[])
{
FILE *fp;
char *prog=argv[0];
if(argc==1) /* no args; copy standard input */
fileCopy(stdin,stdout);
else
while(--argc>0)
if((fp=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"%s: can't open %s \n",prog,*argv);
exit(1);
} else{
fileCopy(fp,stdout);
fclose(fp);
}
if(ferror(stdout)){
fprintf(stderr,"%s: error writing stdout\n",prog);
exit (2);
}
exit (0);
}
/***
fileCopy: copy file ifp to file ofp
***/
void fileCopy(FILE *ifp, FILE *ofp)
{
int c;
while((c=getc(ifp))!=EOF)
putc(c,ofp);
}
7.7 Line input and output:
Exercise 7-6. Write a program to compare two files, printing the first line where they differ.
#include
#include
#include
#define MAXLINE 100
void filecomp(FILE *fp1,FILE *fp2);
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,"com:can't open %s\n",*argv);
exit (1);
}else if((fp2=fopen(*++argv,"r"))==NULL){
fprintf(stderr,"com:can't open %s\n",*argv);
exit (1);
}else{
filecomp(fp1,fp2);
fclose(fp1);
fclose(fp2);
exit (0);
}
}
}
/***
filecomp: file compare
***/
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",line1);
lp1=lp2=NULL;
}
}else if(lp1!=line1 && lp2==line2)
printf("end of first file at line \n%s",line1);
else if(lp1==line1&&lp2!=line2)
printf("end of first file at line \n%s",line1);
}while(lp1==line1 && lp2==line2);
}
Exercise 7-7. Modify the pattern finding program of Chapter 5 to take its input from a set of named files or, if no files are named as arguments, from the standard input. Should the file name be printed when a matching line is found?
#include
#include
#include
#define MAXLINE 1000
void fpat(FILE *fp,char *fname,char *pattern,int except,int number);
/***
find: print lines that match pattern from 1st argument
***/
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) /* read standard input */
fpat(stdin,"",pattern,except,number);
else
while(--argc>0) /* get a named file*/
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;
}
/***
fpat: find pattern
***/
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);
}
}
}
Exercise 7-8. Write a program to print a set of files, starting each new one on a new page, with a title and a running page count for each file.
#include
#include
#include
#define MAXBOT 3
#define MAXHDR 5
#define MAXLINE 100
#define MAXPAGE 66
/***
heading: put heading and enough blank lines
***/
int heading(char *fname, int pageno)
{
int ln=4;
fprintf(stdout,"\n\n");
fprintf(stdout,"%s page %d\n",fname,pageno);
while(ln++<=MAXHDR)
fprintf(stdout,"\n");
return ln;
}
/***
fileprint: print file fname
***/
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,"page \f end"); /* page eject after the file */
}
/***
printf: print files - each new one on a new page
***/
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;
}