前言
今天上了个数据结构课,直接自闭了,记得学习C++已经是去年的事了,再看语法已经忘得七七八八,所以写一篇基础知识博客,助人也助我
本博客适用于有C++基础,正在学C语言数据结构的同学,或者是肯动脑思考的同学。
如果你正在学C++,不出意外也会有所收获,尤其是指针和结构体(华农非计科这部分考的不多)。
关于代码风格,这个因人而异,开始我也喜欢一对中括号对齐,后来写Java慢慢适应左右分开。
最后,因本人能力有限,文章不足之处还望多多指正。
编程模板
C语言模板
#include int main(void) { printf("我爱帅帅龙!");return 0;
}
常用数据类型
简单数据类型:
复杂数据类型:
查看某种数据类型所占字节数:
#include
#include int main(){printf("int 存储大小 : %d \n", sizeof(int));return 0;
}
转义字符
- \n 换行符,类似按下了回车
- \t 横向制表符,输出4个空格
输入输出
C语言使用scanf
进行输入,使用printf
进行输出,当输入简单数据类型的时候要加上&取址符
,但是输出不用加&取址符
,与Python的格式化相似,请看案例。
输入输出一个整数(简单数据类型):
#include int main(void) {printf("请输入一个整数:");int i;scanf("%d",&i);printf("你输入的整数是%d",i);return 0;
}
输入输出一个字符数组(复杂数据类型):
#include int main(void) {printf("请输入一段字符:");char ch[20];scanf("%s",ch);printf("你输入的一段字符是%s",ch);return 0;
}
OK,那为什么会这样呢?其实可以这样理解:
在输入的时候,计算机需要知道变量的地址,因此需要加上取址符,在输出的时候只需要写变量就好了,如果这时候再加上取址符就会得到地址,在格式化的时候原来的变量就变成相应的地址了,注意,数字数组不能直接输入输出
,只有字符数组可以,可以看看下面的例子:
#include int main(void) {printf("请输入一个整数:");int i;scanf("%d",&i);printf("你输入的整数是%d",&i);return 0;
}
除此之外,输入字符还有多种形式,在此不过多介绍
输入输出格式化
格式化方式 | 输入输出含义 |
---|
%d | 输入/输出十进制整数,一般对应int类型 |
%c | 输入/输出字符,一般对应char类型 |
%f | 输入/输出十进制实数,一般对应float类型,也可以是double类型 |
%s | 输入字符或字符数组,输出字符数组 |
%% | 输出百分号(%) |
数组的定义与初始化
常见的数组有字符数组,数值数组,数组支持索引的形式访问和修改元素,在创建的时候需要写上数组大小,通常我们使用数组实现顺序表,时间复杂度为O(1)
数值数组的初始化可以这样来:
double balance[5] = {1000.0, 2.0, 3.4, 7.0, 50.0};
字符数组初始化有两种形式可以选择:
char ch_1[] = "hello";
char ch_2[] = {'h','e','l','l','o','\0'};
除此之外,还有指向数组的指针,我觉得也并不太常用,但是还是介绍一下吧,其实就是通过地址+1
的形式,再解引用获取某数据所在地,再赋值或更新
#include int main (){double balance[5] &#61; {1000.0, 2.0, 3.4, 17.0, 50.0};double *p &#61; balance;printf("使用指针的数组值\n");for (int i&#61;0;i<5;i&#43;&#43;){printf("*(p&#43;%d):%f\n",i,*(p&#43;i));}return 0;
}
数组作为函数参数
函数不需要讲&#xff0c;因为现阶段我们一般不会去用。简单提一下数组作为函数参数的情况&#xff0c;函数的参数只需要声明是那种数组&#xff0c;再写个形参名即可&#xff0c;不需要写数组大小&#xff0c;即&#xff1a;
#include void printArray(int array[]) {for (int i&#61;0;i<5;i&#43;&#43;) {printf("%d\n",array[i]);}
}int main(void) {int array[]&#61;{1,2,3,4,5};printArray(array);return 0;
}
结构体的定义与使用
结构体类似简单的类&#xff0c;用struct
关键字声明&#xff0c;其中有变量或常量存储数据&#xff0c;如果声明后面加上变量名表示创建了一个实例&#xff0c;名为book
&#xff0c;注意&#xff0c;末尾的;
不可省略
struct Books{char title[50];char author[50];char subject[100];int book_id;
} book;
结构体也可以直接初始化&#xff0c;如下&#xff1a;
struct Books{char title[50];char author[50];char subject[100];int book_id;
} book &#61; {"C 语言", "RUNOOB", "编程语言", 123456};
指向结构体的指针
如下&#xff0c;LinkList
等价于Node*
&#xff0c;以后函数返回值或直接声明就可以直接使用LinkList&#xff0c;返回的是一个存放地址信息的指针变量类型
#include
typedef struct Node {int data;struct Node *next;
}Node,*LinkList;int main (){Node *p;p &#61; (LinkList)malloc(sizeof(Node));p->data &#61; 11;printf("%d",p->data);return 0;
}
何为指针与指针类型变量
我们可以使用取址符&
得到变量的地址&#xff0c;其返回值是对应类型的指针类型&#xff0c;例如&#xff1a;
#include int main(void) {int i&#61;1;int *p &#61; &i;printf("当前地址是:%d",p);return 0;
}
字符数组的变量名就表示首地址&#xff0c;所以可以直接输入&#xff1a;
#include int main(void) {char ch[10];scanf("%s",ch);printf("输入的是:%s",ch);return 0;
}
什么叫引用&#xff0c;什么叫解引用&#xff1f;
引用就可以理解为指针类型的数据。例如int *p
&#xff0c;此时p
就可以成为引用&#xff0c;他的值是地址&#xff0c;*p
表示解引用&#xff0c;代表这个地址的对象
#include int main(void) {int i&#61;1;int *p &#61; &i;printf("当前地址是:%d\n",p);printf("数值是:%d\n",*p);return 0;
}
指针类型变量
以BOOK这个结构体为例&#xff0c;其定义如下&#xff1a;
typedef struct Book {int book_id;
} Book;
整体代码如下&#xff1a;
#include typedef struct Book{int book_id;
} Book;int main(void) {Book book1,book2;Book *p &#61; &book2;book1.book_id &#61; 10;p->book_id &#61; 10;printf("book1的id是%d&#xff0c;book2的id是%d",book1.book_id,p->book_id);return 0;
}
从上面的代码格式可以看出&#xff1a;
- 指针类型变量是指针类型的数据&#xff0c;存放的是某变量的地址&#xff0c;应当先创建变量&#xff0c;再取值
- 如果是结构体类型的数据可以直接使用
.
操作符获取元素或赋值 - 如果是指针类型数据需要使用
->
操作符获取元素或赋值
指针对象作为参数的函数
先看下面的代码&#xff0c;发现运行之后book的id没有发生变化&#xff0c;这是因为传参的问题&#xff1a;
#include typedef struct Book{int book_id;
} Book;void add(Book book) {book.book_id &#43;&#61; 1;
}int main(void) {Book book1&#61;{1};printf("book1的原始id是%d\n",book1.book_id);add(book1);printf("book1的现在id是%d\n",book1.book_id);return 0;
}
如果想使用指针将数据进行修改&#xff0c;需要将参数类型修改成指针类型变量&#xff0c;例如&#xff1a;
#include typedef struct Book{int book_id;
} Book;void add(Book *book) {book->book_id &#43;&#61; 1;
}int main(void) {Book book1&#61;{1};printf("book1的原始id是%d\n",book1.book_id);add(&book1);printf("book1的现在id是%d\n",book1.book_id);return 0;
}
数组的变量名就表示首地址
*(p&#43;1)
和*(balance&#43;1)
的效果是一样的&#xff0c;因为p存放的就是数组的首地址&#xff0c;而数组名也表示数组的首地址
#include int main (){double balance[5] &#61; {1000.0, 2.0, 3.4, 17.0, 50.0};double *p &#61; balance;printf("使用指针的数组值\n");for (int i&#61;0;i<5;i&#43;&#43;){printf("*(p&#43;%d):%f\n",i,*(p&#43;i));}printf( "使用balance作为地址的数组值\n");for (int i&#61;0;i<5;i&#43;&#43;){printf("*(balance&#43;%d):%f\n",i,*(balance&#43;i));}return 0;
}
强制类型转换
#include int main(){int sum &#61; 17, count &#61; 5;double mean;mean &#61; (double) sum / count;printf("Value of mean : %f\n", mean );
}
一些排序算法
大家可以看看菜鸟教程实现的六大排序&#xff1a;
https://www.runoob.com/cprogramming/c-sort-algorithm.html
几个可能用到的函数
free——释放内存
把a这个变量给释放掉
int a[10];
free(a);
malloc——申请内存(初始化)
仅仅是申请内存了&#xff0c;类似于C&#43;&#43;的new&#xff0c;但是里面怎么初始化咱不知道&#xff0c;可以后面再进行赋值。Linklist是指针类型变量&#xff0c;如果没有声明&#xff0c;直接写原变量类型的指针变量声明形式&#xff0c;这里是链表的部分代码&#xff0c;可以写成Node*
Linklist L&#61;(Linklist)malloc(sizeof(Node));
几个常见的关键字
#define
#define 是 C 指令&#xff0c;用于为各种数据类型定义别名&#xff0c;与 typedef 类似&#xff0c;但是它们有以下几点不同&#xff1a;
- typedef 仅限于为类型定义符号名称&#xff0c;#define 不仅可以为类型定义别名&#xff0c;也能为数值定义别名&#xff0c;比如您可以定义 1 为 ONE。
- typedef 是由编译器执行解释的&#xff0c;#define 语句是由预编译器进行处理的。
#include #define TRUE 1
#define FALSE 0int main( ){printf( "TRUE 的值: %d\n", TRUE);printf( "FALSE 的值: %d\n", FALSE);return 0;
}
typedef
用typedef
来为类型取一个新的名字&#xff0c;例如给cahr起一个别名叫BYTE&#xff0c;这样&#xff0c;在代码中写char或BYTE都是一个意思了&#xff1a;
typedef char BYTE;
同时&#xff0c;我们还可以为结构体起个别的名字&#xff1a;
typedef struct Books{char title[50];char author[50];char subject[100];int book_id;
} Book;
const
被修饰的变量或数组具有只读特性&#xff0c;不能够被更改&#xff1b;若想对变量重新赋值&#xff0c;则是错误的。
此外&#xff0c;const修饰变量还起到了节约空间的目的&#xff0c;通常编译器并不给普通const只读变量分配空间&#xff0c;而是将它们保存到符号表中&#xff0c;无需读写内存操作&#xff0c;程序执行效率也会提高。
除此之外&#xff0c;const还能修饰函数参数、指针&#xff0c;不再一一介绍
const int i &#61; 5;
sizeof
sizeof 可以获得数据类型或变量在内存中所占的字节数&#xff0c;同时&#xff0c;用 sizeof 也可以获得整个数组在内存中所占的字节数&#xff0c;例如&#xff0c;这个输出40&#xff1a;
# include
int main(void){ int a[10] &#61; {0};printf("sizeof(a) &#61; %d", sizeof(a));return 0;
}
一些问题
变量定义在函数内出错
变量如果定义在函数内&#xff0c;当执行完函数变量会自行销毁&#xff0c;呜呜呜&#xff0c;别乱定义
使用指针类型变量的时候要malloc
使用指针类型数据声明变量的时候&#xff0c;需要使用malloc分配内存&#xff0c;要不然没有空间&#xff0c;如果是非指针类型数据就不用使用malloc了&#xff0c;它声明的时候自动分配空间了