C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)

目录

三、其他字符串函数

3.1 strstr——判断是否为子串

3.2 strtok——切割字符串

3.3 strerror——返回错误码所对应错误信息

四、字符操作函数

4.1 字符分类函数

4.2 字符转换函数

五、内存操作函数

5.1 memcpy

5.2 memmove

5.3 memcmp 

5.4 memset


三、其他字符串函数

3.1 strstr——判断是否为子串

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第1张图片

char* strstr(const char *str1, const char *str2);

如果str2是str1的子串的话则返回str2在str1中首次出现的地址。如果str2在str1中没出现则返回空指针NULL。

例如:

int main()
{
    char arr1[20] = "abcdefabcdef";
    char arr2[] = "cdef";
    char* ret = strstr(arr1, arr2);
    if(NULL == ret)
        printf("找不到子串\n");
    else
        printf("%s\n", ret);
    return 0;
}

输出为cdefabcdef。

【strstr的模拟实现】:

char* my_strstr(const char* str1, const char* str2)
{
	assert(str1 && str2);
	char* s1 = str1;
	char* s2 = str2;

	char* cur = str1;
	while (*cur)
	{
		s1 = cur;
		s2 = str2;
		while (*s1 && *s2 && *s1 == *s2)
		{
			s1++;
			s2++;
		}
		if (*s2 == '\0')
		{
			return cur;
		}
		cur++;
	}
	return NULL; //找不到
}

int main()
{
	char arr1[20] = "abcqabcd";
	char arr2[] = "bcd";
	char* ret = my_strstr(arr1, arr2);
	if (NULL == ret)
		printf("找不到子串\n");
	else
		printf("%s\n", ret);
	return 0;
}

3.2 strtok——切割字符串

这是一个很奇怪的函数,希望大家能仔细阅读以下讲解~

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第2张图片 char* strtok(char* str, const char* sep);

str是一个字符串,sep是一个由分隔符组成的字符串,str是被分割的。

例如:

int main()
{
    char arr[] = "[email protected]";
    const char* sep = "@.";
    strtok(arr, sep);
    return 0;
}

 strtok函数找到str中的下一个标记,并将其用\0结尾,返回一个指向这个标记的指针。即上面那个代码使用了一次strtok会把arr变成"abcdefg\0yeah.net",它把分隔符的地方变成\0,返回a的地址。

注意:strtok会改变被操作的字符串,所以在使用时切分的字符串一般都是临时拷贝的内容,并且可修改。如:

int main()
{
    char arr[] = "[email protected]";
    char buf[30] = {0};
    strcpy(buf, arr);
    const char* sep = "@.";
    strtok(buf, sep);
    return 0;
}

strtok第一个参数不为NULL,函数将找到str中第一个标记,strtok函数将保存它在字符串中的位置。若第一个参数为空的话,则会从保存好的位置继续往后找。例如:

int main()
{
    char arr[] = "[email protected]";
    char buf[30] = {0};
    strcpy(buf, arr);
    const char* sep = "@.";
    printf("%s\n", strtok(buf, sep));//只找第一个标记
    printf("%s\n", strtok(NULL, sep));//是从保存好的位置开始继续往后找
    printf("%s\n", strtok(NULL, sep));//是从保存好的位置开始继续往后找
    return 0;
}

输出结果为:

abcdefg

yeah

net

可以用for循环简化为:

int main()
{
    char arr[] = "[email protected]";
    char buf[30] = {0};
    strcpy(buf, arr);
    const char* sep = "@.";
    char* str = NULL;
    for(str=strtok(buf, sep); str!=NULL; str=strtok(NULL,sep))
    {
        printf("%s\n",str);
    }
    return 0;
}

3.3 strerror——返回错误码所对应错误信息

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第3张图片

 例如:

int main()
{
    printf("%s\n", strerror(0));
    printf("%s\n", strerror(1));
    printf("%s\n", strerror(2));
    printf("%s\n", strerror(3));
}

这四种错误会分别输出:

No error  Operation not peimitted   No such file or directory    No such process

每种错误码对应一种错误信息。

又例如:

#include 
#include 
#include 
#include   //用到了INT_MAX
#include 
int main()
{
    int* p = (int*)malloc(INT_MAX);
    if(p == NULL)
    {
        printf("%s\n", strerror(errno));
        return 1;
    }
    return 0;
}

遇到错误时会把错误码放到errno里去,所以这里用strerror(errno)即可输出错误信息:Not enough space

(补充:perror更方便,若将上面的printf那行换成perror("malloc");则可直接输出malloc: Not enough space)


四、字符操作函数

4.1 字符分类函数

再此列举一些:

iscntrl——判断是否为任何控制字符;isspace——判断是否为空白字符;

isdigit——判断是否为数字字符; isxdigit——判断是否为十六进制数字字符;

islower——判断是否为小写字母; isupper——判断是否为大写字母;

isalpha——判断是否为字母;isalnum——判断是否为字母或数字;

ispunct——判断是否为标点符号; isgraph——判断是否为任何图形字符;

isprint——判断是否为可打印字符;

比如:

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第4张图片

是数字返回非0,不是数字返回0。

其他字符分类函数也类似,可以自行查阅使用~


4.2 字符转换函数

int tolower (int c);  //小写转大写

int toupper (int c);  //大写转小写

int main()
{
    char ch =  'a';
    putchar(toupper(ch));
    return 0;
}

这样可以输出A。


五、内存操作函数

5.1 memcpy

strcpy只拷贝字符串,而memcpy是通用的。

int main()
{
    int arr1[10] = {1,2,3,4,5,6,7,8,9,10};
    int arr2[5] = {0};
    //此时strcpy()是不行的
    memcpy(arr2, arr1, 20);
    return 0;
}

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第5张图片

void*更有通用性。 

【memcpy的模拟实现】:

void* my_memcpy(void* dest, const void* src, size_t count)
{
	assert(dest && src);
	void* ret = dest;
	while (count)
	{
		*(char*)dest = *(char*)src;
		dest = (char*)dest + 1;
		src = (char*)src + 1;
		count--;
	}
	return ret;
}

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[5] = { 0 };
	//此时strcpy()是不行的
	my_memcpy(arr2, arr1, 20);
	for (int i = 0; i < 5; i++)
	{
		printf("%d ", arr2[i]);
	}
	return 0;
}

但这种写法也有一定缺陷,比如my_memcpy(arr1+2, arr1, 20);就会有问题(其实用库函数里的memcpy不会有问题但是不好)。因为这设计重叠内存拷贝。那么我们就可以使用下一个函数:memmove。


5.2 memmove

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第6张图片

 看上去好像没什么区别~但memmove可以完成重叠内存的拷贝!

【memmove的模拟实现】:

void* my_memmove(void* dest, const void* src, size_t count)
{
	assert(dest && src);
	void* ret = dest;
	if (dest < src)
	{
		//前->后
		while (count--)
		{
			*(char*)dest = *(char*)(src);
			dest = (char*)dest + 1;
			src = (char*)src + 1;
		}
	}
	else
	{
		//后->前
		while (count--)
		{
			*((char*)dest + count) = *((char*)src + count);
		}
	}
	return ret;
}

int main()
{
	int arr1[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int arr2[5] = { 0 };
	//此时strcpy()是不行的
	my_memmove(arr1+2, arr1, 20);
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", arr1[i]);
	}
	return 0;
}

5.3 memcmp 

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第7张图片

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第8张图片

int main()
{
    int arr1[] = {1,2,3,4,5};
    int arr2[] = {1,2,3,4,0x11223305};
    int ret = memcmp(arr1,arr2,17);
    printf("%d\n", ret);
    return 0;
}

 输出为0(因为是小端存储)。若改为memcpy(arr1,arr2,18);则输出负数。


5.4 memset

C语言常见库函数详解——【字符/字符串函数及内存操作函数】(二)_第9张图片

以字节为单位的内存设置。

int main()
{
    int arr[] = {1,2,3,4,5};
    memset(arr,0,20);
    return 0;
}

 这个操作可以把arr内值全变为0。(每个字节都是00)


好啦~这次关于“C语言常见库函数详解——【字符/字符串函数及内存操作函数】”的介绍就到此为止啦!感谢大家的阅读~希望能对大家有所帮助!欢迎大家一起交流ovo

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