//一个8位的空间,如果表示无符号数0-255 unsigned char 0~2^8 -1
//如果用来表示有符号数 -128~127 char -2^7 ~2^7-1
//对其范围的探求,不止于,自字节数
#if 0
1字节 char
0 - 255 unsigned char 0~2^8 - 1
-128~127 char -2^7 ~2^7-1
2字节 short
0 -65535 0 ~2^16 -1
-32768 -32767 -2^15~ 2^15-1
4个字节 int
#endif
输入输出
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
int a = 1;
printf("%2d\n", 123456);//当实际宽度大于域宽时,按实际输出
printf("%2d\n", a);
printf("%10d\n", 10);
printf("%-10d###\n", 10); //左对齐
printf("%15d\n", 123456); //默认空格
printf("%015d\n", 123456); //0 右对齐时用0补齐 默认空格
}
/*
123456
1
10
10 ###
123456
000000000123456
*/
数组
//相同的数据类型构造,就构成了数组
//不同的数据类型,就构成了结构体
//对于构造类型来说,
//定义 大小 初始化 访问
//未初始化
//满初始化
//部分初始化,其余部分清零;初始化清零
//越界初始化 禁止 c语言对于越界是不检的 灵活
凡是构造类型,在定义的时候初始化,不可以先定义再初始化的方式赋值
凡是基本数据类型,既可以在定义时初始化,也可以先定义,再赋值
int main(int argc, char* argv[]) {
int arr[10] = {
1,2,3,4,5,6,7,8,9,10};
for (int i = 0; i < 10; i++) {
printf("arr[%d] = %d\n",i,arr[i]);
}
printf("sizeof(arr)=%d\n", sizeof(arr));
printf("sizeof(arr[0])=%d", sizeof(arr[0]));
}
int main(int argc, char* argv[]) {
int arr[10] = {
0};
for (int i = 0; i < 10; i++) {
arr[i] = rand() % 50; //[0,50)
}
for (int i = 0; i < 10;i++) {
printf("arr[%d] = %d\n",i,arr[i]);
}
}
一维数组的存储
一维数组,在内存中是一段连续的存储区域
#include <stdio.h>
int main(int argc, char* argv[]) {
int arr[10];
for (int i = 0; i < 10; i++) {
printf("&arr[%d]= %p\n",i,&arr[i]);
}
}
/*
&arr[0]= 000000231DF2FCC8
&arr[1]= 000000231DF2FCCC
&arr[2]= 000000231DF2FCD0
&arr[3]= 000000231DF2FCD4
&arr[4]= 000000231DF2FCD8
&arr[5]= 000000231DF2FCDC
&arr[6]= 000000231DF2FCE0
&arr[7]= 000000231DF2FCE4
&arr[8]= 000000231DF2FCE8
&arr[9]= 000000231DF2FCEC
*/
数组的三要素
数组的声明,已经把数组访问不的三要素,均已表示出来了,三要素就是,起始位置、移步刻度、终止位置。
#include <stdio.h>
int main(int argc, char* argv[]) {
int maxValue;
int minValue;
int arr[10] = {
100,2,7,4,5,6,7,8,9,10};
maxValue = arr[0];
minValue = arr[0];
for (int i = 0; i < 10; i++) {
if (maxValue < arr[i]) {
maxValue = arr[i];
}
if (minValue > arr[i]) {
minValue = arr[i];
}
}
printf("int arr max = %d;min = %d", maxValue, minValue);
return 0;
}
#include <stdio.h>
int main(void)
{
// int arr[] = { 1,2,3,4,56 };
// int[4] arr[3];
// int arr[3][4]; // int[4] arr[3];T arr[3]
int arr[][3] = {
1,2,4,5,6,7,9,10,11,12 };
for (int i = 0; i < sizeof(arr) / sizeof(int[3]); i++) {
for (int j = 0; j < 3; j++) {
printf("%3d", arr[i][j]);
}
putchar(10);
}
printf("sizeof(arr)=%d\n",sizeof(arr));
return 0;
}
三要素
#include <stdio.h>
int main(void)
{
int arr[4];
printf("%p\n", arr); //起始地址
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p arr + 1 = %p\n",arr,arr + 1); //步长
return 0;
}
#include <stdio.h>
int main()
{
int arr[3][4]; //int[4] arr[3] T arr[3]
printf("arr = %p \n", arr); //起始地址
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p arr + 1 = %p\n", arr, arr + 1); //步长 16 一个一维数组的大小
printf("arr[0] = %p\n",arr[0]); //内嵌一维数组的起始地址
printf("&arr[0][0] =%p \n",& arr[0][0]); //内嵌一维数组首元素的地址
printf("arr[0] + 1 = %p\n",arr[0] + 1);//内嵌一维数组的步长 4
printf("sizeof(arr[0]) = %d sizeof(int[4])= %d\n",sizeof(arr[0]), sizeof(int[4])); //16
printf("sizeof(arr) = %d\n", sizeof(arr)); //48
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
arr[i][j] = rand() % 100;
}
}
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%3d", arr[i][j]);
}
putchar(10);
}
return 0;
}
/*
arr = 000000869E33FBB8
&arr[0] = 000000869E33FBB8
arr = 000000869E33FBB8 arr + 1 = 000000869E33FBC8
arr[0] = 000000869E33FBB8
&arr[0][0] =000000869E33FBB8
arr[0] + 1 = 000000869E33FBBC
sizeof(arr[0]) = 16 sizeof(int[4])= 16
sizeof(arr) = 48
41 67 34 0
69 24 78 58
62 64 5 45
*/
//一维数组的数组名,是一级指针
//二维数组的数组名是,数组指针
arr = &arr[0]
*arr = arr[0]
#include <stdio.h>
int main()
{
int arr[3][4];
printf("arr = %p\n", arr);
printf("&arr[0] = %p\n", &arr[0]);
printf("arr+1 = %p\n", arr + 1);
// & reference * dereferrence
printf("arr[0] = %p\n",arr[0]);
printf("&arr[0][0] = %p\n", &arr[0][0]);
printf("arr[0] + 1 = %p\n", arr[0] + 1);
printf("arr = %p\n", arr );
printf("arr + 1= %p\n", arr + 1);
//arr = &arr[0]
printf("*arr = %p\n", *arr);//arr[0]
printf("*arr + 1 = %p\n", *arr + 1);
return 0;
}
/*
arr = 000000B6EE10FC28
&arr[0] = 000000B6EE10FC28
arr+1 = 000000B6EE10FC38
arr[0] = 000000B6EE10FC28
&arr[0][0] = 000000B6EE10FC28
arr[0] + 1 = 000000B6EE10FC2C
arr = 000000B6EE10FC28
arr + 1= 000000B6EE10FC38
*arr = 000000B6EE10FC28
*arr + 1 = 000000B6EE10FC2C
*/
二维数组的数组名是,数组指针
#include <stdio.h>
int main()
{
int arr[3][4] = {
{
2,2,2,0} ,{
1,2,0,3}, {
4,4,4,4} };
printf("arr = %p\n", arr);
printf("&arr[0] = %p\n", &arr[0]);
printf("arr+1 = %p\n", arr + 1);
// & reference * dereferrence
printf("arr[0] = %p\n",arr[0]);
printf("&arr[0][0] = %p\n", &arr[0][0]);
printf("arr[0] + 1 = %p\n", arr[0] + 1);
printf("arr = %p\n", arr );
printf("arr + 1= %p\n", arr + 1);
//arr = &arr[0]
printf("*arr = %p\n", *arr);//arr[0]
printf("*arr + 1 = %p\n", *arr + 1);
//想访问第2行的第二个元素 arr+1 => a[1] *(arr + 1) = &a[1]
//(*(arr + 1) + 1) => &a[1][1]
printf("a[1][1] = %d\n", *(*(arr + 1) + 1));
//&arr[0] + 1 = &a[1] =
//想访问第2行的第二个元素 arr+1 => &a[1] *(arr + 1) = &a[1]
//(*(arr + 1) + 1) => &a[1][1]
return 0;
}
/*
arr = 000000CC63CFF518
&arr[0] = 000000CC63CFF518
arr+1 = 000000CC63CFF528
arr[0] = 000000CC63CFF518
&arr[0][0] = 000000CC63CFF518
arr[0] + 1 = 000000CC63CFF51C
arr = 000000CC63CFF518
arr + 1= 000000CC63CFF528
*arr = 000000CC63CFF518
*arr + 1 = 000000CC63CFF51C
a[1][1] = 2
*/
int main() {
char *p, q;//声明了一个指针变量,一个int类型的变量
printf("sizeof(p) = %d sizeof(q) = %d\n",sizeof(p),sizeof (q));
}
指针的运算
#include <stdio.h>
//指针 类型(步长) 地址(物理数据)
int main() {
int data = 0x12345678;
char *pc = &data;
printf("%x\n", *pc);
int *p = (int *) 0x0001;
int pData = 0x0001;
printf("p = %#x p+1 = %#x\n", p, p + 1);
printf("pData = %#x pData+1 = %#x\n", pData, pData + 1);
printf("(double*)p = %#x (double*)p+1 = %#x\n", (double*)p, (double*)p + 1);
printf("(int)pData = %#x (int)pData+1 = %#x\n", (int)pData, (int)pData + 1);
printf("%x\n",++p);
printf("%x\n",++pData);
int arr[10];
int pHead = (int)&arr[0];int pTail = (int)&arr[9];
printf("%d\n",pHead - pTail); //-36
// int arr[10];
// int *pHead = &arr[0];int *pTail = &arr[9];
// printf("%d\n",pHead - pTail); //-9
}
/*
pData = 0x1 pData+1 = 0x2
(double*)p = 0x1 (double*)p+1 = 0x9
(int)pData = 0x1 (int)pData+1 = 0x2
5
2
-36
*/
判断是否是回文数
int main() { char name[5] = { 'm', 'a', 'd', 'a', 'm'}; char *ph = &name[0]; char *pt = &name[4]; int flag = 1; while(ph < pt){ if (*ph == *pt ){ ph ++; pt --; } else{ break; flag = 0; } } if (flag == 1){ printf("yes"); } else{ printf("非回文"); } return 0; }
#include <stdio.h>
int main() {
//数组访问 偏移法
int arr[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// for (int i = 0; i < 10; i++) {
// printf("%d\n", *(arr + i)); // arr = &arr[0] *arr = arr[0]
// }
//数组名是指针常量,方可唯一的表示一个数组。数组名是数组的唯一标识符。
printf("arr = %p\n", arr);
printf("arr + 1 = %p\n", arr + 1);
printf("&arr[0] = %p\n", &arr[0]);
printf("&arr[0]+1=%p", &arr[0] + 1);
//&arr[0] ==arr 在一定程度上。 int *
//一维数组名,可以赋给一级指针
int *pa = &arr[0];
int *pb = arr;
//数组名能干的指针就能干,数组名不能干的 指针也能干
return 0;
}
/*
arr = 00000073a7dff970
arr + 1 = 00000073a7dff974
&arr[0] = 00000073a7dff970
&arr[0]+1=00000073a7dff974
*/
#include <stdio.h>
int main() {
int arr[10] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int *pa = arr;
for (int i = 0; i < 10; i++) {
printf("%d\n", *(pa + i));
}
for (int i = 0; i < 10; i++) {
printf("%d\n", pa[i]);
}
for (int i = 0; i <10 ; ++i) {
printf("%d\n",*pa++);
}
return 0;
}
int *pa = arr; for (int i = 0; i < 10; ++i) { printf("%d\n", *(pa++)); }
小结:
- 数组名是一个常量,不允许重新赋值
- 指针变量是一个变量,可以重新赋值
- p+i和a+i均表示数组元素a[i]的地址,均指向a[i]
- //(p+i)和 (a+i)均表示p+i和a+i所指向的内容a[i]
- p++ = (p++) 先得到 *p 再使 p=p+1
- (*p)++表示将p所指向的元素的值加一,等价于a[i]++
- 指向数组元素的指针也可以表示成数组的形式,即允许指针变量带下标,*(p+i) 也可以表示成p[i]
二维数组的访问方式
下标法
数组元素的表示方法是:数组名[行] [列]
本质偏移法
a a[0] a[0] [0]
int a[3] [4]; a = &a[0]
*a = a[0]
&a[0] = a
a[i] <==> *(a+i)
a[i] [j] <==> ((a+i)+j)
a是数组首元素的地址,所以a的值和&a[0]的值相同,另一方面,a[0]本身是包含4个整数的数组,因此,a[0]的值同其首元素的地址&a[0] [0]相同。简单的讲,a[0]是一个整数大小对象的地址,而a是4个整数大小对象的地址。因为整数和4个整数组成的数组开始于同一个地址,因此a和a[0]的值是相同的。
a 所指的对象大小是4个int,而a[0]所指的对象大小一个int 所以a+1 和 a[0] + 1
推论(仅助理解)
二维数组名解引用,降维为一维数组名 *(a+1) a[1]
一维数组名,对其引用,升级为二维数组名 &a[1] <>(a+1)
&引用和*解引用互为逆向关系
#include <stdio.h>
int main() {
int arr[3][4] = {
1, 2, 3, 4,
10, 20, 30, 40,
100, 200, 300, 400};
for (int i = 2; i >= 0; i--) {
for (int j = 3; j >= 0; j--) {
printf("arr[%d][%d] = %#x\n", i, j, &arr[i][j]);
}
printf("=======\n");
}
// arr[2][1] ==> *(*(arr + 2)+1)
printf("%d\n", *(*(arr + 2) + 1));
printf("arr = %#p arr+1 = %#x arr+2 = %#x \n", arr, arr + 1, arr + 2);
printf("arr[0] = %#p arr[0]+1 = %#x arr[0]+2 = %#x \n", arr[0], arr[0] + 1, arr[0] + 2);
printf("*arr = %#p *arr+1 = %#x *arr+2 = %#x \n", *arr, *arr + 1, *arr + 2);
printf("&arr[0] = %#p &arr[0]+1 = %#x &arr[0]+2 = %#x \n", &arr[0], &arr[0] + 1, &arr[0] + 2);
printf("arr[0][0] = %d arr[0][1] = %d arr[0][2] = %d \n", *arr[0], *(arr[0] + 1), *(arr[0] + 2));
printf("arr[0][0] = %d arr[0][1] = %d arr[0][2] = %d \n", **arr, *(*arr + 1), *(*arr + 2));
//arr arr[0]
// *arr --> arr[0]
//arr[0] arr
// &arr[0] --> arr
return 0;
}
/*
arr[2][3] = 0x1e9ffa1c
arr[2][2] = 0x1e9ffa18
arr[2][1] = 0x1e9ffa14
arr[2][0] = 0x1e9ffa10
=======
arr[1][3] = 0x1e9ffa0c
arr[1][2] = 0x1e9ffa08
arr[1][1] = 0x1e9ffa04
arr[1][0] = 0x1e9ffa00
=======
arr[0][3] = 0x1e9ff9fc
arr[0][2] = 0x1e9ff9f8
arr[0][1] = 0x1e9ff9f4
arr[0][0] = 0x1e9ff9f0
=======
200
arr = 0x481e9ff9f0 arr+1 = 0x1e9ffa00 arr+2 = 0x1e9ffa10
arr[0] = 0x481e9ff9f0 arr[0]+1 = 0x1e9ff9f4 arr[0]+2 = 0x1e9ff9f8
*arr = 0x481e9ff9f0 *arr+1 = 0x1e9ff9f4 *arr+2 = 0x1e9ff9f8
&arr[0] = 0x481e9ff9f0 &arr[0]+1 = 0x1e9ffa00 &arr[0]+2 = 0x1e9ffa10
arr[0][0] = 1 arr[0][1] = 2 arr[0][2] = 3
arr[0][0] = 1 arr[0][1] = 2 arr[0][2] = 3
Process finished with exit code 0
*/
二维数组的本质是,数组指针 二维数组名 跟二级指针没有毛关系
#include <stdio.h>
int main()
{
char* p = "abcdef";//"abcdef"是一个常量字符串
//*p = 'W'; 错误的 segmentation fault 段错误
printf("%s\n",p);
printf("%c\n", *p);
printf("%s\n",p); //%s 指针p 会打印整个字符串
return 0;
}
int main()
{
char arr1[] = "abcdef";
char arr2[] = "acbdef";
char* p1 = "abcdef";
char* p2 = "abcdef";
if (arr1 == arr2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
}
//输出haha
int main()
{
char arr1[] = "abcdef";
char arr2[] = "acbdef";
char* p1 = "abcdef";
char* p2 = "acbdef";
if (p1 == p2)
{
printf("hehe\n");
}
else
{
printf("haha\n");
}
}
//输出hehe
指针数组 是数组 用来存放指针的
int main()
{
int arr[10] = {
0 };//整型数组
char ch[5] = {
0 };//字符数组
int* parr[4];//存放整型指针的数组 -指针数组
char* pch[5];//存放字符指针的数组 -指针数组
return 0;
}
int main()
{
int a = 10;
int b = 20;
int c = 30;
int d = 40;
int* arr[4] = {
&a,&b,&c,&d };
int i = 0;
for (i = 0; i < 4; i++)
{
printf("%d ",*(arr[i]));
}
return 0;
}
//输出 10 20 30 40
指针加一并不是单纯的加一,而是指向下一个元素的地址,看指针的类型,例如int 则是郏4个字节
int main()
{
int arr1[] = {
1,2,3,4,5};
int arr2[] = {
2,3,4,5,6};
int arr3[] = {
3,4,5,6,7};
int* parr[] = {
arr1, arr2,arr3};
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", * (parr[i] + j));
}
printf("\n");
}
return 0;
}
数组指针
//数组指针 - 指针
int main()
{
//int* p = NULL;//整型指针 -指向整型的指针 - 可以存放整型的地址
//char* pc = NULL;//pc是字符指针 -指向字符的指针 - 可以存放字符的地址
//数组指针 - 指向数组的指针 - 可以存放数组的地址
//int arr[10] = { 0 };
// arr - 首元素地址
//&arr[0]- 首元素地址
//&arr - 数组的地址
int arr[10] = {
1,2,3,4,5,6,7,8,9,10 };
int (*p)[] = &arr;//数组的地址要存起来
printf("%d", (*p)[0]); //(*p) 相当于 arr
}
int main()
{
char* arr[5];
char* (*pa)[5] = &arr;
return 0;
}
数组指针的使用
int main()
{
int arr[10] = {
1,2,3,4,5,6,7,8,9,10 };
int (*pa)[10] = &arr;
for (int i = 0; i < 10; i++)
{
//printf("%d ",(* pa)[i]);
printf("%d ", *(*pa + i));// *pa数组首元素的地址 + i 第i个元素的地址 然后解引用
}
return 0;
}
//参数是数组的方式
void print1(int arr[3][5],int x,int y)
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
//printf("%d ", (*(arr))[i] + j);
printf("%d ", arr[i][j]); //理解成二维数组中 一维数组的 数组名
}
printf("\n");
}
}
//参数是指针的形式
void print2(int (*p)[5],int x,int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
//printf("%d ", *(*(p + i) + j));
printf("%d ", (*(p + i))[j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {
{
1,2,3,4,5},{
2,3,4,5,6},{
3,4,5,6,7} };
print1(arr,3,5);//arr - 数组名 - 首元素地址 看成一维数组 就是{1,2,3,4,5}这个数组的地址
print2(arr, 3, 5);
return 0;
}
/*
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
1 2 3 4 5
2 3 4 5 6
3 4 5 6 7
*/
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int i = 0; int* p = arr; for (int i = 0; i < 10; i++) { printf("%d ", p[i]); //printf("%d ", *(p + i)); //printf("%d ", *(arr + i)); //printf("%d ", arr[i]); //arr[i] == *(arr+i) == *(p+i) ==p[i] } return 0;
arr[i] == (arr+i) == (p+i) ==p[i]
改写
void print2(int (*p)[5],int x,int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
//printf("%d ", *(*(p + i) + j));
//printf("%d ",*(p[i]+j))
printf("%d ", p[i][j]);
//printf("%d ", (*(p + i))[j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = {
{
1,2,3,4,5},{
2,3,4,5,6},{
3,4,5,6,7} };
print2(arr, 3, 5);
return 0;
}
指针Pointer
认识内存
线性内存
内存的最小单位b 内存的最小编址单元B,内存中每个字节都对应一个地址,通过地址才能找到每个字节。
#include <stdio.h>
int main(int argc, char* argv[]) {
int arr[3][4] = {
1,2,3 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++) {
printf("%p\n",&arr[i][j]);
}
putchar(10); //输出一个ascii码值是10的字符 即回车换行
}
return 0;
}
/*
00000050F78FF7F8
00000050F78FF7FC
00000050F78FF800
00000050F78FF804
00000050F78FF808
00000050F78FF80C
00000050F78FF810
00000050F78FF814
00000050F78FF818
00000050F78FF81C
00000050F78FF820
00000050F78FF824*/
#include <stdio.h>
int main(int argc, char* argv[]) {
//除了char占一个字节,占一个地址
// 其他类型包含多个字节,也就是拥有多个地址。
//当我们变量取地址的时候 拿到的是哪个字节的地址? 低字节的地址
char a; short b; int c; double d;
printf("%p\n", &a); printf("%#x\n", &a);
printf("%p\n", &b); printf("%#x\n", &b);
printf("%p\n", &c); printf("%#x\n", &c);
printf("%p\n", &d); printf("%#x\n", &d);
printf("sizeof(a) = %d\n",sizeof(&a));
printf("sizeof(b) = %d\n", sizeof(&b));
printf("sizeof(c) = %d\n", sizeof(&c));
printf("sizeof(d) = %d\n", sizeof(&d));
return 0;
}
/*
000000A16E14F5D4
0x6e14f5d4
000000A16E14F5F4
0x6e14f5f4
000000A16E14F614
0x6e14f614
000000A16E14F638
0x6e14f638
sizeof(a) = 8
sizeof(b) = 8
sizeof(c) = 8
sizeof(d) = 8*/
指针常量
指针常量 ->指针变量
对变量取地址,取出的地址,就是一个指针,且常量指针
& * reference derefer 取地址 取内容
常量指针不是一个单纯的地址,而是有类型的
指针的本质,是一个有类型的地址,类型决定了,从这个地址开始的寻址能力。
#include <stdio.h>
int main(int argc, char* argv[]) {
//指针常量 ->指针变量
//对变量取地址,取出的地址,就是一个指针,且常量指针
//& * reference derefer 取地址 取内容
char a = 1; short b = 2; int c = 10; double d = 123.45;
printf("%p ", &a); printf("%#x\n", &a);
printf("%p ", &b); printf("%#x\n", &b);
printf("%p ", &c); printf("%#x\n", &c);
printf("%p ", &d); printf("%#x\n", &d);
printf("%d\n",*(&a));
printf("%d\n",*(&b));
printf("%d\n",*(&c));
printf("%f\n",*(&d));
printf("%d\n", *((char*) 0x8a53fca4));
printf("%d\n", *((short*) 0x8a53fcc4));
printf("%d\n", *((int*) 0x8a53fce4));
printf("%f\n", *((double*) 0x8a53fd08));
return 0;
}
&a | 0x8a53fca4 | (char*) 0x8a53fca4 |
---|---|---|
&b | 0x8a53fcc4 | (short*) 0x8a53fcc4 |
&c | 0x8a53fce4 | (int*) 0x8a53fce4 |
&d | 0x8a53fd08 | (double *)0x8a53fd08 |
小端序
12 |
---|
34 |
56 |
78 |
#include <stdio.h>
int main(int argc, char* argv[]) {
int data = 0x12345678;
printf("%p\n",&data);
printf("%#x\n",*(&data));
//printf("%x\n",*((char*) 0000009CB7D2F574))
printf("%x\n",*((char*)&data)); //对变量取地址 不仅取出了地址 还有类型
printf("%x\n", *((short*)&data));
printf("%x\n", *((int*)&data));
return 0;
}
/*
0000009CB7D2F574
0x12345678
78
5678
12345678
指针的本质,是一个有类型的地址,类型决定了,从这个地址开始的寻址能力。
*/
指针变量
64位系统,这个位数指的是CPU 里面的通用寄存器的数据宽度为64位,也就是说一个地址占二进制位数是64,所以:sizeof(double )==sizeof(int )==sizeof(char *)==64/8==8。
32位系统,同理,他的一个地址占32位二进制空间,sizeof(double )==sizeof(int )==sizeof(char *)==32/8==4。
type * pointerName; *表明了本变量是指针变量,大小 此处的*仅能用于表示声明,类型决定了该指针变量中存储的地址的寻址能力。
#include <stdio.h>
//声明一个指针变量,必须要保存两种东西 一个地址数据 一个类型
//type * pointerName; *表明了本变量是指针变量,大小
int main(int argc, char* argv[]) {
//int a = 12;
//char c = 'c';
//float d = 1.2f;
char a; short b; int c; float f; double d;
printf("%d\n",(sizeof(char *)));
printf("%d\n", (sizeof(short *)));
printf("%d\n", (sizeof(int *)));
printf("%d\n", (sizeof(double *)));
char* pa = &a;
short* pb = &b;
int* pc = &c;
float* pf = &f;
double* pd = &d;
printf("%f\n", *pd);//printf("%f\n", *(&d));
return 0;
}
/*
8
8
8
8
5.600000
*/
int main() {
int data = 0x12345678;
int* pd = &data;
printf("%x\n", *pd);
printf("%x\n", *((int*)pd));
printf("%x\n", *((short*)pd));
printf("%x\n", *((char*)pd));
return 0;
}
/*
12345678
12345678
5678
78
*/
#include <stdio.h>
int main(int argc, char* argv[]) {
int arr[10];
for (int i = 0; i < 10; i++) {
printf("&arr[%d]= %p\n",i,&arr[i]);
arr[i] = i;
}
for (int i = 0; i < 10;i++) {
printf("%d\n", arr[i]);
printf("%d\n", *(arr + i));
}
//代表构造类型/参与元素的访问,此时代表首元素的地址
//arr 首元素地址
printf("&arr[0] = %p\n", &arr[0]);
printf("arr = %p\n", arr);
printf("arr = %p\n", arr);
printf("%d %d\n",arr[1],1[arr]); //[]下标运算符 基址变址运算符
}
/*
&arr[8]= 0000009B60AFF808
&arr[9]= 0000009B60AFF80C
0
0
1
1
2
2
3
3
4
4
5
5
6
6
7
7
8
8
9
9
&arr[0] = 0000009B60AFF7E8
arr = 0000009B60AFF7E8
arr = 0000009B60AFF7E8
1 1
*/
函数
可以提高程序开发的效率 。
提高了代码的重用性 。
使程序变得更简短而清晰。
有利于程序维护。
int main() {
srand(time(NULL));
int i = rand() % 101; //0-100 + 100 100-200
printf("%d\n",i);
return 0;
}
#include <stdio.h>
#include <math.h>
#include <ctype.h>
int main() {
double data = 9.0;
double r = sqrt(data);
printf("%f\n", r);
double power = pow(data,3);
printf("%f\n",power);
printf("%f\n",ceil(3.14));//向上取整
printf("%f\n", floor(3.14));//向下取整
for (char ch = 'a';ch < 'z';ch ++){
putchar(toupper(ch));
//转小写tolower()
}
return 0;
}
自定义函数
#include <stdio.h>
int myMax(int , int);
//函数在调用的时候,输入的参数,通常叫做实参
//函数在定义或者声明的时候的参数,通常叫做形参。声明中的形参可以省略。
int main() {
int a = 3, b = 5;
int iMax = myMax(a,b);
printf("%d\n",iMax);
return 0;
}
int myMax(int i,int j){
return i>j?i:j;
}
传值与传址
#include <stdio.h>
//进程空间
//函数在被调用之前,其内所有的变量尚未开辟空间。
//空间的开辟起始于函数调用,空间消失结束于函数调用完毕
//传值
void func(int a);
int main() {
int a = 10;
func(a);
printf("a = %d\n", a);
return 0;
}
void func(int a) {
a++;
printf("a=%d\n", a);
}
/*
11
10
*/
#include <stdio.h>
void func(int *pa);
int main() {
int a = 10;
func(&a);
printf("a = %d\n", a);
return 0;
}
void func(int *pa) {
(*pa)++;
printf("a=%d\n", *pa);
}
/*
11
11
*/
交换值
#include <stdio.h>
void mySwap(int *pa, int *pb);
int main() {
int a = 10, b = 3;
mySwap(&a, &b);
printf("a = %d b = %d", a, b);
}
void mySwap(int *pa, int *pb) {
int temp;
temp = *pa;
*pa = *pb;
*pb = temp;
}
传递一维数组
#include <stdio.h>
//数组的传递不可能通过拷贝的方式来传递,C语言基于效率的原因,
// 只传递首地址
//数组有三要素,起始地址,步长 范围
//数组名,是一个指针包含了(起始地址和步长)但是数组名里面没有范围
//所以在传递一维数组的时候要传递 数组名和 范围
void disArray(int *p, int n);
int main() {
int arr[] = {
1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// for (int i = 0; i <10 ; ++i) {
// printf("%d\n",arr[i]);
// }
printf("sizeof(arr) = %d\n", sizeof(arr));
//disArray(&arr[0]);
//disArray(arr);
disArray(arr, sizeof(arr) / sizeof(arr[0]));
return 0;
}
void disArray(int *p, int n) {
for (int i = 0; i < n; i++) {
printf("%d\n", *p++);
}
}
/*
sizeof(arr) = 40
1
2
3
4
5
6
7
8
9
10
*/
用逻辑代数可以证明这种交换算法的正确性:易证异或运算满足交换律和结合律,则(a^b)^b=a^(b^b)=a^0=a,(a^b)^a=a^(a^b)=(a^a)^b=0^b=b。
选择排序
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void initRandArr(int *arr, int n) {
srand(time(NULL));
for (int i = 0; i < n; i++) {
*arr++ = rand() % 100;
}
}
void display(int *arr, int n) {
for (int i = 0; i < n; ++i) {
printf("%d\n", *arr++);
}
}
int smallIndex(int startIdx, int *arr, int n) {
int idx = startIdx;
for (int i = startIdx + 1; i < n; ++i) {
if (arr[i] < arr[idx])
idx = i;
}
return idx;
}
void mySwap(int *pa, int *pb) {
*pa ^= *pb;
*pb ^= *pa;
*pa ^= *pb;
}
void selectSort(int *arr, int n) {
for (int i = 0; i < n; ++i) {
int idx;
idx = smallIndex(i, arr, n);
if (idx != i) {
mySwap(&arr[i], &arr[idx]);
}
}
}
int main() {
int arr[10];
initRandArr(arr, 10);
display(arr, 10);
selectSort(arr, 10);
printf("------sort----- : \n");
display(arr, 10);
return 0;
}
如何传递二维数组
#include <stdio.h>
void func(int (*p)[4],int n){
for (int i = 0; i < n; ++i) {
for (int j = 0; j < 4; ++j) {
printf("arr[%d][%d] = %d ",i,j,p[i][j]);
}
printf("\n");
}
}
int main() {
int arr[3][4]={
{
1},
{
2,3},
{
4,5,6}}; //int[4] arr[3]
func(arr,3);
return 0;
}
函数调用-递归
#include <stdio.h>
int getAge(int n){
if (n==1){
return 10;
}else
return getAge(n-1)+2;
}
int main() {
//直接或间接调用自己的情形,就是递归调用,recursive
//递归,是比较接近自然语言的特性的一种调用方式。递归必须要有合理的出口,不然会挂掉。
//递归起始条件getAge(5) 有使递归趋于结束的语句getAge(n-1) 递归终止条件n==1
int age;
printf("请输出要计算的年龄:");
scanf("%d", &age);
age = getAge(age);
printf("%d\n", age);
return 0;
}
#include <stdio.h>
int getAge(int n){
if (n==10){
return 1;
}else
return (getAge(n+1)+1)*2;
}
int main() {
int peach ;
peach = getAge(1);
printf("%d\n", peach);
return 0;
}
变量作用域/生命周期/修饰符
作用域Scope
函数的生命周期起于调用 结束于调用
局部变量的生命周期,起于调用,结束于调用结束
main 进程的开始和结束
修饰符
auto 只能用于修饰局部变量,该变量存储于stack
存储在stack上的参数有什么特点,随用随开 用完消失
默认的局部变量,就是auto类型的,通常将其省略 C++ auto
C语言 忘记
register
extern 跨文件使用 同文件使用
变量的声明与 定义 现在要区分了
extern 是可以省略的 但是不建议省略
static修饰局部变量
#include <stdio.h>
//static修饰局部变量,默认初始化为零
//auto 修饰的局部变量存储在栈上,随用即开 用完即清
//static 修改的局部变量, data
void func() {
int a=1;
printf("a = %d ", a++);
static int b=1 ;
printf("b = %d\n",b++);
printf("++++++++++++\n");
}
int main() {
for (int i = 0; i <10 ; ++i) {
func();
}
return 0;
}
字符串常量
stack heap data 全局变量 static 局部变量 常量 text 字符串常量是由双引号,引起的一串字符。系统在字符串最后添加了一个字符'\0' C语言 如何处理字符串,将其处理一个向data段字符的一个首地址 对比数组,三要素,起始地址,步长,范围 char* 可不可以代表整个字符串 起始地址 步长 '\0' 可以代表整个字符串
#include <stdio.h>
int main(){
printf("sizeof(\"china\")=%d\n",sizeof("china"));
int a = 10;
int b = 20;
printf("%s\n","china");
char *p = "china";
printf("p = %p p+1 = %p p[0] = %c 2[p] = %c\n",p,p+1,p[0],2[p]);
printf(" = %p + 1 = %p = %c = %c\n","china","china"+1,"china"[0],2["china"]);
printf("a = %d,b = %d ,p = %s\n",a,b,p);
return 0;
}
/*
sizeof("china")=6
china
p = 00007ff75c98a014 p+1 = 00007ff75c98a015 p[0] = c 2[p] = i
= 00007ff75c98a014 + 1 = 00007ff75c98a015 = c = i
a = 10,b = 20 ,p = china
*/
字符串与字符数组
#include <stdio.h>
//正是因为字符数组和字符串,他们具有相同的性质
//所以为了要改变字符串的内容,通常将字符串,拷贝到字符数组中去。
//arr[6]是栈上的空间 "china" 是data 一块常量区域
int main(){
char arr[6] = "china";
printf("%d\n",sizeof(char));
printf("sizeof(arr) = %d arr = %p arr + 1 = %p \t\n",sizeof(arr),arr,arr+1);
printf("sizeof(\"china\") = %d \"china\" = %p \"china\" + 1 = %p \t\n",sizeof("china"),"china","china"+1);
printf("%s\n",arr);
printf("\"china\"=%s\n","china");
return 0;
}
/*
1
sizeof(arr) = 6 arr = 0000004d93dff6da arr + 1 = 0000004d93dff6db
sizeof("china") = 6 "china" = 00007ff6f941a034 "china" + 1 = 00007ff6f941a035
china
"china"=china
*/
字符数组和字符串之间的联系
等价 sizeof(字符数组)的大小 >= sizeof(字符串)的大小
#include <stdio.h>
//字符数组和字符串之间的相同性质。并不代表字符串可以与任意的字符串数组之间划等号
//等价 sizeof(字符数组)的大小 >= sizeof(字符串)的大小
int main() {
char arr[2] = "china";
printf("arr = %s\n",arr);
printf("%s\n","china");
printf("%s\n","ch\0ina");
char arr1[6] = "china\0";
printf("%s\n",arr1);
char ca[6] = "china"; //char[5] 不等价 字符数组长度小于 字符串长度 发生越界 字符串后面有系统自动加上的'\0'
printf("ca = %s \n",ca);
return 0;
}
/*
arr = ch����
china
ch
china
ca = china
*/
更好的做法:利用数组可以省略大小的特点,一句数组的大小自适应,这样避免浪费空间。
原生字符串处理
#include <stdio.h>
#include <string.h>
int myStrlen(char * arr){
int len ;
for (len = 0; *arr++; len++);
return len;
}
int main() {
char *p = "china";
char arr[] = "china";
int count = 0;
// while(*p!=0){
// p++;
// count ++;
//
// }
// printf("china长度为 %d",count);
int len = myStrlen(arr);
int len1 = strlen(p);
printf("china长度为 %d\n", len);
printf("china长度为 %d", len1);
return 0;
}
#include <stdio.h>
#include <string.h>
int main() {
char firstName[30] = "chenxu";
char lastName[30] = "yang";
char *p, *q;
p = firstName;
q = lastName;
while(*p) p++;
// while(1){
// *p = *q;
// if(*q == 0)
// break;
// p++;
// q++;
// }
// while(*p = *q){
// p++;
// q++;
// }
while(*p++ = *q++);
printf("%s\n",firstName);
return 0;
}
/*
chenxuyang
*/
多文件变成xx.h 与xx.c
指针数组
一个数组中的各个元素都是字符指针,我们称该数组为字符指针数组,或指针数组。
#include <stdio.h>
//指针数组的本质是数组 数组指针的本质是指针
int main(){
// char *pa="china",*pb="meri",*pc="canada",*pd="japan";
// printf("pa = %p\n",pa);
// printf("pb = %p\n",pb);
// printf("pc = %p\n",pc);
// printf("pd = %p\n",pd);
// char * cqArr[4] = {pa,pb,pc,pd};;
// for (int i = 0; i < 4; ++i) {
// printf("cqArr = %p\n",cqArr[i]);
// }
char * pArr[] = {
"china","meir","japan"};//字符指针数组
for (int i = 0; i < 4; ++i) {
printf("%p %s\n",pArr[i],pArr[i]);
}
return 0;
}
int main1() {
int arr[] = {
1,2,3,4,5};//整型数组
char cArr[] = {
'a','b','c','d','e'};//字符数组
int a, b,c,d;
int * intArr[] = {
&a,&b,&c,&d}; //整型指针数组
char aa,bb,cc,dd;
char * cpArr[] = {
&aa,&bb,&cc,&dd};//{char*,char*,char*,char*}字符指针数组
char *pa="china",*pb="meri",*pc="canada",*pd="japan";
char * cqArr[] = {
pa,pb,pc,pd};;
return 0;
}
/*
0x100403000 china
0x100403006 meir
0x10040300b japan
*/
#include <stdio.h>
#include <string.h>
int main() {
char *pArr[] = {
"china", "ameria", "canada", "japan"};
for (int i = 0; i < 4; i++) {
printf("%p %s\n", pArr[i], pArr[i]);
}
printf("%d\n", sizeof(pArr));
int n = sizeof(pArr) / sizeof(*pArr);
char *p;
for (int i = 0; i < n - 1; i++) {
for (int j = i + 1; j < n; j++) {
if (strcmp(pArr[i], pArr[j]) > 0) {
p = pArr[i];
pArr[i] = pArr[j];
pArr[j] = p;
}
}
}
for (int i = 0; i < 4; i++) {
printf("%p %s\n", pArr[i], pArr[i]);
}
return 0;
}
/*
00007ff79209a000 china
00007ff79209a006 ameria
00007ff79209a00d canada
00007ff79209a014 japan
32
00007ff79209a006 ameria
00007ff79209a00d canada
00007ff79209a000 china
00007ff79209a014 japan
*/
#include <stdio.h>
//在启动进程,通过命令行,传递给进程的参数,即传递main的参数
//arg argment 参数 c count 个数的意思 argc 参数的个数的意思
//argv arg 指针数组 v vector 指针数组向量
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
}
return 0;
}
栈内存与堆内存的基本概念
源程序 源代码
程序 可执行性文件
进程 时间概念 可执行文件被拉起,到结束的这一段过程,成为进程
进程空间 , 可执行性文件被拉起后 在内存中的分布情况
栈内存的内容
栈中存放任意类型的变量,但必须是auto类型修饰的,即自动类型的局部变量。
栈存储的特点
随用随开,用完即消 内存的分配和销毁系统自动完成,不需要人工干预。
栈大小
栈的大小并不大,它的意义并不在于存储大数据,而在于数据交换。而不适于大空间的申请
堆空间主要用于大内存的使用。
栈的发展方向 高地址向低地址
堆内存的特点
低地址向高地址
堆内存可以存放任意类型的数据,但需要自己申请与释放
堆大小
堆大小,想像中的无穷大,对于栈来说,大空间申请。但实际使用中,受限于内存的大小和内存是否连续性。
//heap 内存,可以用于申请大空间 需要手动申请与释放
//malloc 是以字节为单位进行申请
//free 释放
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
char * p = (char *) malloc(1024 * 1024 * 1024);
if (p == NULL)
printf("malloc error");
strcpy(p, "abcd");
printf("over\n");
free(p);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
//基本数据类型在栈和堆上
int a; a = 100;
printf("a = %d\n", a);
int *p = (int *) malloc(4);
*p = 100;
printf("*p = %d\n",*p);
//数组类型在栈和堆上
int arr[10] ;
int *pa = (int *) malloc(40);
memset(pa,1,40);
for (int i = 0; i <10 ; ++i) {
printf("%d\n",pa[i]);
}
free(p);
return 0;
}
结构体
凡是 基本类型,既可以在定义的时候初始化,也可以先定义再赋值
凡是构造类型,要么在定义的时候初始化,不可以先定义再以初始化的方式赋值
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct stu {
char name[100];
int num;
char sex;
float score;
};
//初始化是一种特殊的语法 跟赋值不等价
//凡是 基本类型,既可以在定义的时候初始化,也可以先定义再赋值
//凡是构造类型,在定义的时候初始化,不可以先定义再以初始化的方式赋值
int main() {
//int a; a = 10;
//int arr[10] = {1,2,4,5,6};
//arr = {1,2,3,4,5};
struct stu s ;//= {"yangchengxu", 22, 'f', 99};
strcpy(s.name,"zhangsan");
s.num=1001;
s.score=99;
s.sex='f';
printf("name: %s\n num: %d\n sex: %c\n score: %f\n",s.name,s.num,s.sex,s.score);
return 0;
}
输出
name: zhangsan
num: 1001
sex: f
score: 99.000000
静态链表
#include <stdio.h>
//静态链表的定义
typedef struct node {
int data;
struct node *next;
} Node;
int main() {
//节点变量
Node a, b, c, d, e;
//定义头指针
Node *head = &a;
a.data = 1;
b.data = 2;
c.data = 3;
d.data = 4;
e.data = 5;
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = NULL;
//打印链表 元素内容一般 重新定义一个指针,如果使用head头指针,对其改动head的指向最后就变了
//在这里只是打印 所以不定义新的指针变量
Node * pa = head;
// while (pa){
// printf("data = %d\n",pa->data);
// pa = pa->next;
// }
while (head) {
printf("data = %d\n", head->data);
head = head->next;
}
return 0;
}
/*
data = 1
data = 2
data = 3
data = 4
data = 5
*/
动态链表
链表的创建头插法与尾插法
尾插法
尾插法,在尾节点插入,每插入一个节点,即成尾节点
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
Node *t = head, *cur;
int nodeData;
scanf("%d", &nodeData);
while (nodeData) {
cur = (Node *) malloc(sizeof(Node));
if (NULL == cur) {
exit(-1);
}
cur->data = nodeData;
t->next = cur;
t = cur;
scanf("%d", &nodeData);
}
t->next = NULL;
return head;
}
void traverseList(Node * head){
head = head->next;
while(head){
printf("data = %d\n",head->data);
head = head->next;
}
}
int main() {
Node *head = createList();
traverseList(head);
return 0;
}
/*
3
2
1
0
data = 3
data = 2
data = 1
*/
头插法
所谓的头插法,就是在头节点后面插入元素,每插入一个元素即为首节点
让新来的节点先有所指向,避免打断原有的指向
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
#if 0
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
Node *t = head, *cur;
int nodeData;
scanf("%d", &nodeData);
while (nodeData) {
cur = (Node *) malloc(sizeof(Node));
if (NULL == cur) {
exit(-1);
}
cur->data = nodeData;
t->next = cur;
t = cur;
scanf("%d", &nodeData);
}
t->next = NULL;
return head;
}
#endif
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
Node *cur;
int nodeData;
scanf("%d", &nodeData);
while (nodeData) {
cur = (Node *) malloc(sizeof(Node));
if (cur == NULL)
exit(-1);
cur->data = nodeData;
cur->next = head->next;
head->next = cur;
scanf("%d", &nodeData);
}
return head;
}
void traverseList(Node *head) {
head = head->next;
while (head) {
printf("data = %d\n", head->data);
head = head->next;
}
}
int main() {
Node *head = createList();
traverseList(head);
return 0;
}
/*
3 2 1 0
data = 1
data = 2
data = 3
*/
链表的插入
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
//真正意义上的创建链表,就是创建一个空链表
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
return head;
}
void insertList(Node * head,int nodedata){
Node * cur = (Node *) malloc(sizeof(Node));
if(NULL == head)
exit(-1);
cur->data = nodedata;
cur->next = head->next;
head->next = cur;
}
void traverseList(Node *head) {
head = head->next;
while (head) {
printf("data = %d\n", head->data);
head = head->next;
}
}
int main() {
Node *head = createList();
for (int i = 0; i <5 ; ++i) {
insertList(head,i);
}
traverseList(head);
return 0;
}
/*
data = 4
data = 3
data = 2
data = 1
data = 0
*/
求长
int lenList(Node * head){
int len =0;
head=head->next;
while(head){
len ++;
head=head->next;
}
return len;
}
删除
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
//真正意义上的创建链表,就是创建一个空链表
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
return head;
}
void insertList(Node *head, int nodedata) {
Node *cur = (Node *) malloc(sizeof(Node));
if (NULL == head)
exit(-1);
cur->data = nodedata;
cur->next = head->next;
head->next = cur;
}
void traverseList(Node *head) {
head = head->next;
while (head) {
printf("data = %d\n", head->data);
head = head->next;
}
}
//求长 本质就是遍历
int lenList(Node *head) {
int len = 0;
head = head->next;
while (head) {
len++;
head = head->next;
}
return len;
}
//查
Node *searchList(Node *head, int findData) {
head = head->next;
while (head) {
if (head->data == findData)
break;
head = head->next;
}
return head;
}
//删
Node *deleteNodeOfList(Node *head, Node *pfind) {
while (head->next != pfind)
head = head->next;
head->next = pfind->next;
free(pfind);
}
int main() {
Node *head = createList();
for (int i = 0; i < 5; ++i) {
insertList(head, i);
}
traverseList(head);
int len = lenList(head);
printf("len of list %d\n", len);
Node *pfind = searchList(head, 0);
if (pfind == NULL) {
printf("find none\n");
} else {
//改
// pfind->data = 1000;
printf("find in List\n");
deleteNodeOfList(head, pfind);
}
traverseList(head);
return 0;
}
/*
data = 4
data = 3
data = 2
data = 1
data = 0
len of list 5
find in List
data = 4
data = 3
data = 2
data = 1
*/
删除优化
//删
Node *deleteNodeOfList(Node *head, Node *pfind) {
if(pfind->next == NULL) {
while (head->next != pfind)
head = head->next;
head->next = pfind->next;
free(pfind);
}else{
printf("不是尾节点\n");
Node *t = pfind->next;
pfind->data = pfind->next->data;
pfind->next = pfind->next->next;
freee(t);
}
}
冒泡排序
#include <stdio.h>
#define N 5
int main() {
int arr[N] = {
5, 4, 3, 2, 1};
for (int i = 0; i < N - 1; ++i) {
for (int j = 0; j < N - 1 - i; ++j) {
if (arr[j] > arr[j + 1]) {
arr[j] ^= arr[j + 1];
arr[j + 1] ^= arr[j] ;
arr[j] ^= arr[j + 1] ;
}
}
}
for (int i = 0; i <N ; ++i) {
printf("arr[%d]=%d\n",i,arr[i]);
}
return 0;
}
/*
arr[0]=1
arr[1]=2
arr[2]=3
arr[3]=4
arr[4]=5
*/
链表排序
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
//真正意义上的创建链表,就是创建一个空链表
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
return head;
}
void insertList(Node *head, int nodedata) {
Node *cur = (Node *) malloc(sizeof(Node));
if (NULL == head)
exit(-1);
cur->data = nodedata;
cur->next = head->next;
head->next = cur;
}
void traverseList(Node *head) {
head = head->next;
while (head) {
printf("data = %d\n", head->data);
head = head->next;
}
}
//求长 本质就是遍历
int lenList(Node *head) {
int len = 0;
head = head->next;
while (head) {
len++;
head = head->next;
}
return len;
}
//查
Node *searchList(Node *head, int findData) {
head = head->next;
while (head) {
if (head->data == findData)
break;
head = head->next;
}
return head;
}
//删
Node *deleteNodeOfList(Node *head, Node *pfind) {
if (pfind->next == NULL) {
while (head->next != pfind)
head = head->next;
head->next = pfind->next;
free(pfind);
} else {
printf("不是尾节点\n");
Node *t = pfind->next;
pfind->data = pfind->next->data;
pfind->next = pfind->next->next;
free(t);
}
}
//排序
void popSortList(Node *head) {
int len = lenList(head);
head = head->next;
Node *p, *q;
for (int i = 0; i < len; ++i) {
p = head;
q = head->next;
for (int j = 0; j < len - 1 - i; ++j) {
if (p->data > q->data) {
p->data ^= q->data;
q->data ^= p->data;
p->data ^= q->data;
}
p = p->next;
q = q->next;
}
}
}
int main() {
Node *head = createList();
for (int i = 5; i > 0; --i) {
insertList(head, i);
}
traverseList(head);
int len = lenList(head);
printf("len of list %d\n", len);
Node *pfind = searchList(head, 3);
if (pfind == NULL) {
printf("find none\n");
} else {
//改
// pfind->data = 1000;
printf("find in List\n");
deleteNodeOfList(head, pfind);
}
traverseList(head);
popSortList(head);
printf("after sored: \n");
traverseList(head);
return 0;
}
/*
data = 1
data = 2
data = 3
data = 4
data = 5
len of list 5
find in List
不是尾节点
data = 1
data = 2
data = 4
data = 5
after sored:
data = 1
data = 2
data = 4
data = 5
*/
快速排序
//排序2
void popSortList(Node * head){
int len = lenList(head);
Node *prep,*p,*q,*t;
for (int i = 0; i <len - 1 ; ++i) {
prep = head;
p = head->next;
q = p->next;
for (int j = 0; j < len -1 -i; ++j) {
if(p->data>q->data){
prep->next=q;
p->next=q->next;
q->next=p;
t = p;
p = q;
q = t;
}
prep = prep->next;
p= p->next;
q = p->next;
}
}
}
链表的销毁
void destoryList(Node * head){
Node * t;
while(head){
t = head;
head = head->next;
free(t);
}
}
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} Node;
//真正意义上的创建链表,就是创建一个空链表
Node *createList() {
Node *head = (Node *) malloc(sizeof(Node));
if (NULL == head) {
exit(-1);
}
head->next = NULL;
return head;
}
void insertList(Node *head, int nodedata) {
Node *cur = (Node *) malloc(sizeof(Node));
if (NULL == head)
exit(-1);
cur->data = nodedata;
cur->next = head->next;
head->next = cur;
}
void traverseList(Node *head) {
head = head->next;
while (head) {
printf("data = %d\n", head->data);
head = head->next;
}
}
//求长 本质就是遍历
int lenList(Node *head) {
int len = 0;
head = head->next;
while (head) {
len++;
head = head->next;
}
return len;
}
//查
Node *searchList(Node *head, int findData) {
head = head->next;
while (head) {
if (head->data == findData)
break;
head = head->next;
}
return head;
}
//删
Node *deleteNodeOfList(Node *head, Node *pfind) {
if (pfind->next == NULL) {
while (head->next != pfind)
head = head->next;
head->next = pfind->next;
free(pfind);
} else {
printf("不是尾节点\n");
Node *t = pfind->next;
pfind->data = pfind->next->data;
pfind->next = pfind->next->next;
free(t);
}
}
//排序
//void popSortList(Node *head) {
// int len = lenList(head);
// head = head->next;
// Node *p, *q;
// for (int i = 0; i < len; ++i) {
// p = head;
// q = head->next;
// for (int j = 0; j < len - 1 - i; ++j) {
// if (p->data > q->data) {
// p->data ^= q->data;
// q->data ^= p->data;
// p->data ^= q->data;
// }
// p = p->next;
// q = q->next;
// }
// }
//}
//排序2
void popSortList(Node * head){
int len = lenList(head);
Node *prep,*p,*q,*t;
for (int i = 0; i <len - 1 ; ++i) {
prep = head;
p = head->next;
q = p->next;
for (int j = 0; j < len -1 -i; ++j) {
if(p->data>q->data){
prep->next=q;
p->next=q->next;
q->next=p;
t = p;
p = q;
q = t;
}
prep = prep->next;
p= p->next;
q = p->next;
}
}
}
void destoryList(Node * head){
Node * t;
while(head){
t = head;
head = head->next;
free(t);
}
}
int main() {
Node *head = createList();
for (int i = 5; i > 0; --i) {
insertList(head, i);
}
traverseList(head);
int len = lenList(head);
printf("len of list %d\n", len);
Node *pfind = searchList(head, 3);
if (pfind == NULL) {
printf("find none\n");
} else {
//改
// pfind->data = 1000;
printf("find in List\n");
deleteNodeOfList(head, pfind);
}
traverseList(head);
popSortList(head);
printf("after sored: \n");
traverseList(head);
destoryList(head);
return 0;
}