C语言入门的零散笔记
说明
笔者为考研开始学c,鉴于已经有了python基础,故之后的笔记仅对一些必要、易遗忘处进行记录
格式/语法
整体格式
#include <stdio.h>
int main()
{
printf("Hello World!\n");
}
需要注意每条执行语句后的分号“;”
C中的注释
单行注释采用//
多行注释采用/开头/结尾
// 单行注释
/*
多行注释
多行注释
*/
定义常量
const int AMOUNT = 100
const是一个修饰符,表示这个变量的值一旦被初始化,就不能再修改了
++与--
a++等效于a += 1,不过++和–既可以放在a前面也可以放在a后面,对a的效果相同,但如果给其赋值则不一样,例如下:
#include <stdio.h>
int main()
{
int a = 10;
printf("a++=%d\n", a++)
printf("a=%d\n", a)
printf("++a=%d\n", ++a)
printf("a=%d\n", a)
}
>>a++=10
a=11
++a=12
a=12
输入
// 先定义变量
int a = 0
// 输入
scanf("%d", &a)
double b;
scanf("%lf", &b)
切记&符号
判断if语句
if (a>b){
语句
}else{
语句
}
if和else后面也可以不用{}而采用换行缩进的方式,但这种方式仅能执行一条语句
当有嵌套的if时,如果采用缩进的方式,else配套的是离他最近的的if判断,无论else是否有缩进,如下例:
int a = 2;
int b = 3;
int c = 4
if (a==b)
printf("123");
if (b<c)
printf("222");
else:
printf("3333");
不会输出任何值,仅当条件都成立的时候,才会打印3333
建议始终使用{}
if (条件1){
}else if(条件2){
}else{
}
循环
普通的while只需把if换成while即可
while(条件){
语句
}
另外还有do-while循环,是先进入循环体再判断条件,判断成功再次执行
do{
语句
}while(条件);
第三种类python中的for循环:
int i = 1;
for (i=1; i<=n; i++) {
语句
}
注意用;分开for里面的语句
for循环是编程语言中一种循环语句,而循环语句由循环体及循环的判定条件两部分组成,其表达式为:for(单次表达式;条件表达式;末尾循环体){中间循环体;}。
1.for循环中的变量可以是一个也可以是多个。
2.for循环中语句可以为语句体, 语句体外加大括号"{}“将参加循环的语句括起来。
3. for循环中的"单次表达式”、"条件表达式"和"循环体语句"都是选择项, 即可以缺省成只剩下“;”的空语句,。
break和continue都只能作用在其所在的一层循环,而不能跳出所有循环。
跳出所有循环有两种办法:
1.设定跳出的条件,例如新增一个变量来进行判断,判断成功后改变变量值,在每一层循环都新增一个if break的判断来一层层跳出
2.使用 goto 可以直接跳转至 goto: 之后的语句,但一般情况程序不推荐使用这种goto语句跳转,容易使程序混乱。
switch-case
当if中需要判断的条件情况特别多时,就可以使用switch-case语句
switch(type){
case 1:
printf("你好");
break;
case 2:
printf("早上好");
break;
case 3:
printf("下午好");
break;
case 4:
printf("晚上好");
break;
default:
printf("啊?说啥嘞?");
}
即根据type的值不同,打印不同的值,default相当于else
注意:控制表达式(即上例中的type)只能是整数型。如果没哟写break会直接进入下一个case执行,知道遇到break
函数
C语言的类型
整数:
- char; short; int; long; long long(C99的类型)
-
例:
char a = 255;
int b = 255;
printf("%d, %d", a, b);
>>-1 255
unsigned char a = 255;
int b = 255;
printf("%d, %d", a, b);
>>255 255
char
char也可以是字符
printf("%c", '字符');
scanf("%c", '字符');
浮点数:
- float; double; long double(C99的类型)
inf表示无穷大,nan表示不存在
%e是输出科学技术法
如a=1.456默认是double,如果要定义为float,需要在数值后面加f,如:a = 1.456f
如没有特殊需要,直接用double即可
逻辑:
- bool(C99的类型)
- 要使用bool必须在开始加上include <stdbool.h>
需要注意!是单目运算符,优先级高于>等,例如 ! age>20,会优先处理 ! age,然后再和20作比较
注意:不要将赋值写进逻辑判断,避免短路
指针
scanf("%d", &a)中的&,其作用就是获得变量的地址,类似于python中“引用”的概念
指针就是保存地址的变量,例:
int i;
int* p = &i;
int* p,q; int *p,q; 注意这两条语句等效,但q都不是指针,只有p是
输出:
printf("%p", p) // 打印地址
printf("%d", *p) // 打印值
注意:如果将一个数组传递给函数,则实际传递的是数组的指针,在函数内对数组进行修改会对数组的实际值造成改变
#### 动态内存分配
字符串
定义字符串变量:
char *str = 'Hello';
char world[] = 'Hello';
char int[10] = 'Hello'; // Hello实际占据了6个位置,因为还有末尾的0
注意: 如果想对字符串进行修改,例如s[0] = ‘a’ 则可以用数组的方式定义字符串,两者的区别是 char* s 是“我指向那个字符串”(字符串保存在代码段,这里是不可修改的,系统有保护机制), s[]= 是“那个字符串在我这里”
字符串的输入输出
char s[8];
scanf("%s", s);
scanf("7%s", s)
使用scanf("%s")读取输入,但读到空格、tab、回车就回停止,超出字符限制会报错
scanf("%7s")表示最多只能输入7个字符
字符串数组
char *a[12]={"January","February","March","April","May",
"June","July","Auguest","September","October","November","December"};
字符串函数
使用字符串函数需要引用<string.h>
- int putchar(int c);
- 向标准输出写一个字符;返回写了几个字符,EOF(-1)表示写失败
- int getchar(void);
- 从标准输入读入一个字符;返回类型是int是为了返回EOF(-1)
- strlen:获取字符串长度
- strcmp(const char *s1, const char *s2):比较两个字符串——0:s1==s2; (s1-s2>0):s1>s2;(s1-s2<0):s1<s2
- strcpy(char *restrict dst, const char *restrict src):把src的字符串拷贝到dst,restrict表示两个字符串不重叠,例:
char *dst = (char*)malloc(strlen(src)+1);
strcpy(dst, src);
- strcat(char *restrict s1, const char *restrict s2):把s2拷贝到s1的后面
以上函数都存在风险,即目标地址可能没有足够空间,所以需要有以下安全版本的函数:
strncpy(char *restrict dst, const char *restrict src, size_t n);
strncat(char *restrict dst, const char *restrict src, size_t n);
strncmp(const char *s1, const char *s2, size_t n); // 只比较前n个字符
中间的n表示最多拷贝过去多少个
- char *strchr(const char *s, int c):在字符串中找字符,从左边第一次出现的位置
- char *strrchr(const char *s, int c):在字符串中找字符,从右边第一次出现的位置
返回Null表示没找到,找到的话返回值是一个指针 - char strstr(const char s1, const char* s2):在字符串中找字符串
- char strcasestr(const char s1, const char* s2):在字符串中找字符串,忽略大小写
自定义类型
返回类型
void 无类型,不返回
类型转换
自动类型转换
强制类型转换
参数
void test()表示参数不确定
void test(void)表示确定不传参
建议在编写程序时,一定要在()内写明确,避免错误
数组
格式:
<类型> 变量名称[元素数量]
例:
int test[100]
数组一旦创建,无法改变大小
- 也可以直接定义数组,和python中格式有点区别:
int a[] = {1, 2, 3}
- 也可以给制定位置赋值,其他位置用0填充,可以不指定数组大小,让计算机自己计算,会取用最大位置作为数组大小,适用于比较稀疏的数据
例:
int a[10] = {[0] = 2, [2] = 3, 6, }
// 仅限C99
'''上方最后一个逗号只是远古传统,有没有对程序没影响,早先是为了方便之后再添加数值'''
注:数组不能直接赋值,如:int a[] = {1, 3, 5} b[] = a,只能通过遍历把原有元素交给另一个数组
如何获取数组大小?
printf("%lu", sizeof(a));
上方语句可以获得数组a的字节大小,再除以sizeof(a[0])就可以获得数组包含的个数,即:
printf("%lu", sizeof(a)/sizeof(a[0]));
二维数组
int a[3][5] 三行五列
在定义二维数组的时候,列数必须给出,行数可以由编译器来数,如:
int a[][5] = {
{1, 3, 5, 6, 8},
{4, 6, 8, 1, 3},
}
随机
每次使用rand()就可以得到一个随机的整数
全局变量
例:
#include <stdio.h>
int main(int argc, char const *argv[]){
f();
f();
f();
}
int f(void){
static int all = 1;
printf("in %s all=%d\n", __func__, all);
all += 2;
printf("agn in %s all=%d\n", __func__, all);
}
>>in f all=1
agn in f all=3
in f all=3
agn in f all=5
in f all=5
agn in f all=7
如果没有static,则输出永远都是1和3
编译预处理
- #开头的是编译预处理指令
- 它们不是C语言的成分,但是C语言程序离不开它们
- #define用来定义一个宏
例如早期C版本没有const选项,就可以使用宏来定义固定参数,例:
#define PI 3.14159
然后在编译器开始编译前,编译预处理程序(cpp)会把程序中的PI都替换成3.14159
除了定义常数还可以定义带参数的函数,例:
#include <stdio.h>
#define cube(x) ((x)*(x)*(x))
int main()
{
printf("%d", cube(5));
return 0;
}
还可以带多个参数
#define MIN(a, b), ((a)>(b)?(b):(a))
结构类型
枚举
- 枚举是一种用户定义的数据类型,它用关键字 enum 以如下语法来说明:
enum 枚举类型名字{名字0, ... , 名字n};
结构
结构相当于python中的类
联合
联合定义的方式类似于结构,不同在于其所有成员是共用一份内存空间,会互相覆盖
应用示例:
相当于将存放i的内存,依次用16进制进行读取
#include <stdio.h>
typedef union{
int i;
char ch[sizeof(int)];
}CHI;
int main(int argc, char const *argv[])
{
CHI chi;
int i;
chi.i = 1234;
for ( i=0; i<sizeof(int); i++ ){
printf("%02hhX", chi.ch[i]);
}
printf("\n");
return 0;
}
大程序结构
如果要讲一个大型程序拆分,类似python中import的形式导入,则需要在Dev C++中新建一个项目,然后将几个源文件加入进去
头文件
- 把函数原型放到一个头文件(.h结尾)中,在需要调用这个函数的源代码文件(.c文件)中 #include 这个头文件,就能让编译器在编译时知道函数的原型
使用其他源文件中的全局变量
需要在.h文件中进行声明
extern int abc;
文件
格式化输入输出
printf
flags
width / .prec
#### hiL
type
scanf
flag
type
文件输入和输出
- 用>和<做重定向
二进制文件
位运算
原则
1.每一个变量在被使用前都必须要先定义,并赋予一个初始值
2.使用scanf读取输入时,输入值必须满足scanf内的格式字符串,例如下方输入a和b,则输入时必须输入“a, b”才行(包括空格)
int a = 0;
int b = 0;
scanf("%d, %d", &a, &b);
printf("%d, %d", a, b);
3.C语言中两个整数的运算,结果也只能是整数,小数部分会被直接舍弃,也不会四舍五入。小数分为double和float,double占据的数据大小是float的两倍
来源:https://blog.csdn.net/sinat_38354769/article/details/100202593