C语言(五)

目录

求字符串长度:

长度不受限制的字符串函数:

 strcpy():字符串复制函数

 strcat()字符串追加(连接)函数

  strcmp()字符串比较函数

字符串受限制的函数:

strstr() -- 字符串查找

 strtok()函数 - 切割字符串

错误信息报告:

字符操作:

内存操作函数

memcpy - 内存拷贝

memmove()

memecmp()函数 - 内存比较

memset() - 内存设置函数


先介绍字符串函数以及内存函数有哪些:


1,求字符串长度:

2,长度不受限制的字符串函数:

3,字符串受限制的函数:

4,字符串查找

5,错误信息报告:

6,字符操作:

7,内存操作函数


求字符串长度:


strlen():不计算"\0",计算到‘\0’为止
 strlen()返回值为无符号数(易错)
 因为无符号数 - 无符号数得到的结果还是无符号数
int main()
{
    unsigned int a = 4;
    unsigned int b = 8;
    if (a - b > 0)
    {
        printf("a - b > 0\n");
        printf("%d\n", a - b);
        printf("%u\n", a - b);
    }
    else
    {
        printf("a - b < 0\n");
    }
    return 0;
}

长度不受限制的字符串函数:


 strcpy
 strcat
 strcmp


 
strcpy():字符串复制函数


char* strcpy (char* destination,const char* score);
 

int main()
{
    char arr[20] = "##########";
    //arr = "hello";    //err
    strcpy(arr, "hello");  //right
    //根据内存调试,可以看到’\0‘也会被复制;而且也必须复制
    //这个函数最好仅限字符串使用,而且要保证目标的空间足够大,可以存放源字符串的数据
    //当然目标字符串不可以是常量字符串(因为常量字符串不可以修改)
    printf("%s\n", arr);
    return 0;
}
//输出
hello


 strcat()字符串追加(连接)函数


char* strcpy (char* destination,const char* score);

char* my_strcat(char* dest, const char* sc)
{
    char* ret = dest;
    assert(dest&& sc);
    //1,找到目标字符串中的\0
    while (*dest)
    {
        dest++;
    }
    while (*dest++ = *sc++)
    {
        ;
    }
    return ret;
}
int main()
{
    char ch1[20] = "hello ";
    char ch2[] = "world";
    strcat(ch1, ch2);
    printf("%s\n", ch1);
    printf("%s\n", my_strcat(ch1, ch2));
    return 0;
}
//输出
hello world
hello worldworld


目标字符串空间足够;只作用于字符串('\0'也会被复制过去);
 原字符串和目标字符串都必须有’\0‘;


 
 strcmp()字符串比较函数


 
自己实现strcmp

int my_strcmp(const char* p1, const char* p2)
{
    assert(p1 && p2);
    while (*p1 == *p2)
    {
        if (*p1 == '\0')
        {
            return 0;
        }
        p1++;
        p2++;
    }
    //if (*p1 > *p2)
    //{
    //    return 1;
    //}
    //else
    //{
    //    return -1;
    //}
    return *p1 - *p2;


}
int main()
{
    char* p1 = "abc";
    char* p2 = "aabb";
    printf("%d\n", my_strcmp(p1, p2));
    printf("%d\n", strcmp(p1, p2));
    if (strcmp(p1, p2) == 0)
    {
        printf("相等\n");
    }
    else if (strcmp(p1, p2) < 0)
    {
        printf("p1<p2\n");
    }
    else
    {
        printf("p1>p2\n");
    }
    return 0;
}


字符串受限制的函数:


strncpy
 strncat
 strncmp
 后面追加一个int num;这个数字表示从源字符串复制,添加,比较0-num个

strstr() -- 字符串查找


strstr(str1,str2);
 在字符串str1里查找字符串str2是否存在
 char * strstr(const char* ,const char*);


char* my_strstr(const char* p1, const  char* p2)
{
    assert(p1 && p2);
    const char* flag = p1;
    const char* s1 = NULL;
    const char* s2 = NULL;
    if (*p2 == '\0')
    {
        return p1;
    }
    while (*flag)
    {
        s1 = flag;
        s2 = p2;
        while (*s1 && *s2 && (*s1 == *s2))
        {
            s1++;
            s2++;
        }
        if (*s2 == '\0')
        {
            return flag;
        }
        else
        {
            flag++;
        }
    }
    return NULL;
}
int main()
{
    //char ch1[] = "abcdef";
    char ch1[] = "abbabcdefbbc";
    //char ch2[] = "bcd";
    char ch2[] = "bbc";
    //char* ret = strstr(ch1, ch2);
    char* ret = my_strstr(ch1, ch2);
    if (ret == NULL)
    {
        printf("没找到!\n");
    }
    else
    {
        printf("找到了!\n");
    }
    return 0;
}
//输出
找到了!

 KMP算法 - 字符串查找算法
  
 


 strtok()函数 - 切割字符串


 192.168.3.122
 198 168 3 122
 char* strtok(char*str,const char*sep)

int main()
{
    char ch[] = "mhq@qq.com.mhq@qq.com";
    char* p =  ".@" ;

    //printf("%s\n",strtok(ch, p));
    //printf("%s\n",strtok(NULL, "@."));
    char temp[200] = { 0 };
    strcpy(temp, ch);
    char* ret = NULL;
    for (ret = strtok(ch, p); ret != NULL; ret = strtok(NULL, p))
    {
        printf("%s\n", ret);
    }
    return 0;
}
//输出
mhq
qq
com
mhq
qq
com


 strtok()函数会更改字符串,所以一般都是使用看临时拷贝且可修改的字符串;
 每次使用sttok()函数,都会记住这个函数的标记符的位置
 这个函数没有进行模拟实现


 

错误信息报告:

 // strerror()函数
 使用库函数的时候,都会设置错误码,把错误码转换为错误信息
全局错误码:int errno ;//5

int main()
{
    //printf("0:%s\n", strerror(0));
    //printf("1:%s\n", strerror(1));
    //printf("2:%s\n", strerror(2));
    //printf("3:%s\n", strerror(3));
    //printf("4:%s\n", strerror(4));
    //printf("5:%s\n", strerror(5));
    //printf("6:%s\n", strerror(6));
    FILE* pf = fopen("text.txt", "r");
    if (pf == NULL)
    {
        //printf("%s\n", strerror(errno));
        perror("");
        perror("fopen");
        return 1;
    }
    fclose(pf);
    pf = NULL;
    return 0;
}
//输出
No such file or directory
fopen: No such file or directory


创建了text.txt就不会显示错误码
 
 perror()函数:用来打印错误信息的函数
 
 
 


字符操作:

isdigit()
z字符分类函数:判断参数是否为真
int main()
{
    char ch = '1';
    int ret = isdigit(ch);
    printf("%d\n",isdigit(ch));
    //如果是数字字符返回4,如果不是返回0;
    printf("a:%d\n", islower('a'));
    //如果是数字字符返回2,如果不是返回0;

    return 0;
}
判断是你需要的字符,就返回非0;不是需要的,就返回0;

 字符转换函数

isupper()
 
int main()
{
    char ch[20] = { 0 };
    scanf("%s", ch);
    int i = 0;
    while (ch[i] != '\0')
    {
        if (isupper(ch[i]))
        {
            ch[i] = towlower(ch[i]);
        }
        else
        {
            ch[i] = towupper(ch[i]);
        }
        i++;
    }
    printf("%s\n", ch);

    return 0;
}
 


内存操作函数


memcpy()
memmove()
memcmp()
memset()
 


memcpy - 内存拷贝


void*memcpy(void *destination,const void*source,size_t num);

返回值为目标地址
注意:num表示复制的字节个数,也就是最小地址单位。

void* my_memcpy(void* dest, const void* src, size_t num)
{
    assert(dest && src);
    int i = 0;
    for (i = 0; i < num; i++)
    {
        //*((char*)dest+i) = *((char*)src + i);
        *((char*)dest)++ = *((char*)src)++;
    }

    return dest;
}
int main()
{
    int arr1[10] = { 1,2,3,11111111,5,6,7,8,9,10 };

    int arr2[20] = { 1,2 };
    //memcpy(arr2, arr1, 13);
    printf("%p\n",arr2);
    printf("%p\n",my_memcpy(arr2, arr1, 13));
    return 0;
}

 memcpy()函数应该拷贝不重叠的内存

memmove()


memmove()可以处理内存重叠的情况


void*memmove(void *destination,const void*source,size_t num);

void* my_memmove(void* dest, const void* src, size_t num)
{
    void* ret = dest;
    assert(dest && src);
    int i = 0;
    //可以把源数据从前向后拷贝,也可以从后向前拷贝
    if (dest > src)
    {
        //从后向前拷贝
        //for (i = 0; i < num; i++)
        //{
        //    *((char*)dest + num -1- i) = *((char*)src + num -1- i);
        //}
        while (num--)
        {
            *((char*)dest + num) = *((char*)src + num);
        }
    }
    else if (dest < src)
    {
        //从前向后拷贝
        for (i = 0; i < num; i++)
        {
            *((char*)dest+i) = *((char*)src + i);
            //*((char*)dest)++ = *((char*)src)++;
        }
    }
    else
    {
        ;
    }
    return ret;
}
int main()
{
    int arr1[10] = { 1,2,3,11111111,5,6,7,8,9,10 };

    int arr2[20] = { 1,2 };
    //memcpy(arr2, arr1, 13);
    printf("%p\n", arr1);
    //printf("%p\n", memmove(arr1 + 2, arr1, 20));
    //printf("%p\n", my_memmove(arr1 + 2, arr1, 20));
    printf("%p\n", my_memmove(arr1, arr1 + 2, 20));
    return 0;
}


memcpy - 只要实现了不重叠就可以了,而VS中的实现既可以拷贝不重叠,也可以拷贝重叠内存

memecmp()函数 - 内存比较


memcmp()和strcmp()很像
int main()
{
    float arr1[] = { 1.0,2.0,3.0,4.0 };
    float arr2[] = { 1.0,3.0 };
    printf("%d\n", memcmp(arr1, arr2, 4));
    printf("%d\n", memcmp(arr1, arr2, 8));

    return 0;
}


memset() - 内存设置函数


void *memset(void*ptr,int value,size_t num);

函数解释:将s中当前位置后面的n个字节 (typedef unsigned int size_t )用 ch 替换并返回 s 。

memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法

int main()
{
	int arr[10] = { 0 };
	int i = 0;
	memset(arr, 255, 20);
	for(i = 0;i<10;i++)
	{
		printf("%x\n", *(arr+i));
	}
	
	return 0;
}

输出

ffffffff
ffffffff
ffffffff
ffffffff
ffffffff
0
0
0
0
0

对于void *memset(void*  ptr  ,  int   value  ,  size_t num);

memset把每一个字节都用value来代替
//memset()只能对字符类型进行操作


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值