• Blocks combine multiple statements into a single unit.
• Can be used when a single statement is expected.
• Creates a local scope (variables declared inside are local tothe block).
• Blocks can be nested.
{
int x=0;
{
int y =0; /∗both x and y visible∗/
}
/∗only x visible∗/
}
关于Blocks,这个总结很精辟,通过blocks的嵌套scope,生成一棵scope树,这样有些函数式程序的味道。
• goto allows you to jump unconditionally to arbitrary part ofyour code (within the same function).
• the location is identified using a label.
• a label is a named location in the code. It has the same formas a variable followed by a ’:’
start :
{
if ( cond )
goto outside ;
/ ∗ some code ∗ /
goto start;
}
outside:
/ ∗ outside block ∗ /
goto可谓大名鼎鼎,虽然人们在程序设计中使用较少。goto在C中是很自然的一个命令,因为它可以方便地与汇编中的跳转对应,之所以臭名卓著,主要是因为人们的滥用以及相应产生的复杂性。
进行跳转在程序中是很必要的,但随意的无规则跳转会使程序的复杂性成倍增加,因此需要限制goto的使用。Return,break和continue其实也是跳转语句,但它们是受限制的跳转语句,跳转范围不大且有简单而明确的规则,相当于弱化了的goto。
goto在C中最常用的功能是跳出多层循环嵌套,但目前C中循环嵌套的层次并不多,而且完全可以由return实现。但goto仍可以方便地应用到错误和异常处理中,因为出现了错误和异常时,程序的执行流程往往发生较大改变,并且经常会结束某一段程序的执行。这时使用goto,副作用不会很明显而且可以实现正常执行代码和异常处理代码的分离。
Standard input and output
int putchar(int )
• putchar(c) puts the character c onthe standard output.
• it returns the character printedor EOF on error.
int getchar()
• returns the next character fromstandard input.
• it returns EOF on error.
虽然名字为putchar,但参数却是个数字,这说明putchar是很底层的函数,难道其实现涉及到视频的驱动?也有可能是为了方便,因为C中int和char基本是可以互换的,我想前者的可能性大些。
Since we will be reading and writing strings, here is a briefdigression
• strings are represented as an array of characters
• C does not restrict the length of the string. The end of thestring is specified using 0.
For instance, "hello" is represented using the array{’h’,’e’,’l’,’l’,’\0’}.
Declaration examples:
• char str []="hello"; /∗compiler takes care ofsize∗/
• char str[10]="hello"; /∗make sure the array islarge enough∗/
• char str []={ ’h’,’e’,’l’,’l’,0};
Note: use \" if you want the string to contain "
最常用String声明的就是charstr[] = "hello";这种方式最简单,并且程序员不必这个字符去数并冒着数错的风险来分配内存(想想都觉得boring),但存在的问题是这种声明方式隐藏了\0,C中的字符串结束符。C中的字符串表示很简单,使用一个以\0结尾的字符数组即可。
So far, we have read from the standard input and written to thestandard output. C allows us to read data from text/binary filesusing fopen().
FILE∗ fopen(char name[],char mode[])
• mode can be "r" (readonly),"w" (write only),"a" (append) among otheroptions. "b" can be appended for binary files.
• fopen returns a pointer to the filestream if it exists or NULL otherwise.
• We don’t need to know thedetails of the FILE data type.
• Important: The standard input andoutput are also FILE* datatypes (stdin,stdout).
• Important: stderr corresponds tostandard error output(different from stdout).
int fclose(FILE∗ fp)
• closes the stream (releases OSresources).
• fclose() is automatically calledon all open files when program terminate
C中的File是个很有意思的数据结构,刚开始接触时觉得它很可怕,里面肯定有很多复杂的细节,这当然是对的,但神奇的是我们并不需要关心FILE里面的东西,这体现了封装的强大,并揭示了C为什么能完成操作系统等大型软件的奥秘。
C中的很多设备都被看作文件来处理,相信stdin,stdout和stderr也会作为文件来处理。
File input
int getc(FILE∗ fp)
• reads a single character from thestream.
• returns the character read or EOFon error/end of file.
Note: getchar simply uses the standard input to read a character.We can implement it as follows:
#define getchar() getc(stdin )
char[] fgets(char line [], int maxlen, FILE∗ fp)
• reads a single line (upto maxlencharacters) from the input stream (including linebreak).
• returns a pointer to the characterarray that stores the line(read-only)
• return NULL if end of stream.
int putc(int c,FILE∗ fp)
• writes a single character c to theoutput stream.
• returns the character written orEOF on error.
Note: putchar simply uses the standard output to write acharacter. We can implement it as follows:
#define putchar(c) putc(c,stdout)
int fputs(char line [], FILE∗ fp)
• writes a single line to the outputstream.
• returns zero on success, EOFotherwise.
int fscanf(FILE∗ fp,char format[], arg1,arg2)
• similar to scanf,sscanf
• reads items from input stream fp.
stdin等是FILE*,我以前认为是FILE。当时想的不够深入,的确,FILE没什么用,涉及到FILE的操作基本上都是用FILE*的。
另外,我觉得putc和getc这两个函数名起的不好,改为fputc和fgetc就会好很多,这样putc和putchar就不会容易混淆而且putc函数也就更容易理解和记忆了。
int main(int argc,char∗ argv[])
• argc: count of arguments.
• argv[]: an array of pointers toeach of the arguments
• note: the arguments include thename of the program as well.
Examples:
• ./cat a.txt b.txt
(argc=3,argv[0]="cat"argv[1]="a.txt" argv[2]="b.txt")
• ./cat
(argc=1,argv[0]="cat")
函数名自身也算在参数中,不明白这是为什么,也许是为了方便吧,反正加进去也没什么坏处。