首页 > 其他分享 >课堂笔记2

课堂笔记2

时间:2024-03-09 11:34:28浏览次数:32  
标签:arr int 笔记 地址 数组 printf 课堂 sizeof

define _CRT_SECURE_NO_WARNINGS

include <stdio.h>

//
////冒泡排序 该方法只能进行整数的排序
//void BubbleSort(int arr[], int sz)
//{
// int i = 0;
// int j = 0;
// for (i = 0; i < sz - 1; i++)
// {
// for (j = 0; j < sz - 1 - i; j++)
// {
// if (arr[j] > arr[j + 1])
// {
// int tmp = arr[j];
// arr[j] = arr[j + 1];
// arr[j + 1] = tmp;
// }
// }
// }
//}
//
//打印
void print(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
}
//
//int main()
//{
//
// int arr[] = { 9, 8, 7, 6, 5, 4, 3, 2, 1 };
// int sz = sizeof(arr) / sizeof(arr[0]);
// BubbleSort(arr, sz);
// print(arr, sz);
// return 0;
//}

//使用qsrot函数进行排序

include <stdlib.h>

include <string.h>

//qsort函数
//void qsort(void* base, //base中存放的是待排序数据中第一个对象的地址
// size_t num, //排序数据元素的个数
// size_t size,//排序数据中一个元素的大小,单位是字节
// int (cmp)(const void e1, const void* e2)//是用来比较待排序数据中的2个元素的函数
// );
int cmp_int(const void* e1, const void* e2)
{
//降序排序
return (int)e2 - (int)e1; //把e1和e2void类型的转换为int类型这样就可以用于比较整形类型的数据
}

//用qsort函数对整形数组排序
void test1()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sz = sizeof(arr) / sizeof(arr[0]);
qsort(arr, sz, sizeof(arr[0]), cmp_int);

}

//用qsort函数对结构体进行排序

//结构体的定义
struct stu
{
char name[20];
int age;
};

//以名字的方式排序
int sort_by_name(const void* e1, const void* e2)
{
return strcmp(((struct stu)e1)->name, ((struct stu)e2)->name);
}

//以年龄的方式进行排序
int sort_by_age(const void* e1, const void* e2)
{
return ((struct stu)e1)->age - ((struct stu)e2)->age;
}

void test2()
{
struct stu s[3] = { {"zhangsan", 20}, {"lisi", 21},{"wangwu", 22}};
int sz = sizeof(s) / sizeof(s[0]);
//qsort(s, sz, sizeof(s[0]), sort_by_name);
}

void test3()
{
struct stu s[3] = { {"zhangsan", 20}, {"lisi", 21},{"wangwu", 22} };
int sz = sizeof(s) / sizeof(s[0]);
//qsort(s, sz, sizeof(s[0]), sort_by_name);
qsort(s, sz, sizeof(s[0]), sort_by_age);

}

//通过冒泡排序的思想来模拟实现qsort函数

void Swap1(char* buf1, charbuf2, int width) //buf1和buf2是char类型的指针
{
int i = 0;
for (i = 0; i < width; i++)
{
int tmp = buf1; //该交换函数的思想是传入两个char类型的指针,指针从首地址开始
*buf1 = *buf2; //每次交换一个字节的内容然后移动一个字节直到交换完整个字节的内容
*buf2 = tmp;
buf1++;
buf2++;
}
}

void BubbleSort(int base, int num, int width, int (cmp)(const void e1, const void* e2))
{
int i = 0;
int j = 0;
for (i = 0; i <= num; i++)
{
for (j = 0; j <= num - 1 - i; j++)
{
if (cmp((char)base + j * width, (char)base + (j+1) * width) > 0)
{
Swap1((char)base + j * width, (char)base + (j+1) * width, width);
}

    }
}

}

//对整形数组的排序
void test4()
{
int arr[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int sz = sizeof(arr) / sizeof(arr[0]);
BubbleSort(arr, sz, sizeof(arr[0]), cmp_int);
print(arr, sz);
}

int main()
{
//test1();
/test2();/
/test3();/
test4();
return 0;
}

该代码是使用冒泡排序的思想来实现qsort函数
//void qsort(void* base, //base中存放的是待排序数据中第一个对象的地址
// size_t num, //排序数据元素的个数
// size_t size,//排序数据中一个元素的大小,单位是字节
// int (cmp)(const void e1, const void* e2)//是用来比较待排序数据中的2个元素的函数指针,
形参类型是void*是因为需要根据要求来写出比较函数,这样就可以实现对任何类型数据的比较。
// );
现在我对这段代码的理解仅停留在对代码的实现,冒泡排序的思想已经理解的差不多了,对函数指针的理解还不够透

笔试题详解

数组名的意义:

  1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
  2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
  3. 除此之外所有的数组名都表示首元素的地址。

int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));
sizeof(数组名)的时候计算的是整个数组的大小所以这里的输出是16
printf("%d\n",sizeof(a+0));
这里的a(即数组名)没有单独放在sizeof里a后面还加了一个0所以a表示的是首元素的地址首元素地址+0还是首元素的地址,sizeof()计算的又是所占空间的大小,
所以这里的输出结果是4/8
printf("%d\n",sizeof(a));
此处的a表示的是数组首元素的地址对首元素地址的解引用输出结果是4
printf("%d\n",sizeof(a+1));
这里的a没有单独放在sizeof里面使用a表示的是数组首元素的地址a+1表示的就是数组第二个元素的地址,所以这里输出4
printf("%d\n",sizeof(a[1]));
a[1]表示的是数组的第二个元素,输出结果为4
printf("%d\n",sizeof(&a));
&a取的是数组的地址,是地址所以输出为4/8
printf("%d\n",sizeof(
&a));
&a取的是数组的地址然后对数组解引用所以输出结果为16
printf("%d\n",sizeof(&a+1));
&a表示取数组的地址,数组的地址+1跳过数组a,&a+1指向下一个数组,但其仍是地址,所以输出4/8
printf("%d\n",sizeof(&a[0]));
&a[0]取出数组首元素的地址,所以输出4/8
printf("%d\n",sizeof(&a[0]+1));
&a[0]+1取出第二个元素的地址,所以输出4/8

char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
sizeof(数组名),输出6
printf("%d\n", sizeof(arr+0));
arr+0表示数组首元素的地址,是地址就输出4/8
printf("%d\n", sizeof(*arr));
*arr对数组首元素地址解引用,sizeof计算所占空间大小,arr的元素是char类型,所以输出1
printf("%d\n", sizeof(arr[1]));
a[1]表示的是数组的第二个元素,输出结果为1
printf("%d\n", sizeof(&arr));
&arr取的是数组的地址,是地址所以输出为4/8
printf("%d\n", sizeof(&arr+1));
&a表示取数组的地址,数组的地址+1跳过数组a,&a+1指向下一个数组,但其仍是地址,所以输出4/8
printf("%d\n", sizeof(&arr[0]+1));
&a[0]+1取出第二个元素的地址,是地址所以输出4/8

printf("%d\n", strlen(arr));
char arr[] = {'a','b','c','d','e','f'};该数组没有定义\0所以向strlen函数传入数组名时会一直往后找直至找到\0才停止,所以输出结果为随机值
printf("%d\n", strlen(arr+0));
arr+0表示首元素的地址,输出结果也为随机值,原因与上相同
printf("%d\n", strlen(*arr));
*arr表示对数组首元素的解引用,strlen的形参只能时指针类型,把a传入strlen时会发生错误
printf("%d\n", strlen(arr[1]));
发生错误,理由同上
printf("%d\n", strlen(&arr));
&arr表示取出数组的地址,输出结果是随机值,因为在数组中没有定义\0
printf("%d\n", strlen(&arr+1));
&arr+1表示跳过数组arr,其仍未地址输出结果是随机值-6
printf("%d\n", strlen(&arr[0]+1));
&arr[0]+1表示数组第二个元素的地址,输出结果为随机值-1

char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
sizeof(数组名)的时候计算的是整个数组的大小,数组的每个元素类型又是char类型所以这里的输出是7
printf("%d\n", sizeof(arr+0));
arr+0表示数组首元素的地址,是地址就输出4/8
printf("%d\n", sizeof(*arr));
*arr对数组首元素的解引用,数组首元素是char类型,输出结果是1
printf("%d\n", sizeof(arr[1]));
a[1]表示的是数组的第二个元素,数组首元素是char类型,输出结果为1
printf("%d\n", sizeof(&arr));
&arr取的是数组的地址,是地址所以输出为4/8
printf("%d\n", sizeof(&arr+1));
&a表示取数组的地址,数组的地址+1跳过数组a,&a+1指向下一个数组,但其仍是地址,所以输出4/8
printf("%d\n", sizeof(&arr[0]+1));
&a[0]+1取出第二个元素的地址,是地址所以输出4/8

char arr[] = "abcdef";
printf("%d\n", strlen(arr));
strlen函数计算的是字符串的长度,arr表示的是整个数组的地址,所以输出结果为6
printf("%d\n", strlen(arr+0));
arr+0表示数组首元素的地址,输出结果是6
printf("%d\n", strlen(*arr));
*arr表示对数组首元素的解引用,strlen的形参只能时指针类型,把a传入strlen时会发生错误
printf("%d\n", strlen(arr[1]));
发生错误,理由同上
printf("%d\n", strlen(&arr));
&arr表示数组的地址,输出结果为6
printf("%d\n", strlen(&arr+1));
&arr表示取数组的地址,数组的地址+1跳过数组arr,输出结果为随机值
printf("%d\n", strlen(&arr[0]+1));
&arr[0]+1表示的是第二个元素的地址,输出结果为5

char* p = "abcdef";
printf("%d\n", sizeof(p));
这里的p指向的是字符串字符a的地址,所以输出结果为4/8
printf("%d\n", sizeof(p+1));
p+1指向的是字符b的地址,所以输出结果为4/8
printf("%d\n", sizeof(*p));
*p表示对字符a进行解引用,,strlen的形参只能时指针类型,把a传入strlen时会发生错误
printf("%d\n", sizeof(p[0]));
发生错误,理由同上
printf("%d\n", sizeof(&p));
p表示的是字符a的地址,&p表示取出p的地址是一个二级指针,是地址输出结果为4/8
printf("%d\n", sizeof(&p+1));
&p+1是地址,所以输出结果为4/8
printf("%d\n", sizeof(&p[0]+1));
&p[0]表示取出字符a的地址,+1就是取出字符b的地址,是地址就输出4/8

char* p = "abcdef";
printf("%d\n", strlen(p));
这里的p指向的是字符串字符a的地址,输出结果是6
printf("%d\n", strlen(p+1));
p+1指向的是字符串字符b的地址,输出结果是5
printf("%d\n", strlen(p));
p表示对字符a进行解引用,,strlen的形参只能时指针类型,把a传入strlen时会发生错误
printf("%d\n", strlen(p[0]));
发生错误,理由同上
printf("%d\n", strlen(&p));
/
&p指向p,p指向字符a的地址,所以输出结果为6
/,输出结果应为随机值
printf("%d\n", strlen(&p+1));
/&p指向p,p指向字符a的地址,+1指向的是字符b的地址,所以输出结果为5/,输出结果应为随机值
printf("%d\n", strlen(&p[0]+1));
&p[0]表示取出字符a的地址,+1就是取出字符b的地址,输出结果为5

//二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));
a表示的是整个二维数组的地址,所以输出结果为344=48
printf("%d\n",sizeof(a[0][0]));
arr[0][0]表示的是下标为0 0的元素,所以输出结果为4
printf("%d\n",sizeof(a[0]));
a[0]表示的是第一行的数组名,所以输出结果为16
printf("%d\n",sizeof(a[0]+1));
a[0]没有单独放在sizeof里所以在这里a[0]代表的是第一行第一个元素的地址,+1表示第一行第二个元素的地址,所以输出结果为4/8
printf("%d\n",sizeof((a[0]+1)));
a[0]+1表示第一行第二个元素的地址,对它进行解引用,输出结果为4
printf("%d\n",sizeof(a+1));//第一次做不出来
a虽然是二维数组的地址,但是并没有单独放在sizeof内部,也没有取地址,a表示首元素的地址,二维数组首元素的地址是第一行,a就是的地址,a+1表示的就是第二行的地址
是地址输出结果就是4/8
printf("%d\n",sizeof(
(a+1)));
a+1表示的就是第二行的地址,对第二行进行解引用输出结果是16,(a+1)-->a[1]
printf("%d\n",sizeof(&a[0]+1));
a[0]是第一行的数组名,&a[0]取出的是第一行的地址,+1取出的是第二行的地址
printf("%d\n",sizeof(
(&a[0]+1)));
(&a[0]+1))对第二行进行解引用,输出结果为16
printf("%d\n",sizeof(
a));
a没有单独放在sizeof里a就表示二维数组首元素的地址即第一行的地址,对其解引用输出结果为16
printf("%d\n",sizeof(a[3]));
a[3]-->*(a+3),输出结果为16

课堂杂记:
strlen函数是求字符串长度的,关注的是字符串中的\0,计算的是\0之前的字符个数;
strlen是库函数,只针对字符串;
sizeof只关注占用内存空间的大小,不在乎内存中存放的是什么;
sizeof是操作符;

标签:arr,int,笔记,地址,数组,printf,课堂,sizeof
From: https://www.cnblogs.com/lwd107/p/18062009

相关文章

  • 王道计算机网络截图笔记
    目录第一章概述1.计算机网络概览1.1网络与计算机网络1.2计算机网络的功能1.3计算机网络的组成1.3.1组成部分1.3.2工作方式1.3.3功能组成1.4计算机网络的分类1.5小结2.计算机网络的标准化工作2.1标准的分类2.2RFC2.3标准化工作的相关组织2.4小结3.计算机网络性能指标3......
  • 2024.3.9 笔记
    2024.3.9笔记P1948题目大意为在无向图上求出从\(1\)到\(N\)的路径,使路径上第\(k+1\)大的边权尽量少。第一种是DP用\(f[i][j]\)表示从\(1\)到点\(i\),用了\(j\)条免费线的最小花费。对于一条\(u->v\)的边\(e\)有转移:不用免费线\(f_{v,k}=min(f_{v,k},max......
  • MYSQl学习笔记19: 外键约束
    外键约束用来让两张表的数据之间建立连接,从而保证数据的一致性和完整性具有外键的表(emp)称为子表外键关联的表(dept)称为父表外键约束创建表时添加createtable表名(字段名数据类型,[constrain][外键名称]foreignkey(外键字段名)references主表(主表......
  • MYSQL学习笔记20: 外键约束(删除/更新行为)
    外键约束删除/更新行为setdefault在mysql的默认引擎innodb中不支持CASCADEaltertable表名addconstraint外键名称foreignkey(外键字段)references主表名(主表字段名)onupdatecascadeondeletecascade;建立外键约束#如果父表和子表建立外键的字段有不同的......
  • MYSQL学习笔记17: 流程控制函数(IF, CASE)
    流程控制函数(IF,CASE)ifselectif(true,'ok','error');selectif(false,'ok','error');/*相当于iftrue:ok;else:error;*/ifnullselectifnull('ok','default');selectifnull(......
  • MYSQL学习笔记18: 约束
    约束约束是作用于表中字段上的规则,用于限制存储在表中的数据.保证表中的正确性,有效性和完整性约束作用于表中字段上,可以在建表和修改表时为表添加约束按照需求创建表,并创建约束createtableusers(idintprimarykeyauto_incrementcomment'主键',n......
  • MYSQL学习笔记15: 数值函数
    数值函数ceil向上取整(并不是四舍五入)selectceil(1.5);selectceil(2.1);floor向下取整selectfloor(3.9);selectfloor(2.0);mod取模(余数)selectmod(7,4);rand0-1的随机小数,不包括0和1selectrand();round四舍五入#参数2:保留的......
  • MYSQL学习笔记16: 日期函数
    日期函数返回当前日期selectcurdate();返回当前时间(24小时制)selectcurtime();返回当前日期+时间selectnow();YEAR,MONTH,DAY获取当前时间对应的年月日selectyear(now());selectmonth(now());selectday(now());在制定日期上增加时间后的日期......
  • MYSQL学习笔记9: DQL排序查询(升降序)
    DQL排序查询select字段列表from表名orderby字段1排序方式1,字段2排序方式2;排序方式ASC升序(默认)DESC降序如果是多字段排序,第一个字段值相同,会根据第二个字段的值进行排序,以此类推按年龄降序排序select*fromworkersorderbyagedesc;......
  • MYSQL学习笔记10: DQL分页查询(利用limit)
    DQL分页查询(利用limit)select字段列表from表名limit起始索引,查询记录数;起始索引从0开始,起始索引=(查询页码-1)*每页显示记录数分页查询是数据库的方言,不同数据库有不同的实现,MYSQL中是LIMIT如果查询的是第一页的数据,起始索引可以省略,直接简写为l......