13.字符串
自己设计的字符串输入函数需要考虑的问题:
1.在存储函数之前应该跳过那些空白嘛。
2.什么字符会导致结束,空白字符,换行符还是某个字符,这些要存储起来嘛。
3.输入太多了怎么办,是截取还是留给下次读入。
//string.h中包含了很多的字符串操作:复制,比较,选择子串,合并等。
//strncpy会安全些,都是返回的目标指针
char* strcpy(char* dest, const char* src);
//得足够大的
char* strcat();
//比较情况,完全一致比长短,否则按ASCII码大小,'\0'与0一致
int strcmp(const char* s1, const char* s2);
//字符串长度
size_t strlen(const char* s1);
//输出到字符串
int sprintf(day_str, "%2d", str);
/* 一些字符串操作的惯用法 */
//字符串末尾定位
while(*s++)
;
//复制字符串
//这个赋值运算符,整体为赋值的值,和这个逗号表达式类似
while(*s++ = *p++)
;
/*字符串数组的一种不浪费空间的方法 */
char* p[] = {"23123", "asdasd", "asd6767"};
p[i][j] = 'M'//来寻搜索元素
/* 命令行参数 */
//argc代表命令行参数的个数,0默认为程序名
main(int argc, char* argv[])
C中的字符串字面量不是常量,它的每个字符元素也不是常量,所以字符元素的不可变性仅仅表现在语义层面,但在语法和约束条件上没有要求。而C++中的字符串字面量是常量,每个字符元素也是常量,因此在语义和约束条件两方面都要求不能改变其中的每个字符元素;另外,处于兼容性考虑C++还存在着特殊情况下的向非const指针的转换。
我们针对字符串使用时当然要有空字符结尾,然而有些其他用途包括字符翻译表就不需要用这个操作。
prinf(某字符串时),其实这很危险,如果该字符包含%,输出结果将非常危险
//文件尾或错误
(ch = getchar()) != '\n' && (ch != EOF)
14.预处理器
预处理是一个小软件,他可以在编译前编辑C语言程序,适度使用。
三种类型:宏定义,文件包含,条件编译。
宏定义太长可以用\来表示,还有下一行。
宏会更通用,不像函数参数一样有类型。
/* 介绍#和##这两个骚操作 */
//#可以为宏定义时显示标签,将x转为字符串字面型
#define PRINT_INT(x) printf(#x " =%d", x)
PRINT_INT(i/j);
//##作为粘合剂,即标识之间粘合起来
//GENERIC_MAX(float),有点函数模板的味道了
#define GENERIC_MAX(type) \
type type##_max(type x, type y)\
{ \
return x > y ? x : y; \
}
一个宏的作用范围为出现到文件结尾,当然我们可以#undef。
//创建一些很长的宏
#define ECHO(s) (gets(s), puts(s))
//或者是语句,利用do while必须加分号的骚操作
#define ECHO(str) \
do{ \
gets(s); \
puts(s); \
}while(0) \
还有assert可以帮我们定位错误的信息,比如文件名字及行数。
//一些很有意思的预定义宏
printf("%s--%s",__TIME__,__DATE__);
//条件编译
#define DEBUG 1
#if DEBUG
#endif
//宏测试
#ifdef DEBUF
#endif
//下面介绍条件编译几个应用
1.多种操作系统之间互相移植
#if defined(WINDOWS)
#elif defined(DOS)
#endif
2.C语言编译器
#if defined(__STDC__)
#else
endif
3.为宏提供默认定义
#ifndef BUFFSIZE
#define BUFFSIZE 256
#endif
4.嵌套注释
一些不常用的宏指令:
1.#pragma
编译器包含需要执行的指令
2.#error
输出某些错误信息
#if INT_MAX < 100000000
#error int type is too small
#endif
如果遇到宏名之前出现过,是不会宏展开的,否则会无限循环。
对于##和#的嵌套使用,大家也要多加注意,一般的技巧是定义新的宏。
这个if define非常灵活,可以测试多个宏了。