个人笔记——C语言入门的零散笔记

你离开我真会死。 提交于 2019-11-29 18:32:01

说明

笔者为考研开始学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的两倍

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!