C语言笔记

笔记

  • C语言笔记_第1张图片
    十六进制只有a—f

    目录

      • 笔记
    • 内存
    • 数组
    • 指针
      • 概念
      • malloc函数
    • 字符串 %s
      • 字符串操作常用函数
        • 拷贝函数
        • 拼接函数
        • 比较函数
        • 查找子字符
        • 查找子串
        • 字符串分割
    • 自己实现字符串操作函数
    • 结构体
      • static
    • 链表
      • 链表静态添加和动态遍历
      • 动态添加

内存

64位编译器:
char :1个字节
char*(即指针变量): 8个字节
short int : 2个字节
int: 4个字节
unsigned int : 4个字节
float: 4个字节
double: 8个字节
long: 8个字节
long long: 8个字节
unsigned long: 8个字节

数组

注意数组越界
输出数组a中有多少个元素: sizeof(a)/sizeof(a[0])
数组名 = 数组首地址 = 数组第一个数据的地址
数组传参时main函数向其他函数中传递数组的首地址数组个数(sizeof(array)/sizeof(array[0])),该地址在Linux中占8个字节,之后就可在函数中遍历数组。

指针

概念

指针变量:存放地址的变量
指向谁 偏移后指向谁
定义指针变量为指针标识符//其余为运算符
地址强制保存 int* a = (int *)0xfe;

*a = 520;

指针数组
多变量的地址的集合 存放地址的变量
是一个数组,数组的每一个元素是指针(指针的数组)
int* parray[3];
数组指针 int (*p)[x];
指向某个数组,指向数组首元素地址
指向数组的指针偏移时偏移的是整个数组的大小 类型x数组长度的长度

函数指针 void (*p)() {};
这里给一下关于地址错误的代码:

#include

int main()
{
     
	int i = 10;
	int *p = &i;
	printf("i = %d\n",i);
	printf("i = %d\n",*p);
	printf("i的地址为:%d\n",&i);
	printf("p的地址为:%d\n",p);//printf("p的地址为 %d\n",&p);
	printf("i和p的地址一样都为 %d",&i);//偏移12位 
	return 0;
 } 

函数指针格式要求很强(参数类型,个数,返回值)
p = 【函数名】;
p()直接调用//(*p)();取内容,再调用

malloc函数

开辟 malloc(n * sizeof(int));
多次调用malloc所分配的地址不能有重叠部分,除非某次malloc所分配的地址被释放掉
malloc应该尽快完成内存分配并返回(不能使用NP-hard的内存分配算法)
内存大小调整 realloc
malloc申请的空间,程序不会主动释放。Linux中的话,程序结束后,系统会回收这个空间。使用free/p=NULL;

字符串 %s

可以直接定义 “abc”或者‘a’
char *array = "xxx"; 易造成段错误
字符串在内存中,除了有效字符外,还会自动在结尾处补一个’\0’,作为结束标志。
不能用sizeof来计算字符串中有效字符的个数!
常用strlen,他在计算字符串大小时,遇到’\0’就会结束计数。

字符串操作常用函数

	指针标识字符串时,先定义,然后malloc开辟空间(注意内存泄漏问题),最后memset初始化元素:
		char *p;
		p = (char *)malloc(128);
		memset(p,'\0',128);
		malloc开辟空间也可能会失败,可以用返回值做判断:
			if(p = NULL){
				exit(-1);
			}

拷贝函数

char *strcpy(char* dest, const char *src);
参数:dest为目标字符串,src为原字符串。
返回值:目标串的地址。
例:

char strDest[128] = {
     '\0'};
						char *strSrc = "li";
						strcpy(strDest,strSrc);

如果想要继续使用strcpy来复制字符串到strDest,则需要重新初始化数组:

memset(strDest,'\0',sizeof(strDest)/sizeof(strDest[0]));
strcpy(strDest,"li is handsome");

///分割线

char *strncpy(char *destinin, char *source, int maxlen);

参数:destinin:表示复制的目标字符数组;source:表示复制的源字符数组;maxlen:表示复制的字符串长度。
例:

strncpy(strDest,"x",5);
						puts(strDest);

strcpy只是复制字符串,但不限制复制的数量,很容易造成缓冲溢出。strncpy要安全一些。 strncpy能够选择一段字符输出,strcpy则不能。

拼接函数

char *strcat(char *dest, const char *src);

功能:把src所指向的字符串(包括“\0”)复制到dest所指向的字符串后面(删除dest原来末尾的“\0”)。
要保证
dest足够长,以容纳被复制进来的*src。*src中原有的字符不变。返回指向dest的指针。
例:

char strDest[128] = "123456";
				char *strSrc = "xxx";
				strcat(strDest,strSrc);
				puts(strDest);

比较函数

int strcmp(const char *s1,const char *s2);

strcmp函数是string compare(字符串比较)的缩写,用于比较两个字符串并根据比较结果返回整数。
基本形式为strcmp(str1,str2),若str1=str2,则返回零;若str1str2,则返回正数。
两个字符串自左向右逐个字符相比(按ASCII值大小相比较),直到出现不同的字符或遇’\0’为止。
例:

                        char *str1 = "123";
						char *str2 = "123";
						判断两字符串是否一样:
						if(!strcmp(str1,str2)){
     
							printf("两个字符串相同\n");
						}

查找子字符

char *strchr(const char *str, char c)

参数:str-要被检索的 C 字符串。c-在 str 中要搜索的字符。
功能:在参数str所指向的字符串中搜索第一次出现字符c(一个无符号字符)的位置。
返回值:返回一个指向该字符串中第一次出现的字符的指针,如果字符串中不包含该字符则返回NULL空指针。
例:

char *str = "abcd";
     char c = 'h';
    char *p = NULL;
p = strchr(str,c);
if(p == NULL){
     
	printf("没有找到\n");
}else{
     
	printf("找到\n");
	puts(p);
}

查找子串

strstr()函数用来检索子串在字符串中首次出现的位置,其原型为:

char *strstr( char *str, char * substr );

函数参数:str参数为要检索的字符串,substr参数为要检索的子串。
函数返回值: 返回字符串str中第一次出现子串substr的地址;如果没有检索到子串,则返回NULL。
例:

char *substr = "hen";
						char *p = NULL;
						p = strstr(str,substr);
						puts(p);
				

字符串分割

strtok字符串的分割 :char *strtok(char *s, char *delim);
例:

char str[] = "li,zhe,zhe,hello,world";
					char *p = NULL;
					p = strtok(str2,",");
					puts(p); //获取到的第一个子串
					p = strtok(NULL,",");
    				printf("获取到第二个串:p=%s\n",p);//获取到的第二个字串
    				如果p==NULL,说明后续没有子串了。

获取子串并将其存储在指针数组中:

    				char str2[] = "li,zhe,zhe,hello,world";
    				char *p = NULL;
    				char *psubs[10];
    
    				int i =1;
    				p = strtok(str2,",");
    				if(p!=NULL){
     
       					 //printf("获取到第一个串p=%s\n",p);
        				psubs[i-1] = p;
    				}
    
    				while(1){
     
       					i++;
        				p = strtok(NULL,",");
        				if(p != NULL){
     
          				//  printf("获取到第%d个串p=%s\n",i,p);
          					psubs[i-1] = p;
        				}else{
     
            				printf("没有子串了\n",p);
            				break;
        				}
    				}
    
    				int j;
    				for(j=0;j<i;j++){
     
        				puts(psubs[j]);
    				}
``

转为小写函数:strlwr
转为大写函数:strupr

自己实现字符串操作函数

    ————gets:
			int mygets(char *p)
			{
     
			        int ret = 0;
			        if(p == NULL){
     
			                return;
			        }
			        while((*p=getchar()) != '\n'){
     
			                ret++;
			                p++;
			        }
			        return ret;
			}
    ————puts:
			void myputs(char *p)
			{
     
			        while(*p != '\0'){
     
			                putchar(*p++);
			        }
			        putchar('\n');

}
    ————strlen:
			int mystrlen(char *p)
			{
     
			        int cnt = 0;
			        while(*p++ != '\0'){
     
			                cnt++;
			        }
			        return cnt;
			}
	————memset:
			void mymemset(char *p,char c,int size)
			{
     
			        while(size){
     
			                *p++ = c;
			                size--;
			        }
			}
	————strcpy:
			char *mystrcpy(char* dest, char *src)
			{
     
			        if(dest==NULL || src==NULL){
     
			                return NULL;
			        }
			        while(*src != '\0'){
     
			                *dest++ = *src++;
			        }
			        *dest = '\0';
			        return dest;
			}
	————strncpy:
			char *mystrncpy(char* dest, char *src, int maxlen)
			{
     
			        if(dest == NULL || src == NULL){
     
			                return NULL;
			        }
			        while(*src != '\0' && maxlen >0){
     
			                *dest++ = *src++;
			                maxlen--;
			        }
			        *dest = '\0';
			        return dest;
			}
	————strcat:
			char * mystrcat(char *dest, char *src)
			{
     
			        while(*dest != '\0'){
     
			                dest++;
			        }
			        while(*src != '\0'){
     
			                *dest++ = *src++;
			        }
			        *dest = '\0';
			        return dest;
			

结构体

struct data{
     
char* name;
int score;
};
struct data data1;

字符串用ctrcpy赋值:strcpy(stu1.name,"lizhe");(先开辟空间)

static

限定结构体变量作用域只在这个文件,防止别的文件有相同文件名而导致出现错误
结构体指针

struct data *p;
p = (struct data *)malloc(sizeof(struct data));
p->name = "lizhe"//错误
strcpy(p->name,"lizhe")

注意结构体指针的偏移 偏移的是整个结构体大小
写函数:

struct student* getmes() 

{} 不需要返回值也可以
如果要找一个人

int FindSomeone(struct data *p,char *name)
{
     
	int i;
	for(i=0;i<128;i++)
	{
     
		if(strcmp(name,p->name) == 0)
		{
     
			return 1;
		}
		p++;
	}
	return 0;
}

结构体大小计算:自行参阅

https://blog.csdn.net/chenlichenforlinux21/article/details/89950075

https://blog.csdn.net/chenlichenforlinux21/article/details/103311310

typedef:为了代码编写简洁
char 能表示2的8次方
int 能表示2的32次方
double float 根据环境
4种数据类型0——128都可以表示
例:

typedef unsigned int u_int8;
        u_int8 = oxfe;
 //在结构体中 可以
 typedef struct 
 {
     
 }STU,*pstu;

链表

结构体的应用

  1. 概念
    数据结构(思想)
    比如一组数组,它的地址是连续的。 增删减改难以实现,且数组开始内存就已经确定。
    链表即指针的传递,灵活 比如:
    C语言笔记_第2张图片

在这里插入图片描述
链表的地址不连续

链表静态添加和动态遍历

#include 
//#include 

struct Test
{
     
	int stunum;
	struct Test *next;
};

void printlink(struct Test *head)//打印链表
{
     
	struct Test *point;
	point = head;
	
	while(point != NULL)
	{
     
			printf("%d\n",point->stunum);
			point = point->next;
	}
	putchar('\n');
 } 
 
 int getlinktotal(struct Test *head)//节点个数 
 {
     
 	int cnt = 0;
 	while(head != NULL)
 	{
     
 		cnt++;
 		head = head->next;
	 }
	 //printf("链表节点个数为:%d\n",cnt);
	 return cnt;
 }
 
 int searchlinktotal(struct Test *head,int a)//查找数据存在 
 {
     
 	while(head != NULL)
 	{
     
 		if(head->stunum == a)
 		{
     
 			return 1;
		 }
 		head = head->next;
	 }

	 return 0;
 }
 
 int createlink(struct Test *head,struct Test *new,int a)//指定位置后方添加 
 {
     
 	struct Test *p = head;
	 while(p != NULL)
	 {
     
	 	if(p->stunum == a)
	 	{
     
	 		new->next = p->next;
	 		p->next = new;
	 		return 1;
		 }
		 p = p->next;
	  } 
 	return 0;
 	
 }
 
 struct Test* createlinkin(struct Test *head,struct Test *new,int a)//指定位置前插入 
{
     
	struct Test *p = head;
	if(p->stunum == a)//链表头添加 
	{
     
		new->next = head;
		return new;//改变链表头! 
		}	
	while(p->next != NULL)
	{
     
		if(p->next->stunum == a)
		{
     
			new->next = p->next;
			p->next = new;
			return head;
		}
		p = p->next;
	}
	return head;
}

struct Test* delatelink(struct Test *head,int a)//删除 
{
     
	struct Test *p = head;
	if(p->stunum == a)
	{
     
		head = head->next;
		//free(p);
		return head;
	}
	while(p->next != NULL)
	{
     
		if(p->next->stunum == a)
		{
     
			p->next = p->next->next;
			return head;
		}
		p = p->next;
	}
	return head;
}

 int main()
 {
     
 	int i;
 	
 	//struct Test *p = (struct Test*)malloc(sizeof(struct Test));
 	struct Test t1 = {
     1,NULL};
 	struct Test t2 = {
     2,NULL};
 	struct Test t3 = {
     3,NULL};
 	
 	t1.next = &t2;
 	t2.next = &t3;
	 
	 struct Test new = {
     100,NULL};
	 int b = createlink(&t1,&new,2);
	 if(b == 1)
	 {
     
	 	printf("插入成功!"); 
	 }
	int totalnum = getlinktotal(&t1);
	printf("链表节点个数为:%d\n",totalnum);
    printlink(&t1);
    
    int ret = searchlinktotal(&t1,6);
    if(ret == 1)
    {
     
    	printf("YES!");
	}
	else printf("NO!");
	
	struct Test *head = NULL;
	 head = &t1;
	 struct Test new1 = {
     101,NULL};
	 head = createlinkin(head,&new1,1);
 	
 	return 0;
  } 

动态添加

头插法/尾插法:

#include 
#include 
struct test
{
     
	int data;
	struct test *next;
};


void printlink(struct test *head)
{
     
	struct test *point;
	point=head;
	while(point !=NULL)
	{
     
		printf("%d ",point->data);
		point = point->next;
	}		
	putchar('\n');
}


struct test* insertfromhead(struct test *head,struct test *new)
{
     
		if(head==NULL)
		{
     
			head=new;
		}
		else//如果不是
		{
     
			new->next=head;
			head=new;//
		}
		return head;
}

struct test* createlink(struct test *head)
{
     
	struct test *new;
	while(1)
	{
     
		new =(struct test *)malloc(sizeof(struct test));
		printf("input your new node data:\n");
		scanf("%d",&(new->data));
		if(new->data ==0)
 		{
     
			printf("0 quit\n");
			free(new);
			return head;返回头
		}
		head = insertfromhead(head,new);//调用头插法函数并将返回数据给头
	}

}
int main()
{
     	
	struct test *head = NULL;
	head = createlink(head);
 	printlink(head);
	struct test t1 ={
     1000,NULL};//传参
	head = insertfromhead(head,&t1);
 	printlink(head);

	return 0;
}



尾插

#include 
#include 
struct test
{
     
	int data;
	struct test *next;
};


void printlink(struct test *head)
{
     
	struct test *point;
	point=head;
	while(point !=NULL)
	{
     
		printf("%d ",point->data);
		point = point->next;
	}		
	putchar('\n');
}


struct test* insertbehind (struct test *head,struct test *new)
{
     
	struct test *p =head;
	if(p==NULL)
	{
     
		head=new;
		return head;
	}
 
	while(p->next != NULL)
	{
     
		p=p->next;//
	}
	p->next =new;//
	return head;
}


struct test* createlink2(struct test *head)//动态后插法
{
     
	struct test *new;
	while(1)
	{
     
		new =(struct test *)malloc(sizeof(struct test));
		printf("input your new node data:\n");
		scanf("%d",&(new->data));
		if(new->data ==0)
 		{
     
			printf("0 quit\n");
			free(new);
			return head;
		}
		head = insertbehind(head,new);
	}
}

int main()
{
     	
	struct test *head = NULL;
	head = createlink2(head);
 	printlink(head);
	
	struct test t2 ={
     2000,NULL};
	head =insertbehind(head,&t2);	
 	printlink(head);

	return 0;
}



你可能感兴趣的:(笔记,c语言)