C语言日记①-初识C
Micah Two

概念

c语言是一种计算机语言 也就是人与计算机打交道的语言
在早期,因为计算机使用的二进制 所以早期写代码都是科学家来写的使用对应的功能二进制代码 需要用到手册,所以开发不方便

在后来,人们发明了汇编语言 用于重命名相应的二进制代码,使开发变得方便起来,但是随着代码量的增多,功能越来越臃肿 导致出现了B语言

而c语言正是在B语言基础之上所搭建的高级计算机语言,类似的还有java/c++等

流行的原因

C语言早期出现并不是很成熟 随着使用人数慢慢增加,c语言越来越完善,最后流行了起来,但是有一个问题 每个人或者每个公司都对c语言有过自定义的定制功能,导致在我这里编译的能跑起来的程序,到您那就不行了

国际标准

为了解决这个情况,人们制定一个国家标准

ANSI C -> C89/C90

hello world

这里使用的开发软件是 vs 2019
百度官网下载

安装 c++库即可总共4g

[[vs2019 初始化]]

创建项目

这里命名规则是test_年_月_日_第几个文件

创建一个空的c++项目

image

新建文件,发现没有以c为后缀的模板

直接新建test.c
输入代码:

1
2
3
4
5
6
7
//引用头文件 std-标准 io-输入输出流 类似于java的库 .h head 头文件
#include <stdio.h>
//主函数--程序的入口 .c c语言源文件
int main() {
printf("hello world\n");
return 0;
}

按F5运行

控制台输出hello world

image

vs 2019快捷键

ctrl+/ 注解生成 设置
image

ctrl+k+d 格式化代码

bit与字节与各种类型的关系

1
2
3
4
5
6
7
8
9
10
八个bit等于一个字节

c语言中的各种类型 与字节大小:
char 2
short 2 意思就是一个short可以占用十六个bit的空间 也就是 2^16-1 65535个数字
int 4
long 8
long long 16
float 4
double 8

主要定义类型还是看需求

地址的解释和输入流的使用

image

地址为某个对象存放在电脑内存中的独有id,可直接查找到相应的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//引用头文件 std-标准 io-输入输出流 类似于java的库 .h head 头文件
#include <stdio.h>
//主函数--程序的入口 .c c语言源文件
int main() {
//printf("hello world\n");

//int a = 10;
//printf("%d\n", a+10);

//char c = 'A';
//printf("%c", c);

int num1 = 0;
int num2 = 0;
scanf_s("%d%d", &num1, &num2);
printf("%d", num1 + num2);
return 0;
}
scanf_s(要输入的类型,...要赋值的对象的地址)

作用域与全局变量

与java类似

但是有个全局作用域,全局变量在整个项目中都可以使用

首先在源文件中定义sum.c

1
int g_num=2021;

再在main中使用

1
2
3
4
5
int main() {
extern int g_num;
printf("%d", g_num);
return 0;
}

要使用全局变量,首先变量名要相同,其次 在要使用的变量前面声明extern

跨平台性的兼容

vs平台认为scanf函数并不安全 所以直接推出scanf_s函数,但是其他编译平台没有,这就导致了该程序只能在vs的平台上运行

所以这里只用使用scanf就好了,查看他报的错误,开启配置

_CRT_SECURE_NO_WARNINGS

在文件的最上方输入#define 配置名称 数值

1
#define _CRT_SECURE_NO_WARNINGS 1

此时使用scanf函数不报错即可运行

一劳永逸

^1b1801

每次创建文件都要加上#define _CRT_SECURE_NO_WARNINGS 1是不是很恶心
所以有这样种方式可以一劳永逸
image

打开所在位置

然后打开这个路径
.\VC\VCProjectItems

找到newc++file.cpp 打开修改
image

保存
此时创建一个新的c时,默认带入该代码
image

各种常量

字面常量

1,2,3
这种都叫字母常量

常变量

使用const关键词修饰的的变量叫常变量

常变量不能作为下面举例的方法中使用
标识符常量

常变量不能被修改 不然编译会报错

标识符常量

使用#define 定义的常量叫标识符常量,这种方式定义出来的数值就真的是常量了

使用案例

1
2
3
4
5
6
7
8
9
10
#define MAX 10
//引用头文件 std-标准 io-输入输出流 类似于java的库 .h head 头文件
#include <stdio.h>
//主函数--程序的入口 .c c语言源文件
int main() {
int arr[MAX] = { 0 };
printf("%d", arr);

return 0;
}

这里注意下,使用define 定义不能加;不然会报错

枚举

enum
定义 和使用 与java类似
代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
enum Sex {
MAN,
WOMAN,
SECRET
};

int main() {
printf("%d\n", MAN);//0
printf("%d\n", WOMAN);//1
printf("%d\n", SECRET);//2

enum Sex sex = SECRET;

printf("%d\n", sex);//2

return 0;
}

字符串

在c中
使用双引号括起来的字符就叫字符串

这里使用两种方式生成字符串,同时打印出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main() {
char str[] = "abc";
char str2[] = { 'a',
'b',
'c',
//"\0"
};
printf("%s\n", str);//abc
printf("%s\n", str2);//abc 乱码

return 0;
}

为什么会有乱码呢?
调试可以发现 字符串必须以\0 或 0结尾
此时我们加上,顺便查看字符串长度

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
int main() {
char str[] = "abc";
char str2[] = { 'a',
'b',
'c',
"\0"
};
//printf("%s\n", str);
//printf("%s\n", str2);
printf("%d\n", strlen(str));
printf("%d\n", strlen(str2));

return 0;
}

发现值相同

转义符
有些字符串想打出他本来的意思,可以使用转义符
\

注释

1
2
3
4
5
6
// c++风格的注释

/*
c语言风格的注释
*/

用处 可以解释翻译你写的代码

函数

定义

1
2
3
返回值类型 方法名(...类型 参数){
return 返回值;
}

作用

简化方法的引用

数组

1
int a[] = { 1,2,3,4,5,6,7,8,9,1,2,3,4,6,7,8,9,11 };

数组长度获取

int length = sizeof(a) / sizeof(a[0]);
sizeof(a) = 数组长度乘以该数组类型分配的字节
sizeof(a[0])=当前数组的类型的字节
相除得到数组长度

leecode算法题

获取数组中没有重复两次的数据
比如1,2,3,4,5,1,2,3,4 要取到5

c写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int a[] = { 1,2,3,4,5,6,7,8,9,1,2,3,4,6,7,8,9,11 };
int length = sizeof(a) / sizeof(a[0]);
for (int i = 0; i < length; i++)
{
int count = 0;
for (int j = 0; j < length; j++)
{
if (a[i] == a[j]) {
count++;
}
}
if (count == 1) {
printf("%d\n", a[i]);
}
}

java写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//1
int[] arr={1,2,3,4,5,6,7,8,9,1,2,3,4,6,7,8,9,11};
List<Integer> countArr=new ArrayList<>();
for (int i : arr) {
if (!countArr.contains(i))
countArr.add(i);
else {
for (int i1 = 0; i1 < countArr.size(); i1++) {
if (countArr.get(i1)==i){
countArr.remove(i1);
}
}
};
}
System.out.println(countArr);


//2
int[] arr={1,2,3,4,5,6,7,8,9,1,2,3,4,6,7,8,9,11};
for (int k : arr) {
int count = 0;
for (int i : arr) {
if (i == k)
count++;
}
if (count == 1) {
System.out.println(k);
}
}

算法优化

这里是最优解
java

1
2
3
4
5
6
7
8
int[] arr={1,2,3,4,5,1,2,3,4};  
int ret=0;
for (int i : arr) {
//0^任何一个数 等于任何一个数 任何一个数^任何一个数等于0 由此可以判断 ^可以打乱顺序,结果不会变
// 同时可以排除掉有两对的数据 但是这种算法不可找到第二个排除的
ret=ret^i;
}
System.out.println(ret);

转换成c

1
2
3
4
5
6
7
int arr[] = { 1,2,3,4,5,1,2,3,4 };
int length = sizeof arr / sizeof arr[0];
int ret = 0;
for (int i=0; i < length;i++) {
ret = ret ^ arr[i];
}
printf("%d", ret);

[[C语言日记② 初识C的内存]]

由 Hexo 驱动 & 主题 Keep
总字数 15.9k 访客数 访问量