C语言学习笔记(二):define和typedef以及printf和scanf族函数
define 和 typedef
预处理指令执行的仅仅是低级的记号替换,某些时候就会暴露出问题:
#define char* String;
String inputFileName;
预处理程序把“#define”指令后面的文本中所以的记号“String”替换成“char*”,所以上面的代码可以工作。但如果写成:
#define char* String;
String intputFileName,OutputFileName;
经过替换,上面的语句变成:
char * inputFileName,OutputFileName;
这就是#define的局限!
typedef就没这个问题,因为typedef是由编译器进行语法分析的,用它定义的类型对声明(或定义)语句中的每一个变量都起作用。
不过,typedef也有一些”局限“,用它定义的类型不能“组合使用”,例如:
typedef int INT32;
unsigned INT32 a;
别以为上面的声明会被编译器看做是:
unsigned int a;
不是的,编译器会拒绝这样的组合。
相反,使用#define却没有这样的问题。
在某些时候,使用typedef一定要小心,例如:
typedef char * String;
const String s;
上面的定义s究竟是:
const char * s;//s是一个指向const char的指针
还是:
char * const s;//s是一个指向char的const指针
答案往往会让粗心的人吓一跳,正确的解释是后者。因为当用typedef定义了一个新的类型String之后,const修饰的对象就是String,而String本身是指针,于是const String的意思就是String(某种指针)的值是常量,所以最后s就被理解为指向char的const指针。
printf(),sprintf(),fprintf() {第一个参数是目的参数}
int sprintf(char *string, char *farmat [,argument,...]); //格式化输出到字符串(string)中,返回值:字符串长度(strlen)
int fprintf(FILE *stream, const char *format, ... ); //传送格式化输出到一个文件(stream)中,返回值是输出的字符数,发生错误时返回一个负值
scanf(),sscanf(),fscanf() {第一个参数是起始参数}
int sscanf(const char *buffer,const char *format,[argument ]...); //从一个字符串(buffer)中读出指定格式相符的数据.成功则返回参数数目,失败则返回0,错误原因存于errno中
例:char buf[512] ;
sscanf("123456 ", "%s", buf);//此处buf是数组名,它的意思是将123456以%s的形式存入buf中!
fscanf(FILE *stream, char *format,[argument...]); //从一个流中执行格式化输入,返回值:读入数据的个数
例:同sscanf()
sprintf与sscanf,fprintf与fscanf的区别
sprintf第一个参数为char*型,存储的为字符串。sscanf的第一个参数为char*型,但此参数是起始参数,可以实现类型的转换,接收的为最后一个参数。而sprintf的第一个参数是目的参数,所以只能存储char*型的数据。