一、字符串、字符、字节

1、size_t为无符号整数类型,在表达式中使用无符号数可能导致不可预料的结果

int main()

{

char *p = "abcdef";

char *q = "abc";

if (strlen(q) - strlen(p) >= 0)

{

printf("q<p\n");

}

else

{

printf("q >= p\n");

}

system("pause");

return 0;

}

永远返回q>=p,因为strlen函数返回值为size_t,所以永远大于0,应该改为if(strlen(x)>=strlen(y))

2、不受限制的字符串函数

(1)strcpy函数

功能:

使用的时候的注意事项:1)dst所指的空间>src所指的空间

                      2)dst不能是常量,例如:char *p="asdfg"

附:查询gets函数的功能

(2)strcat

功能:

使用的时候的注意事项:1)dst所指的空间>src所指的空间

                      2)dst不能是常量,例如:char *p="asdfg"

                      3)不能给自己追加

(3)strcmp比较函数

功能:

使用的时候的注意事项:1)dst所指的空间>src所指的空间

                      2)dst不能是常量,例如:char *p="asdfg"

                      3)可以自己比较自己

3、长度受限制的函数

(1)字符串函数

a)strncpy

b)strncat

c)strncmp

(2)内存管理函数

a)memmove

b)memcmp

4、字符串查找基础

(1)查找一个字符

a)strchar:查找第一个字符

b)strchr:查找最后一个字符

(2)查找任意个字符

 strbtk函数

注意:(1)有可能返回NULL,输出前先做判断

(3)查找一个子字符串:strstr

注意:返回第一次出现的位置

5、高级字符串查找

(1)查找一个字符串前缀

strspn(char const *str,char const *group);起始作用

strcspn(char const *str,char const *group);不予匹配

(2)查找标记

a)strtok

注意:1、会改变原字符串

      2、如果源字符串,不能被修改,那么就对被查找的字符串做一份临时的拷贝

      3、传值比较特殊,第一次传tmp,第二次传NULL(这个函数可以传NULL,我想应该保存了全局和静态变量)

使用方法:

#include <stdio.h>
#include <string.h>

int main()
{
	char *p = "192.168.0.1";
	char tmp[20];
	strcpy(tmp, p);

	char *token;
	for (token = strtok(tmp, ".");
		token != NULL;
		token = strtok(NULL, "."))
	{
		printf("%s\n", token);
	}
	system("pause");
	return 0;
}

运行结果:

wKioL1ZhRuWAhdg6AAAQCMqtdHk317.png

(2)strerror

功能:返回错误代码所对应的信息

使用方法:接受int,返回字符指针,strerror(errno),其中errno为当前错误码

注意事项:定义在#include<errno.h>,相当于工具->错误查找(有可能不是C语言的)


6.内存操作

思考:为什么有了字符串操作函数,还要内存操作函数

答案:可以处理内存块,而不管其中间的类型

(1)内存拷贝

a)memove

b)memcmp

(2)msmset初始化函数,往往在动态内存开辟中用


二、动态内存开辟

1、malloc开辟内存块,动态内存管理

使用方法:

#include<stdio.h>
#include <stdio.h>
int main()
{
	int arr[10];
	int i = 0;
	int n = 0;
	scanf("%d", &n);
	int *p = (int *)malloc(n*sizeof(int));
	if (p == NULL)//判断内存是否开辟成功
	{
		printf("out of memory\n");
		return -1;
	}
	for (i = 0; i < n; i++)
	{
		p[i] = i; *(p + i);
	}
	for (i = 0; i < n; i++)
	{
		printf("%d\n", p[i]);
	}
	free(p);//可以收回空指针
	system("pause");
	return 0;
}

注意事项:1、内存泄漏(自己用不上,别人也用不上)

            程序结束后自动收回,没有泄漏

          2、对NULL进行解应用

2、calloc开辟内存并初始化为"0",所以更低效

3、realoc调整空间大小

4、malloc写成#define MALLOC形式,封装为上层

a)test.c中

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
 
#include "alloc.h"
 
int main()
{
int *p = malloc(10);
int *p = (int *)malloc(10 * sizeof(int));
int i = 0;
p=realloc(p, 80);
for (i = 0; i < 20; i++)
{
p[i] = i;
}
free(p);
 
system("pause");
 
return 0;
}

B)alloc.h文件

#ifndef __ALLOC_H__
#define __ALLOC_H__

#include <stdio.h>

void *alloc(int sz);

#define MALLOC(NUM, TYPE)  \
	(TYPE*)alloc(NUM * sizeof(TYPE))

#define malloc 不能使用malloc

#endif  //__ALLOC_H__

c)alloc.c文件

#define _CRT_SECURE_NO_WARNINGS 1

#include "alloc.h"

void *alloc(int sz)
{
#undef malloc
	void *p = malloc(sz);
	if (p == NULL)
	{
		printf("out of memory\n");
		exit(1);
		//return NULL;
	}
	return p;
}

6、内存开辟的过多不收回,有可能系统会崩溃

#include <stdio.h>
 
int main()
{
int count = 0;
while (malloc(1 << 20))//开辟一兆空间
{
count++;
}
printf("%d\n", count);
system("pause");
return 0;
}

5、relloc,要用其指针接受其返回值(因为返回值有可能会变)

例如:int *q=(int *)realloc(p,80)

6、不是开辟的物理空间,是虚拟地址,认为自己开辟的相当于all computer

7、free只能释放动态开辟的空间

char *p只能是malloc,relloc,calloc,才能free(p)

8、free可以释放空指针NULL,不能释放动态内存的某一部分

9、free函数不能将p置成空,是野指针

8、模拟开辟二维数组

10、改编电话本,将电话本实现为动态增长的

11、结构体的动态开辟问题(详情请看C语言深度剖析 5.3)

部分问题请看如下程序:

#include<stdio.h>
#include <stdio.h>

typedef struct Stu
{
	//char name[20];*****************
	char *name;
	int age;
}Stu, *pStu;

int main()
{
	//struct Stu stu = { 0 };*******************
	//stu.name = "abcdef";      这时的*********这时的name为数组名,不能赋值
	pStu pstu = (pStu)malloc(sizeof(Stu));
	pstu->name = (char *)malloc(12);
	strcpy(pstu->name, "abcdef");//同时一定要给*name开辟空间,要
	pstu->age = 20;             //不然name美欧指定空间
	                            //同时注意给字符串开辟空间一定要预留'\0'
	printf("%s\n", pstu->name);
	free(pstu->name);
	free(pstu);
	pstu->name = NULL;
	pstu = NULL;
	system("pause");
	return  0;
}

注意事项:结构体假如先释放结构体后释放name,就会永远内存泄漏

12、模拟实现strstr

#include<stdio.h>
#include<stdlib.h>
char *my_strstr(const char *str1, const char *str2)
{

	const char *ptr = str1;
	const char *p1 = NULL;
	const char *p2 = NULL;
	while (*ptr)
	{
		p1 = ptr;
		p2 = str2;
		while (*p1 == *p2)
		{
			p1++;
			p2++;
			if (*p2 == '\0')
				return (char *)ptr;
		}
		ptr++;
	}
	return NULL;
}

int main()
{
	char *p = "bcd";
	char*q = "bcd";
	char *ptr = my_strstr(p, q);
	printf("%s\n", ptr);
	system("pause");
}