C语言知识点(三)---字符串

字符串

字符串的基本操作

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

//一级指针的典型用法
//字符串 
//1 C语言的字符串 以零'\0'结尾的字符串
//2 在C语言中没有字符串类型  通过字符数组 来模拟字符串 
//3 字符串的内存分配  堆上 栈上 全局区 

//字符数组 初始化
int main()
{
    //1 不指定长度  C编译器会自动帮程序员 求元素的个数
    char buf1[] = {'a', 'b', 'c', 'd'};  //buf1是一个数组 不是一个以0结尾的字符串

    //2 指定长度  
    char buf2[100] = {'a', 'b', 'c', 'd'};
    //后面的buf2[4]-buf2[99] 个字节均默认填充0

    //char buf3[2] = {'a', 'b', 'c', 'd'}; 
    //如果初始化的个数大于内存的个数 编译错误

    printf("buf1: %s\n", buf1);
    printf("buf2: %s \n", buf2);
    printf("buf2[88]:%d \n", buf2[88]);


    //3 用字符串初始化 字符数组
    char buf3[] = "abcd";       //buf3 作为字符数组 有5个字节
                                //      作为字符串有 4个字节

    int len = strlen(buf3);
    printf("buf3字符的长度:%d \n", len);    //4

    //buf3 作为数组 数组是一种数据类型 本质(固定小大内存块的别名)
    int size = sizeof(buf3); //
    printf("buf3数组所占内存空间大小:%d \n", size); //5


    char buf4[128] = "abcd"; // buf
    printf("buf4[100]:%d \n", buf4[100]);//0

    return 0;
}

sizeof 和 strlen的区别

1.sizeof为一个操作符,执行sizeof的结果,在编译期间就已经确定;
strlen是一个函数,是在程序执行的时候才确定结果。
2. sizeof和strlen对于求字符串来讲,sizeof() 字符串类型的大小,
包括’\0’;strlen() 字符串的长度不包括‘\0’(数字 0 和字符‘\0’等价)。

数组法和指针法操作字符串

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

int main(void)
{
    int     i = 0;
    char    *p = NULL; 
    char    buf[128] = "abcdefg";  

    //通过[]
    for (i=0; i<strlen(buf); i++)
    {                       
        printf("%c ", buf[i]);          
    }                                       

    p = buf; //buf 代表数组首元素的地址
    //通过指针
    for (i=0; i<strlen(buf); i++)
    {                                                          
        printf("%c ", *(p+i) ) ;                            
    }                                                       

    //通过数组首元素地址 buf 来操作
    for (i=0; i<strlen(buf); i++)
    {                                   
        printf("%c ", *(buf+i) ) ;
    }                                                   

    return 0;
}
• [] 的本质 和 *p 是一样。
 buf 是一个指针,只读的常量。
 之所以buf是一个常量指针是为了释放内存的时候,保证buf所指向的内存空间安全。

练习题:

画出字符串一级指针内存四区模型

#include <stdio.h>
#include <string.h>
int main(void)
{
    char buf[20]= "aaaa";//栈里
    char buf2[] = "bbbb"; //栈里
     char *p1 = "111111"; //常量区
    char *p2 = malloc(100); //堆
    strcpy(p2, "3333");//把数据拷贝到堆里
    return 0;               
}

字符串做函数参数

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

int main(void)
{
    char a[] = "i am a student";
    char b[64];
    int  i = 0;

    for (i=0; *(a+i) != '\0'; i++)
    {
        *(b+i) = *(a+i);
    }

    //0没有copy到b的buf中.

    b[i] = '\0'; //重要

    printf("a:%s \n", a);
    printf("b:%s \n", b);

    return 0;
}

以上是拷贝一个字符串用到了数组名(也就是数组首元素地址)的偏移来完成。

项目开发常用字符串应用模型

strstr中的while和do-while模型
利用strstr标准库函数找出一个字符串中substr出现的个数。

do-while模型

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
    //strstr(str, str2)

    int ncount = 0;

    //初始化 让p指针达到查找的条件
    char *p = "11abcd111122abcd3333322abcd3333322qqq";

    do
    {
        p = strstr(p, "abcd");
        if (p != NULL)
        {
            ncount++; //
            p = p + strlen("abcd"); //指针达到下次查找的条件
        }
        else
        {
            break;
        }
    } while (*p != '\0');


    printf("ncount:%d \n", ncount);

    return 0;
}

while模型

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void)
{
    int ncount = 0;

    //初始化 让p指针达到查找的条件
    char *p = "2abcd3333322qqqabcd";

    while ( (p = strstr(p, "abcd")) != NULL )
    {
        ncount ++;
        p = p + strlen("abcd"); //让p指针达到查找的条件
        if (*p == '\0')
        {
            break;
        }
    }
    printf("ncount:%d \n", ncount);

    return 0;
}

练习:

求字符串p中 abcd出现的次数:
1 请自定义函数接口,完成上述需求
2 自定义的业务函数 和 main函数必须分开

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



void fun(char *p,int *count)
{
    int ncount = 0;
     while ( (p = strstr(p, "abcd")) != NULL )
    {
        ncount ++;
        p = p + strlen("abcd"); //让p指针达到查找的条件
        if (*p == '\0')
        {
            break;
        }
    }
     *count = ncount;



}



int main(void)
{
    int ncount = 0;
    char p[] = "2abcd3333322qqqabcd";
    fun(p,&ncount);
    printf("%d\n",ncount);
    system("pause");
    return 0;
}

两头堵模型

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

int get_count_non_space(char *str, int * count_p)
{
    int i = 0;
    int j = strlen(str)-1;
    int ncount = 0;


    if (str == NULL || count_p == NULL) {
        fprintf(stderr, "str == NULL, count_p == NULL\n");
        return -1;
    }

    while (isspace(str[i]) && str[i] != '\0')
    {
        i++;
    }

    while (isspace(str[j]) && j > i)
    {
        j--;
    }

    ncount = j-i+1;

    *count_p = ncount;

    return 0;
}

int main(void)
{
    char *p = "      abcdefg      ";

    int ret = 0;
    int ncount = 0;

    ret = get_count_non_space(p, &ncount);
    if (ret < 0) {
        fprintf(stderr, "get_count_non_space err, ret = %d\n", ret);
        return 0;
    }

    printf("ncount = %d\n", ncount);

    return 0;
}

练习:

    有一个字符串开头或结尾含有n个空格 (”   abcdefgdddd    ”),
 欲去掉前后空格,返回一个新字符串。
    要求1:请自己定义一个接口(函数),并实现功能;
    要求2:编写测试用例。
    int trimSpace(char *inbuf, char *outbuf);  
int trimSpace(char *inbuf, char *outbuf)
{
    if(inbuf==NULL)
    {
        return 0;
    }
     int i = 0;
    int j = strlen(inbuf)-1;
    int ncount = 0;


    if (inbuf == NULL ) {
        fprintf(stderr, "str == NULL, count_p == NULL\n");
        return -1;
    }

    while (isspace(inbuf[i]) && inbuf[i] != '\0')
    {
        i++;
    }

    while (isspace(inbuf[j]) && j > i)
    {
        j--;
    }

    ncount = j-i+1;
    strncpy(outbuf,inbuf+i,ncount);
    outbuf[ncount] = '\0';

    return 0;



}



int main(void)
{
    char  inbuf[30] = "   abcdefgdddd    ";
    char  outbuf[30];
    trimSpace(inbuf,outbuf);
    printf("%s",outbuf);

    system("pause");
    return 0;
}

字符串反转模型

char* inverse(char *str)
{
int length = strlen(str);
char *p1 = NULL;
char *p2 = NULL;
char tmp_ch;

if (str == NULL) {
    return NULL;
}

p1 = str;
p2 = str + length -1;

while (p1 < p2) {
    tmp_ch = *p1;
    *p1 = *p2;
    *p2 = tmp_ch;
    ++p1;
    --p2;
}

return str;

}

越界

char buf[3] = “abc”;
记得反斜杠0;

谈谈const

• const 知识点

一. const声明的变量只能被读

const int i=5;
    int j=0;
    i=j;   //非法,导致编译错误
    j=i;   //合法

二.必须初始化

const int i=5;    //合法
const int j;      //非法,导致编译错误

三.如何在另一.c源文件中引用const常量

extern const int i;         //合法
extern const int j=10;      //非法,常量不可以被再次赋值

四.可以避免不必要的内存分配

/*
由于const定义常量从汇编的角度来看,只是给出了对应的内存地址,
而不是象#define一样给出的是立即数,所以,const定义的常量在
程序运行过程中只有一份拷贝,而#define定义的常量在内存中有
若干个拷贝。
*/

五.C语言中const是一个冒牌货

const char *c;  // 是一个指向常整型数的指针
                    // (所指向的内存数据不能修改,
                    //  但是本身可以修改)
 char * const d; // 常指针(指针变量不能被修改,
                    //  但是它所指向的内存空间可以被修改)
const char * const e;// 一个指向常量整型的常指针
                         // (指针和它所指向的内存空间,
                         //  均不可以修改)

const好处

合理的利用const,
1 指针做函数参数,可以有效的提高代码可读性,减少bug;
2 清楚的分清参数的输入和输出特性





要求写一个函数实现如下功能:
功能1:把偶数位字符挑选出来,组成一个字符串1。
功能2:把奇数位字符挑选出来,组成一个字符串2。
功能3:把字符串1和字符串2,通过函数参数,传送给main,并打印。
功能4:主函数能测试通过。
int getStr1Str2(char *source, char *buf1, char *buf2);
int getStr1Str2(char *source, char *buf1, char *buf2)
{
    if(source==NULL)
    {
        return -1;
    }
    int i = 0;
    int j = 0,k = 0;
    for(i = 0;i<strlen(source);i++)
    {
        if(i%2==0)
        {
            buf1[j] = source[i];
            j++;
        }
        else
        {
            buf2[k] = source[i];
            k++;
        }

    }
    buf1[k++] = '\0';
    buf2[j++] = '\0';



    return 0;

}
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值