字符串+转义字符+注释
字符串
"hello,giturtle!"
这种由双引号(Double Quote)引起来的一串字符成为字符串字面值,简称为字符串.
C String(C风格)字符串指的是以’\0’结尾的字符数组,在计算字符串长度的时候’\0’是作为结束标志,并不算做字符串内容,但在计算字符串占存中算作.
转义字符
假如我们要打印一个目录: [c:\code\test.c]
代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("c:\code\test.c");
system("pause");
return 0;
}
结果如下:
c:code est.c
???
为什么结果和自己所想象的大相径庭?
这里就要引入转义字符的概念了.
很显然,编译器在处理这段代码时,对其中的内容进行了转义操作,所以它最后的运行结果不是我们所希望的那样了.
那么如何才能得到我们希望的格式输出呢?很简单,对转义字符进行转义操作就会使它的效果消除,具体如下:
printf("c:\\code\\test.c");
[牛刀小试]:
//输出结果是什么?
printf("%d\n",strlen("c:\test\3\test.c"));
解:从字符串起点c向后推演,到达\t时水平制表,为一个字符.\3表示在ASCII码表上第3号的字符,总计13个.
注: \ +数字表示在ASCII码表上第几号字符,这就将C语言字符串与ASCII码表联系起来了.
注释
-
注释的作用就是方便代码的可读性和直观性,如若适当添加注释,读者或者一年后的自己拿到这段代码时,就会更加便于理解代码,提升幸福感.
-
代码中有不需要的代码可以直接删除,也可以注释起来,要是之后又需要用到这段代码呢,取消注释就可以了,不用去再敲,比较方便.
这里介绍几种不同风格的注释:
- [C语言风格]
(缺点:不能嵌套注释)
/*xxxxxxx*/
- [C++风格]
(可以一行也可以注释多行,常用)
//xxxxxxx
- [Python风格]
(和C++风格类似,不过不可在C/C++中使用)
#xxxxxxx
选择语句
if选择语句使用的场景非常广泛.
例如:到了大学第四学期,要是选择考研,努力就会考上自己心仪的院校.要是选择玩游戏,就会回家卖红薯.以下用选择语句实现:
#include <stdio.h>
#include <stdlib.h>
int main(){
int choice = 0;
printf("第四学期了,你的选择是:1.考研 2.玩游戏");
scanf("%d",&choice);
if(choice == 1){
printf("努力,你会考上好院校!\n");
}
else{
printf("你还是回家种红薯吧!\n");
}
system("pause");
return 0;
}
这段代码需要注意的细节是:
-
在将用户输入选择后的比较,如果choice == 1这一语句写为 = ,意义就会改变而不是判断输入是否为1了,代码在运行过程中会始终执行这一语句没有终止,造成死循环.
-
在if选择语句输入完,之后跟着的是{ },很多同学会直接下意识的在语句之后加上一个分号作为结尾;这样里面的printf语句就永远执行不到了,一定要注意.
-
if…else…语句搭配,如若每个选择节点里面都有不止一条的语句,一定要用大括号框选上,否则从第二句开始的所有语句都会算作必经流程.为了避免这一点,建议在选择语句中把大括号作为习惯,这样一个细节就会规避以后很多的小麻烦.
循环语句
循环语句一般与选择语句搭配使用.循环语句常见的分为三种:
- while语句
- for语句
- do…while语句
例:到了大四,我要不断努力背单词考研!
这里以while举例进行实例抽象实现:
#include <stdio.h>
#include <stdlib.h>
int main(){
printf("到大四了\n");
int word = 0;
while(word <= 20000){
word++;
printf("我要努力背单词!\n");
}
if(word > 20000){
printf("我考研英语会得高分!");
}
system("pause");
return 0;
}
通过分析代码可以知道:
我的单词量达到了20000,去考研英语会得到高分.这里与要注意while循环一定要有结束的条件,例如这里的超过20000,否则也会形成死循环.
函数
这里的函数与数学领域的函数有异曲同工之妙,同样都是为了解决问题而构建的方法.
int Add(int x,int y){
int z = x + y;
return z;
}
注:函数要位于main()函数之外.
为什么main()函数中可以实现解决还要单独拉出来构建成一个函数呢?岂不是多此一举?
因为函数的特点有以下几点:
- 简化代码,可以使函数体更加简洁
- 代码复用,这也是单独构建函数的重点,一个代码可能会用很多次这样的方法,每次都去敲重复的代码简直太复杂了.那么构建好后每次需要使用就调用构建好的函数岂不是非常简单?
- 因为函数是单独拎出来构建的,所以代码维护/修改就很容易,可以快速定位缺陷所在.
数组
数组是一组相同元素的集合,在内存中表示为一段连续的存储空间.
- 数组的定义
int arr[6] = { 1, 2, 3, 4, 5, 6};
//arr[ ]中的数字为元素个数/数组下标
//定义一个整形数组,最多存放6个元素
- 数组的使用
#include <stdio.h>
int main(){
int i = 0;
int arr[7] = {1,2,3,4,5,6,7};
//数组的遍历:
for(i = 0;i < 10;i++){
printf("%d ",arr[i]);
}
printf("\n");
return 0;
}
注意:
- 数组下标是从0开始计数的,表示的数组中对应值即为arr[0],所以最多可以访问到arr[i-1]的数字.(例如arr[6]数组最后一个元素为arr[5])
- 如果超过了第i-1而表达为arr[i]如果超过了第i-1而表达为arr[i]甚至更大arr[i+1]就会造成数组下标越界,这是一个未定义行为,最后返回的值很有可能是一个随机值.
操作符
以下简单分类罗列一下常见的几类操作符:
- 算术操作符
+ - * / %
//加 减 乘 除 求余(取模)
- 5/2 = 2;
C语言中除操作为地板除,只保留和数据类型有关的有效位数. - 5%2 = 1;和除操作有种相得益彰的感觉,他是取出其除之后的余数的操作.
- 位操作符
& | ~ ^
//按位与 按位或 按位取反 按位异或
- 这里的位操作符都是按二进制位操作,同时按位与&在C语言中还有另外一个含义:取地址.
- 另外,这里的位操作符都是不支持短路求值的,相关内容后面会涉及到.
- 移位操作符
>> <<
//右移 左移
- 移位操作符按二进制位进行移动的操作,左移一位 i << 1,就是将i的二进制位每一位都向左移动一位,也就等效于 * 2 操作,同样 i >> 1,也就等效于 / 2操作.
- 在C语言中,既然移位操作符与乘除2等效,那么二者谁更优先考虑呢?
答案是 /2 .虽然移位操作符比乘除2更加快速,但是这点时间的差别是微乎其微的,几乎可以忽略不计.程序员在代码中写上i / 2这个语句远比写上i >> 1直观,为了代码的可读性还是建议优先使用乘除操作. - 其实在编译阶段,编译器会自动把 /2转换为>>1操作,所以我们不必纠结与二者何者更优,其实本质上是相通的.
- 赋值操作符
= += -= *= /= &= ^= |= >>= <<=
利用 -= +=这类操作符可以一定程度上提升代码简洁度,例如 a -= 1就相当于 a = a - 1;
- 单目操作符
! //逻辑反操作
- //负值
+ //正值
& //取地址
sizeof //操作符的类型长度(以字节为单位)
~ //按位取反(按二进制)
-- //前置--/后置--
++ //前置++/后置++
* //间接访问操作符(解引用操作符)
(类型) //强制类型转换
- 正值/负值操作符:
负值取负变为正值,但负值取正仍为负值 - 自增/自减运算符:
++前置:变量大小立刻加1,返回加之后的值
后置++:变量大小在本段代码执行完后加1,返回加之前的值
(具体内容后面讲解)
- 关系操作符
> >= < <= != ==
//大于 大于等于 小于 小于等于 不等于 等于
- 逻辑操作符
&& ||
//逻辑与 逻辑或 (都支持短路求值)
- 条件操作符
exp1 ? exp2 :exp3 //exp指表达式
这是一个语法糖,可有可无,但是程序员用起来会很舒服.
… ? … : … 这是C语言唯一的一个三目运算符.
9. 逗号表达式
exp1,exp2,exp3...expN
//最后返回的结果只是最后一个 expN的值
- 下标引用/函数调用和结构成员
[ ] ( ) . ->
. 是给结构体变量使用的
->是给结构体指针使用的