-
关系运算符的优先级比算术运算符(包括+和-)低,比赋值运算符高。
这意味着x > y + 2和x > (y+ 2)相同,x = y > 2和x = (y > 2)相同。换言之,如果y大于2,则给x赋值1,否则赋值0。y的值不会赋给x。 -
求绝对值函数 abs fabs ,需要包含头文件 math.c
-
关于睡眠函数和随机数函数
睡眠函数 sleep,需要包含头文件 #include <unistd.h>
随机数函数rand(),需要包含头文件 #include <stdlib.h>, 还需要播种子,具体实现如下
1)
unsigned int seed;
srand(seed); // 随机数种子
printf("%d\n", rand()%10+1); // 1-10的随机数
2)需要多增加一个 <time.h> 的头文件
srand((unsigned)time(NULL));
printf("%d\n", rand()%3+1); // 1-3的随机数 -
逗号运算符的一些性质
逗号运算符有两个其他性质。首先,它保证了被它分隔的表达式从左往右求值(换言之,逗号是一个序列点,所以逗号左侧项的所有副作用都在程序执行逗号右侧项之前发生)。因此,ounces在cost之前被初始化。在该例中,顺序并不重要,但是如果cost的表达式中包含了ounces时,顺序就很重要。
例如,假设有下面的表达式:
ounces++, cost = ounces * FIRST_OZ
在该表达式中,先自增ounces,然后在第二个子表达式中使用onuces新值。作为序列点的逗号保证了左侧子表达式的副作用在对右侧子表达式求值之前发生。
其次 整个逗号表达的值是右侧的值,就好像 a = (i++,i++),肯定是先把i自增一次,再把i自增一次,最后把自增两次的结果赋给 a
逗号运算符赋值:
i = 299,500;
printf("%d\n", i); // i的值是299
先运算逗号左侧表达式,等逗号左侧表达式的副作用运算完,再运算右侧表达式,所以 i = 299
i = (299,500);
printf("%d\n", i); // i的值是500
整个逗号表达的值是右侧的值。()的优先级高于 , 因此先将括号内运算完,再赋值,就好像 a = (i++,i++),先运算括号中i++,先把i自增一次,再把i自增一次,等括号运算完后,再把自增两次的结果赋给 a
5. 关于scanf函数的返回值
scanf函数的返回值,是根据一次成功的数据来决定的,如果一次读取两个数据则返回2
printf("%d\n",scanf("%d%d%d",&i, &j, &k))
输入 1 2 3 则scanf的返回值是 3
输入1 2 q 则scanf的返回值是 2
输入 1 q 2则返回值是1,在读取到第二个是q的是时候,不符合%d,scanf函数就已经结束,不会再去判断后面一个数输入的正确性(如果是换行输入观察就比较明显了,在输入第二个q字符的时候,直接返回)
因此在scanf函数当做while的循环条件时,尽量写成 while(scanf("%d%d%d",&i, &j, &k) == 3) 这种形式
- 特殊字符处理函数,包含头文件:#include <ctype.h>
字符测试函数 如果是以下条件为真,否则为假
isalpha(ch) 字母
isalnum(ch) 字母或数字
isspace(ch) 指代所有的空白符,(包括空格’ ‘、水平制表符’\t’、换行符’\n’、垂直制表符’\v’、换页’\f’以及回车’\r’)
isblank(ch) 标准空白符(这样的空白符只有空格 ’ '和水平制表符 ‘\t’)不能换行换页,或者有其它特殊效果
iscntrl(ch) 控制字符(ctrl+B等)
isdigit(ch) 数字
isgraph(ch) 除空格之外任意可打印字符
islower(ch) 小写字母
isupper(ch) 大写字母
isprint(ch) 可打印字符
ispunct(ch) 标点符号(除空格、字母、数字以外的任意可打印字符)
字符映射函数 行为
tolower(ch) 如果是大写字母则转化为小写字母,否则返回原始参数 putchar(tolower(ch));
toupper(ch) 如果是小写字母则转化为大写字母,否则返回原始参数 putchar(toupper(ch));
7. C99新标准中,可以用 and 代替 && or 代替 || not 代替 !,需要包含头文件:#include <iso646.h>
8. 关于标志位
记录一句话中的单词数目
在读取到不是空白符号的时候记录status的值的true,再次读到空格或者标点符号的时候计数+1,同时将status的值置false,关于true,false需要包含头文件 #include <stdbool.h> (为bool、true、false提供定义)
char ch;
_Bool status = false;
while(’|’ != (ch = getchar()))
{
if(isalpha(ch) && !status) //在读到是 字母 且 status的值为false时候 置status为true
status = true;
if(status && isspace(ch) || ispunct(ch)) // 当status为真 并且 是空白字符或者读到标点符号,则表示读完一个单词,此时计数+1,并将status值false
{
j++;
status = false;
}
}
9. 文件读取结束标志:EOF
这里关键要理解EOF是一个值,标志着检测到文件结尾,并不是在文件中找得到的符号,EOF的实际值是-1
int main()
{
int ch; //这里用int定义char,不影响最后的打印结果,最后打印使用的是putchar,会将对应的int值转化为字符
while(EOF != (ch = getchar()))
putchar(ch);
return 0;
}
注意:
10. 不用定义EOF,因为stdio.h中已经定义过了;
11. 不用担心EOF的实际值,因为EOF在stdio.h中用#define预处理指令定义,可直接使用,不必再编写代码假定EOF为某值;
12. 变量ch的类型从char变为int,因为char类型的变量只能表示0~255的无符号整数,但是EOF的值是-1。还好,getchar()函数实际返回值的类型是int,所以它可以读取EOF字符。如果实现使用有符号的char类型,也可以把ch声明为char类型,但最好还是用更通用的形式;
13. 由于getchar()函数的返回类型是int,如果把getchar()的返回值赋给char类型的变量,一些编译器会警告可能丢失数据;
14. ch是整数不会影响putchar(),该函数仍然会打印等价的字符;
15. 使用该程序进行键盘输入,要设法输入EOF字符。不能只输入字符EOF,也不能只输入-1(输入-1会传送两个字符:一个连字符和一个数字1)。正确的方法是,必须找出当前系统的要求。例如,在大多数UNIX和Linux系统中,在一行开始处按下Ctrl+D会传输文件结尾信号。许多微型计算机系统都把一行开始处的Ctrl+Z识别为文件结尾信号,一些系统把任意位置的Ctrl+Z解释成文件结尾信号。
16. 初始化有数组名的数组可以省略大小,同样初始化复合字面量也可以省略大小
int a[2] = {1, 2} <==> int a[] = {1, 2}
(int [2]){1, 2} <==> (int []){1, 2}