C 字符串类型例题讲解与实现字符串库函数

1、实现C语言中strupr和strlwr函数 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void str_upr(char *p)
{
    int i;
    int len = strlen(p);
    for (i = 0; i < len - 1; i++)
        if (p[i] >= 'a'&&p[i] <= 'z')
            p[i] = p[i] - 'a' + 'A'; //p[i] -= 32; 在ASCII表里小写字母的值比对应大写字母的值大32
}
void str_lwr(char *p)
{
    int i;
    int len = strlen(p);
    for (i = 0; i < len - 1; i++)
        if (p[i] >= 'A'&&p[i] <= 'Z')
            p[i] = p[i] + 'a' - 'A';//p[i] += 32;
}
void main()
{
    char str[128] = { "MSpaint" };
    puts(str);

    str_upr(str);
    puts(str);

    str_lwr(str);
    puts(str);
    system("pause");
}

2、实现C语言中strrev函数

函数原型:char *strrev(char *str); 用于字符串的逆置。

函数功能:把字符串s的所有字符的顺序颠倒过来(不包括空字符NULL)。

函数说明:返回指向颠倒顺序后的字符串指针。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void str_rev(char *p)
{
    char tmp;
    int len = strlen(p);
    for (int i = 0; i < len / 2; i++)
    {
        tmp = p[i];
        p[i] = p[len - 1 - i];
        p[len - 1 - i] = tmp;
    }
}
void main()
{
    char str[10] = "ABCDEFG";
    puts(str);

    str_rev(str);
    puts(str);
    system("pause");
}

3、实现C语言中strset函数

函数原型:extern char *strset(char *str, char character)
参数说明:str为源字符串,character为一个字符。
函数功能:将字符串str中所有的字符都设置成为指定的字符character。
返回说明:返回所有字符都设置为character后的字符串的指针。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void str_set(char *str, char ch)
{
    while (*str != '')
    {
        *str = ch;
        str++;
    }
}
void main()
{
    char str[128] = "Hello world!!!";
    puts(str);

    str_set(str, 'Y');
    puts(str);
    system("pause");
}

4、实现C语言中memset函数

函数原型:原型:extern void *memset(void *ptr, int value, size_t num)
函数功能:将ptr所指的内存区域的前num个字节都设置为value的ASCII值,然后返回指向ptr的指针。
函数说明:参数value虽声明为int,但必须是unsigned char,该函数使用unsigned char(一个字节8位)转换填充内存块,所以范围在0 到255 之间。无论value多大只有后八位二进制有效,而后八位二进制的范围在(0~255)中。而对字符数组操作时则取后八位赋值给字符数组,后八位值作为ASCII码。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void *mem_set(void *ptr, int value, int num)
{
    unsigned char *px = (unsigned char *)ptr;
    if (ptr == NULL)
        return px;
    while (num > 0) //num--
    {                //*ptr++ = (unsigned char)value;
        *px = (unsigned char)value; //把int类型的value转换成unsigned char类型,意味着截去c的高24位,只保留低8位
        px++;     
        num--;
    }
    return ptr;
}
void main()
{
    char str[] = "God bless you";
    int a[6] = { 1,2,3,4,5,6 };

    mem_set(str, '&', 9);
   puts(str);
mem_set(a,
2, 32); for (int i = 0; i < 6; i++) printf("%d ", a[i]); system("pause"); }

数组str是字符型的,字符型占据内存大小是1Byte,而memset函数也是以字节为单位进行赋值的,所以你输出没有问题。 不加单引号,就是以此数字填充一个字节。数字输出的就是ASCII值对应的控制字符。加单引号' '就是以字符的ASCII值去填充一个字节。输出的就是字符。

如果用memset(a,2,sizeof(a)),就是对a指向的内存的24个字节进行赋值,每个都用数2去填充,转为二进制后,2就是0000 0010,占一个字节。一个int元素是4字节,合一起是0000 0010,0000 0010,0000 0010,0000 0010,转化成十进制就是33686018,就完成了对一个int元素的赋值了。

如果用memset(a,'H', sizeof(dx)),以字符' '形式初始化,先将字符' '转为ASCII值,例如'H'的ASCII值为72,转为二进制后就是0100 1000占一个字节,一个int元素4字节,合一起就是0100 1000,0100 1000,0100 1000,0100 1000,转化为10进制就是1212696648

 

5、实现C语言中strcat函数

函数原型: char *strcat(char *dest, const char *src)
函数功能:把src所指向的字符串(包括"")复制到dest所指向的字符串后面(删除*dest末尾的"")。
注意:src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *str_cat(char *dest, char *src)
{
    if (dest == NULL || src == NULL)
        return NULL;
    else
    {
        char *p = dest;
        while (*dest != '')
            dest++;
        while (*src != '') //(*dest++ = *src++) != ''
        {
            *dest = *src;
            dest++;
            src++;
        }
        *dest = '';
        return p;
    }
}
void main()
{
    char dest[64] = "Hello ";
    char src[16] = "C++ user";

    str_cat(dest, src);
    puts(dest);
    system("pause");
}

6、实现C语言中strncat函数

函数原型:char * strncat(char *dest, const char *src, size_t n)

函数功能:把src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的'',字符追加完成后,再追加''。

函数说明:src和dest所指内存区域不可以重叠,并且dest必须有足够的空间来容纳src的字符串,返回指向dest的指针。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
char *str_ncat(char *dest, char *src, int num)
{
    if ((NULL == dest) || (NULL == src)) return NULL;
    char *p = dest;
    int i = 0;

    while (*dest != '')
        dest++;
    while (i < num && *src != '')
    {
        *dest++ = *src++;
        i++;
    }
    *dest = '';
    return p;
}
void main()
{
    char str1[32] = "Hello ";
    char str2[10] = "Mrs.Yang";
    char *p = " And Dr.cheng";

    puts(str_ncat(str1, str2, sizeof(str2)));
    puts(str_ncat(str1, p, 13));

    system("pause");
}

7、实现C语言中strchr函数

函数原型:char *strchr(const char *str, int c)

函数功能:在参数 str 所指向的字符串中搜索第一次出现字符 c(一个无符号字符)的位置。

函数说明:该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *str_chr(char *dest, char ch)
{
    if (dest == NULL)    
        return NULL;
    while (*dest != '')
    {
        if (*dest == ch)
            return dest;
        dest++;
    }
    return NULL;
}
void main()
{
    char str[32] = "Github";
    char ch = 'h';

    char *p = str_chr(str, ch);

    if (p == NULL)
        printf("Not found");
    else
        printf("%c %p", *p, &p);
    system("pause");
}

8、实现C语言中strcmp函数

函数原型:extern int strcmp(const char *s1,const char *s2)

函数说明:用于比较两个字符串并根据比较结果返回整数。若str1 = str2,则返回零;若str1 > str2,则返回正数;若str1 < str2,则返回负数

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int str_cmp(char *str1, char *str2)
{
    int i;
    for (i = 0; str1[i] == str2[i] && str1[i] != ''; i++); //跳过两个字符串相同部分
    if (str1[i] == ''&&str2[i] == '')
        return 0;
    else
        if (str1[i] > str2[i])
            return 1;
        else
            return -1;
}

int str_cmp_(char *s, char *t)
{
    while (*s == *t && *s != '')
    {
        s++;
        t++;
    }
    return *s - *t; //返回第一对不同字符的ASCII差值
}

void main()
{
    char str1[16] = "Las Vegas";
    char str2[16] = "Macao";

    printf("%d", str_cmp(str1, str2));
    system("pause");
}

9、实现C语言中strcpy函数

原型原型:char *strcpy(char* dest, const char *src)

函数说明:把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间;src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *str_cpy(char *strDest, const char *strSrc)
{
    if ((NULL == strDest) || (NULL == strSrc)) return 0;
    char *p = strDest; //可以返回函数内部定义的指针,但是不能返回函数内部定义的数组

    while (*strSrc != '')
    {
        *strDest = *strSrc;
        strDest++;
        strSrc++;
    }
    *strDest = ''; //while ((*strDest++ = *strSrc++) != '');''已复制
                 //赋值表达式返回左操作数,所以在赋值''后,循环停止
    return p;
}

void main()
{
    char str1[16];
    char str2[8] = "Viva";
    char *str3 = "Las Vegas";

    str_cpy(str1, str2);
    puts(str1);

    puts(str_cpy(str1, str3));

    system("pause");
}

10、实现C语言中strncpy函数

函数原型:char *strncpy(char *dest, const char *src, int n)

函数功能:把src所指向的字符串中以src地址开始的前n个字节复制到dest所指的数组中,并返回被复制后的dest。

函数说明:复制字符串src中的内容(字符,数字、汉字....)到字符串dest中,复制多少由n的值决定。如果src的前n个字符不含NULL字符,则结果不会以NULL字符结束。如果n<src的长度,只是将src的前n个字符复制到dest的前n个字符,结果dest不包括'',需要手动添加一个''。如果src的长度小于n个字节,则以NULL填充dest直到复制完n个字节。src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符长度+''。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
char *str_ncpy(char *strDest, char *strSrc, int num)
{
    if ((NULL == strDest) || (NULL == strSrc)) return 0;
    char *p = strDest;
    int i = 0;

    while (i < num && *strSrc != '')
    {
        *strDest++ = *strSrc++;
        i++;
    }
    *strDest = '';
    return p;
}

void main()
{
    char str1[16];
    char str2[8] = "Please";
    char *pc = "Sit down";

    str_ncpy(str1, str2, 6);
    puts(str1);

    puts(str_ncpy(str1, pc, 10));

    system("pause");
}

11、实现C语言中strlen函数

函数原型:extern unsigned int strlen(char *string)

函数功能:计算给定的字符串长度,直到碰到第一个字符串结束符''为止,然后返回计数器值(长度不包含''),char*做参数,且必须是以''结尾的。

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
int str_len(char *str)
{
    int len = 0;
    while (*str++ != '') //计数器
        len++;
    return len;
}

int str_len1(char *p)
{
    const char *pt = p;
    while (*p++ != ''); //指针相减

    return (p - pt - 1);
}

int str_len3(char *str)
{
    if (*str == '')
        return 0;
    else
        return 1 + str_len3(str + 1); //递归
}

int str_len4(char *str)
{
    return assert(str), !(*str) ? 0 : 1 + str_len4(str + 1); //逗号运算符和条件表达式
}

void main()
{
    char str[16] = "Viva Las Vegas";
    char *ps = "Sit down";

    printf("%d %d", str_len(str), str_len(ps));

    system("pause");
}

12、实现C语言中strstr

函数原型:extern char *strstr(char *str1, const char *str2)

函数说明:若str2是str1的子串,则返回str2在str1的首次出现的地址;如果str2不是str1的子串,则返回NULL。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *str_str(char *str, const char *sub)
{
    char *p = str;
    if (NULL == str || NULL == sub) return NULL;

    int M = strlen(str);
    int N = strlen(sub);
    int i, j, flag;

    for (i = 0; i <= M - N; i++)
    {
        flag = 1;
        for (j = 0; j < N; j++)
            if (str[i + j] != sub[j])
            {
                flag = 0;
                break;
            }
        if (flag == 1)
            return (p + i); //返回找到的地址
    }
    return NULL;
}
void main()
{
    char str[32] = "Hooollp";
    char sub[10] = "ol";
    char *p = str_str(str, sub);

    if (NULL == p)
        printf("没有找到");
    else
        printf("地址%p 在str中第%d个位置", p, (p - str));

    system("pause");
}

while循环

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * my_strstr(const char *str, const char *sub)
{
    if (NULL == str || NULL == sub) return NULL;
    char *cur = (char *)str;

    while (*cur != '')
    {
        char *temp_str = cur;//记录母串起始地址
        char *temp_substr = (char *)sub;//记录子串起始地址

        while (*temp_str++ == *temp_substr++)
        {
            printf("%c  ", *temp_str);//为测试用 此时%c是递增后的字符
            if (*temp_substr == '') //退出此时my_strstr函数
            {
                return cur;
            }
        }
        cur++;//母串递增
    }
    return NULL;
}
void main(int argc, char *argv[])
{
    char *string = "adcabcdef!";
    char *substring = "abc";
    char *ret = my_strstr(string, substring);

    if (ret == NULL)
        printf("不存在
");
    else
        printf("
%s
", ret);
    system("pause");
}

14.在字符串s1中查找串s2最右(最后)出现的位置,并返回一个指向该位置的指针。

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

char *my_strrstr(char const *str, char *const sub)
{
    register char *last = NULL;
    register char *current = NULL;

    if (*sub != '')
    {
        current = strstr(str, sub); //查找s2在s1中第一次出现的位置
    }
    if (current == NULL) return NULL;

    while (current != NULL)
    {
        last = current;
        current = strstr(last + 1, sub);
    }
    return last;
}
main()
{
    char *str = "China is great in the Asia iniiininyy";
    char *sub = "in";
    char *p = my_strrstr(str, sub);

    if (p == NULL) printf("没有找到符合的子串哦!!");
    else
        printf("%s", p);

    system("pause");
}

15.实现C语言的memcpy函数

函数原型:void *memcpy(void *destin, void *source, unsigned n)

功能:从源source所指的内存地址的起始位置开始拷贝n个字节到目标destin所指的内存地址的起始位置中。该函数返回一个指向目标存储区destin的指针。

应用说明:如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。source和destin都不一定是数组,任意的可读写的空间均可。

memcpy按照字节来拷贝,所以可以拷贝任何数据类型,不管什么类型都是二进制数据。

void * mem_cpy(void *Dest, void *Src,int count)
{
    if (NULL == Dest || NULL == Src || count <= 0) return NULL;
    char *dest = (char *)Dest;
    char *src = (char *)Src;
    while(count--)
        *dest++ = *src++;
}

 16.字符串逆转

void invert(char *str) //字符数组逆序输出
{
    int len = strlen(str);
    for (int i = 0; i < len / 2; i++)
    {
        int tmp = str[i];
        str[i] = str[len - 1 - i];
        str[len - 1 - i] = tmp;
    }
}

 while循环

void invert_2(char *str)
{
    if (NULL == str) exit(1);//exit(0)正常退出 非0异常退出
    int len = strlen(str);
    int begin = 0;
    int end = len - 1;
    while (begin < end)
    {
        char temp = str[begin];
        str[begin] = str[end];
        str[end] = str[temp];
        ++begin;
        --end;
    }
}

指针循环

void invert_3(char *str)
{
    if (NULL == str)    exit(1);
    int len = strlen(str);
    char *pBegin = str;
    char *pEnd = str + (len - 1);
    while (pBegin < pEnd)
    {
        char temp = *pBegin;
        *pBegin = *pEnd;
        *pEnd = temp;
        pBegin++;
        pEnd--;
    }
}

17.统计substr所指子字符串在str所指字符串中出现的次数。

int fun(char * str, char * sub)
{
    int i, j, k, num = 0;
    for (i = 0; str[i] != ''; i++)
        for (j = i, k = 0; sub[k] == str[j]; k++, j++)
        {
            if (sub[k + 1] == '')
            {
                num++;
                break;
            }
        }
    return num;    
}

18.函数fun功能:将str所指字符串的正序和反序进行连接,形成一个新串放在temp数组中。

void fun(char * str, char * tmp)
{
    int size = strlen(str);
    int i;
    for (i = 0; i < size; i++) tmp[i] = str[i];
    for (i = 0; i < size; i++) tmp[size + i] = str[size - 1 - i];
    tmp[2 * size] = '';
}

19.函数fun功能:将一个表示整数的数字字符串转换为一个十进制整数。

int fun(char * str)
{
    int i = 0, flag = 1, Res = 0;
    int size = strlen(str);
    if (*str == '-')
    {
        str++;
        i++;
        flag = -1;
    }
    if (*str == '+')
    {
        str++;
        i++;
    }
    for (; i < size; i++)
    {
        Res = Res * 10 + (*str - '0');
        str++;
    }
    return Res * flag;
}

20.函数fun功能:将str所指字符串中除下标为奇数同时ASCII值为奇数的字符之外,其余所有字符都删除,串中剩余字符形成一个新串放在tmp所指的数组中。

char * fun(char * str, char * tmp)
{
    int size = strlen(str);
    int i = 0, j = 0;
    for (; i < size; i++)
    {
        if (i % 2 != 0 && str[i] % 2 != 0)
        {
            tmp[j] = str[i];
            j++;
        }
    }
    tmp[j] = '';
    return tmp;
}

21.去掉字符串中的空格

#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
char * trimSpace1(char *inbuf, char * outbuf)
{
    assert(inbuf != NULL); 
    assert(outbuf != NULL);
    while (*inbuf != '')
    {
        while (*inbuf != '' && *inbuf != ' ')
        {
            *outbuf = *inbuf;
            inbuf++;
            outbuf++;
        }
        inbuf++;
    }
    *outbuf = '';
    return outbuf;
}

char * trimSpace2(char *inbuf, char * outbuf)
{
    assert(inbuf != NULL); 
    assert(outbuf != NULL);
    while (*inbuf++ != '')
    {
        if (*inbuf == ' ') continue;
        else
        {
            *outbuf = *inbuf;
            outbuf++;
        }
    }
    return outbuf;
}
int main(void)
{
    char *str = "        X - B_  o   m b  s!  ";
    char *tmp = (char *)malloc(sizeof(char *) * 1024);
    trimSpace1(str, tmp);
    printf("%s
", tmp);

    system("pause");
}

22.删除字符串中的某个字符,保留源字符串,把删除后的字符串存入一个新的字符串中。

char *fun(char *str, char *buf,char ch)
{
    char *p = str;
    int i = 0;
    while (*p != '')
    {
        if (*p != ch)
        {
            buf[i] = *p;
            i++;
        }
        p++;
    }
    return buf;
}

23.将字符串插到某个位置。

#define  _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *fun(char *strSrc, char *strFind, char *insert)
{
    char *pstr = strstr(strSrc, strFind);
    int size = strlen(strFind);
    if (pstr == NULL) printf("Null Not Find");
    else
    {
        char tmp[48];
        strcpy(tmp, pstr + size);//strFind 后的字符串全部拷贝在tmp里
        *(pstr + size) = '';//放弃后面的字符串
        strcat(strSrc, insert);
        strcat(strSrc, tmp);
    }
    return strSrc;
}
int main(void)
{
    char *allStr = { "Shenzhen is in Guangdong" };
    char *findStr = "Shenzhen";
    char *insertStr = " And NanShan";
    
    char *pstr = fun(allStr, findStr, insertStr);
    printf("%s", pstr);

    system("pause");
}

24.函数fun的功能是:将形参s所指字符串中的所有字母字符顺序前移,其他字符顺序后移处理后新字符串的首地址作为函数值返回

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char * fun(char * str)
{
    int size = strlen(str) + 1;
    char AlphaBuf[28] = { 0 }; // = (char *)malloc(size * sizeof(char));
    char  OtherBuf[28] = { 0 };// = (char *)malloc(size * sizeof(char));
    int i = 0, j = 0, k = 0;
    for (i = 0; i < size; i++)
    {
        if ((str[i] >= 'a') && (str[i] <= 'z') || (str[i] >= 'A') && (str[i] <= 'Z'))
        {
            AlphaBuf[j] = str[i];
            j++;
        }
        else
        {
            OtherBuf[k] = str[i];
            k++;
        }
    }
    for (i = 0; i < k; i++)
    {
        AlphaBuf[j + i] = OtherBuf[i]; //合并
    }
    AlphaBuf[j + k] = '';
    strcpy(str, AlphaBuf);
    return str;
}
void main()
{
    char str[100];
    printf("Please input string: ");
    scanf("%s", str);
    printf("
The result is:%s
", fun(str));

    system("pause");
}

 25.两头堵模型  求非空格字符长度

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include <ctype.h>
int main(void)
{
    char *string = "      1A2B3C4D5E       ";

    int i = 0;
    int j = strlen(string) - 1;
    while (isspace(string[i]) && string[i] != '') ++i;
    while (isspace(string[j]) && string[j] != '') --j;
    int ncount = j - i + 1;
    printf("%d
", ncount);

    system("pause");
}

26.squeeze函数:将字符串s中删除字符c

#include<stdio.h>
#include<stdlib.h>
void squeeze(char *s, unsigned char ch)
{
    int i, j;
    for (i = 0, j = 0; s[i]!=''; i++)
    {
        if (s[i] != ch)
            s[j++] = s[i];
    }
    s[j] = '';
}

void main()
{
    char p[] = "Hello World!!!";
    char ch = getchar();
    squeeze(p, ch);
    puts(p);

    system("pause");
}
此处不能用char *p="resource" 是字符串常量对于 char *str = "resource";
把"resource"的值----也就是字符串常量字面值,也就是"resource"的地址,准确来说是起始地址----赋给字符指针str,Linux下,"resource"字符串常量是存放于
只读数据区的,对只读区的数据进行写操作是禁止,具体由相应的操作系统进行判断以及处理。

而对于 char str[] = "resource";str[]是一个字符数组,编译器首先在栈中分配一定的连续空间用于存放“resource”中的字符以及结尾符,
然后把字符串常量的内容,也就是"resource"中的各个字符和结尾符复制到这个栈中的连续空间中。str是数组名,用来表示这个连续栈空间的起始地址,
所以str中存放的是栈地址,这个地址的数据是可写的。

而对于char* str = new char[12];由于重新分配了内存,然后将常量字符串内容拷贝过来,这样str指向的不是只读数据区,也就可以修改了。

但是要注意的是,下面的代码也是不行的:

    char* p = new char[12];
    printf("%p
", p);
    p = "resource";
    printf("%p", p);
  p[6] = 'k'; //报错
或许通过这个例子大家可以更容易的理解这个问题,在编译器调试状态下,可以很容易地看到,刚分配完内存的p的地址与给p赋值后的地址明显不同
所以经过后一个赋值语句后,p又重新指向了只读内存区,所以又不能修改了!

 27.字符串中字符反向排列

void reverse_string(char *str) {
    char *end_character;
    for (end_character = str; *end_character != ''; end_character++);
    end_character--;//让end_character设置为指向字符串的最后一个字符

    while (str < end_character) { //交换str和end_character指向的字符
        char tmp;
        tmp = *str;
        *str++ = *end_character;
        *end_character-- = tmp;
    }
}
原文地址:https://www.cnblogs.com/Yang-Xin-Yi/p/13362147.html