C语言学习笔记

练习题:

题目内容,日本某地发生了一件谋杀案,警察通过排查确定凶手必为4个嫌疑犯中的一人,以下为4个嫌疑犯的供词:

A:不是我;

B:是C

C :是D

D:C在说谎。

已知3个人说了真话一个人说的假话,写一个程序输出凶手。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
    char killer = 0;
    for (killer = 'a'; killer <= 'd'; killer++) {
        if ((killer != 'a') + (killer == 'c') + (killer == 'd') + (killer != 'd') == 3) {
            printf("killer=%c", killer);
        }
    }
    return 0;
}

赛马问题:有36匹马6个跑道没有计时器,请赛马确定,36匹马中的前三名,请问最少比赛几次。

解题思路:36匹马跑6次可以得出6个第一,然后让这6个第一再跑一次分出123456.

但是最后一次中的23名不一定比最后一次第一名的后面的23强,3也一定比2后面的第三名强,所以重新组成6个再跑一次。

所以一共8次。

比特培训(44课)


烧香问题:

如果有不均匀的两根香,但是一根燃完正好一个小时如何确定15分钟的时间。

解题:一根香两端点完,一个香点一边,燃完半个小时过去了,然后第二根再点燃一端,就是15分钟。-------牛客网智力题可以练习


char *p1[ ]="hello world";char *p2[ ]="hello world";

"hello world"是常量字符串,所以他的地址是固定的,内容不能修改。所以p1和p2是相等的。


下面test函数设计正确的是:()

char * arr[5]={"hello","bit"};

test(arr);

a: void test(char* arr)

b:void test(char** arr)

c:void test(char arr[5])

d:void test(char* arr[5])


下面代码中print_arr函数参数设计哪个是正确的()?

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

print_arr(arr,3,5);

题目内容:

A.void print_arr(int ar[][],int row,int col)

B.void print_arr(int *arr,int row,int col)

C.void print_arr(int (*arr)[5],int row,int col)

D.void print_arr(int (*arr)[3],int row,int col)


qsort在指针详解7.8集。


int main(){
   int aa[2][5]={1,2,3,4,5,6,7,8,9,10};
   int *ptr1=(int *)(&&aa+1);
   int *ptr2=(int *)(*(aa+1));
   printf("%d,%d",*(ptr1-1),*(ptr2-1));
}

主要是*(ptr2-1)不好理解,实际上就是aa实际上是二维数组的地址,*(aa+1)=aa[1],也就是拿到第二行元素的首地址,然后再减1就是5.

所以答案是10,5.


2c6251fe2a69424598fca7248977b28e.png


 

在arr1后添加arr2字符串

char arr1[30]="abc";

char arr2[]="def";

strcat(arr1,arr2);

自己给自己追加的时候要用strncat

strncat(arr1,arr1,3);

然后找arr1里面是否有arr2的子串用

strstr(arr1,arr2);如果找到了返回的是arr2首元素在arr1中的地址,如果为NULL,则没找到

 

 

 

strlen的返回值为unsigned int无符号数,所以如果相减也是无符号数,因此如果两个字符串长度相减为负数,要把负数的补码当作无符号数来看。

 

strcmp 字符串比较

strcmp(str1,str2)  str1大于str2 返回一个大于0的地址。相等返回0a70a09199805453aa3d33b6e0f454ebe.png

 长度不受限制的都是以“\0”为结束的

长度受限制的可以自己设长度

 

 

strtok(arr,sep);

strtok是用来拆分字符串的,sep是他的分隔符

例子

char arr[]="ll@163.com

char *p="@."

strtok(arr,p);    输出ll

strtok(NULL,p);输出163

strtok(NULL,p);输出com

拆分完之后返回NULL,没拆分完返回的是第一个元素的首地址,但是会把分隔符地方改成\0

 

strerrorfd3aa58ac46c46c6ac7de8b382f25c60.png

9c798f1f8c854857a0ad9b16b49e7528.png

400dff1eab524e68ac0e4901290f0c7f.png

 

上面是大小写转换,putchar可以输出

 

 

结构体的大小计算(结构体内存对齐)

1.第一个成员在结构体变量偏移量为0的地址处。

2.后面变量的要对其到对齐数的整数倍地址地之处。对齐数为min(系统对齐数,变量对齐数)

3.最后整体大小的时候取大于计算出来的最大地址的对齐数倍数的最小值。

4.如果里面嵌套了结构体,然后这个嵌套结构体就对应到自身的对齐数的整数倍位置。

比如  

struct S3{
double d;

char c;

int i;

}
struct S4{
char c;

struct S3;

double d;

}
大小分别为16,32

12b1b0830e6f459d80e1ce43d3401d22.png

offsetof用来计算成员变量相对于结构体的偏移量

offsetof(struct S4,c)  头文件为stddef.h  offsetof是宏

05d7ded59744437abf618a76b106f6c9.png


位段

1.位段的声明和结构是类似的,有两个不同,位段的成员必须是int,unsigned int或signed int。(整形就行)。一个位段中的类型都是一样的。

2.位段上的空间是按照需要4个字节(int)或者1个字节(char)的方式来开辟的

3.位段是不垮平台的,因为位段涉及很多不确定因素,所以在可移植程序中避免使用位段。

比如

struct A{

int a:2;--意思为a占2个bit

int b:5;--意思为占5个bit

int c:10;

int d:30;

}
长度为8个字节。

计算大小的时候int就先开辟4个字节,32个比特,想当于放了adc(从高位向地位填充,从右向左)就放不下d了,则剩下的丢弃,重新开辟4个字节放d.

66dfa20250f24f00b371c1035cdc0164.png
A就是一个位段类型。位段的位是二进制位的意思


枚举

enum sex{
male;  //0  这个可以设置初始值, 比如=3,后面的如果不再设置的话,就是4,5

female;//1

secret//2

};

e3b6050cedb045e99ad71feb42db35a7.png
 

 enum sex s =0;这样的语法是错的,因为左边为enum sex类型,0为int,所以不对

8ac89fc92e9a46348e8eab7b7cdd4511.png


联合(共用体)

联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间

union Un{

char c;

int i;

};

dc81f9c1728144e7854ff0d45cc44b5c.png

 


 

动态内存分配

malloc

free  

calloc

realloc

头文件stdlib.h

 

int * p =(int *)malloc(10*sizeof(int)) ------用来向内存申请10个整形空间。malloc返回的是首地址。

if( p=NULL) {

printf("%s",strerror(errno)); ----如果分配内存失败,则输出错误原因

}

free(p);----释放空间

p=NULL;---注意释放空间之后记得把地址至为空指针

 

calloc  申请内存空间并且初始化各元素为0;

int * p =(int *)calloc(10,sizeof(int));

free(p)

 

realloc:调整动态开辟内存的大小

 

9f1b2ac88b254c7aaebcd6d33e249185.png

上述代码错误,1.在初始化指针的时候没有赋值,所以是野指针2.返回了局部变量指针的地址,会出现非法访问的情况… 

 


 

柔性数组

结构体的最后一个数组成员长度未知

struct S{

int a;

char b[];

}或者

struct S{

int a;

char b[0];

}

柔性数组计算长度的时候没有包含那个数组的长度,数组的长度后续通过malloc分配

比如  struct S su= (struct S*)malloc(sizeof (struct S)+sizeof(char))

 


 

3e5c1060fe654628a637543004bc91d4.png

文本类型:

1.数据在内存内以二进制进行存储,如果不做处理输出到外存,则叫二进制文件

2.如果要求在外存上以ASCII的形式存储,则需要在存储前转换,以ASCII字符形式存储的文件叫文本文件。


3ef9d8dd7a9542a1860c7ad7ab0e1464.png


8e96a47c3d584affb5a19fcc11f01e94.png

ftell(n)--获取文件当前指针相对于起始位置的偏移量

void rewind(FILE* stream)  ---让文件指针回到文件的起始位置


6abc280e0ef44331979cc53667156e48.png


strerror(errno)---把错误码对应的字符串进行输出。

perror("hehe")---输出为hehe:错误内容,不需要输入错误码   --不需要引头文件

ferror(FILE* stream)----如果返回1,则说明文件读取失败导致的结束

feof(FILE* stream)----如果返回1,则说明文件结尾导致的结束

 


9cdc0fc3deae488f96fdf77a2565fd38.png

写宏的时候不要吝啬括号,比如SQUARE(5+1)  会被计算成5+1*5+1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值