技术宅的结界

 找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 630|回复: 12
收起左侧

C语言实现像高级语言一样的字符串操作

[复制链接]

12

主题

50

帖子

386

积分

用户组: 中·技术宅

UID
2285
精华
0
威望
29 点
宅币
277 个
贡献
1 次
宅之契约
0 份
在线时间
30 小时
注册时间
2017-2-25
发表于 2019-6-21 15:45:25 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有帐号?立即注册→加入我们

x
本帖最后由 乘简 于 2019-7-12 09:45 编辑

如何用C语言操作字符串,像高级语言一样灵活的操作,字符串的长度任意变呢?答案是肯定的,而且更灵活,效率更高!

下面实现strcpy与strcat函数的结合体
[C] 纯文本查看 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MEM_ALINE 64//预留量,为了减少内存分配次数

//定义结构体,声明变量的时候必须要赋初值
//比如string str={0,0,0};
typedef struct{
    size_t memlen;//内存长度
    size_t strlen;//字符长度
    char* str;//字符串,后面有'\0'
}string;

//本模块所有的函数在变量不用时,都需要释放内存
void str_free(string *src)
{
    if(src->memlen){//如果已经申请过了内存
        src->memlen=src->strlen=0;
        free(src->str);
    }
}

//构建字符串,sour字符串在定义string t1={0,0,0};必须要初始化成0
//因为第二次要用realloc函数分配内存了
//本函数支持strcpy_free(&t1,t1.str,3);也就是说把自边往后移3位
//函数名后面加_free表示提醒程序员不要忘了用str_free函数释放内存
void strcpy_free(string *dest,char *sour,size_t start)
{
    char *src=sour;//定义新变量,用于自身复制到自身时
    size_t len=strlen(src)+1;//新字符的长度
    if(start>dest->strlen)start=dest->strlen;//如果传入的起始位置大于原来的长度
    if(len==1){//如果src="",可以直接用desc->str[xx]=0;与dest->strlen=start;来代替
        if(dest->strlen){//原来有内容
            dest->str[start]=0;
            dest->strlen=start;
        }
    }
    else{
        int isFree=0;//是否需要释放内存
        if(dest->memlen==0){//如果第1次赋值
            len+=start;//整长度加上起始位置
            dest->strlen=len-1;//字符长度
            dest->str=(char*)malloc(len);//分配内存
            dest->memlen=len;//内存长度
            strcpy(&dest->str[start],src);//复制字符串
        }
        else{
            if(src>=dest->str && src<=dest->str+start){//内存地址有重叠,可能是自身复制到自身
                src=(char*)malloc(len);//分配原来的长度
                strcpy(src,sour);//先把原来的数据复制到临时变量中
                isFree=1;//需要释放临时分配的内存
            }

            len+=start;//整长度加上起始位置
            dest->strlen=len-1;//字符长度
            if(dest->memlen<len){//内存扩容
                len+=MEM_ALINE;//多分配预留量
                dest->memlen=len;//内存长度
                dest->str=(char*)realloc(dest->str,len);//扩容内存
            }

            strcpy(&dest->str[start],src);//复制字符串
        }

        if(len+(MEM_ALINE<<1)<=dest->memlen){//如果新内存空间,比原来小2倍预留量
            dest->memlen=len+MEM_ALINE;//为了节省了内存空间,保留预留量后释放多余内存
            dest->str=(char*)realloc(dest->str,dest->memlen);
        }

        if(isFree)free(src);//释放临时分配的内存
    }
}

int main(int argc,char*argv[])
{
    string t1={0,0,0};


    //1.连接两个字符串
    strcpy_free(&t1,"Hello! My Good ",0);
    printf("%s\n",t1.str);
    strcpy_free(&t1,"Friends.~~",t1.strlen);
    printf("%s\n",t1.str);
    strcpy_free(&t1,t1.str,7);
    printf("%s\n",t1.str);
    strcpy_free(&t1,"abcd",1);
    printf("%s\n",t1.str);

    str_free(&t1);//释放内存
}


)@ERB{FQEKA$8IZJG5Y]{VB.png

评分

参与人数 1威望 +1 宅币 +8 贡献 +1 收起 理由
0xAA55 + 1 + 8 + 1 屌!

查看全部评分

17

主题

174

帖子

1250

积分

用户组: 上·技术宅

UID
3808
精华
5
威望
31 点
宅币
929 个
贡献
60 次
宅之契约
0 份
在线时间
184 小时
注册时间
2018-5-6
发表于 2019-6-22 17:44:37 | 显示全部楼层
支持楼主
菜鸟一枚,直接指正,不必留情
回复

使用道具 举报

1

主题

45

帖子

157

积分

用户组: 小·技术宅

UID
4683
精华
0
威望
0 点
宅币
112 个
贡献
0 次
宅之契约
0 份
在线时间
18 小时
注册时间
2019-2-11
发表于 2019-6-22 22:35:19 | 显示全部楼层
代码我领走了,会好好对待它的,别担心

36

主题

146

帖子

7189

积分

用户组: 管理员

UID
77
精华
11
威望
115 点
宅币
6626 个
贡献
132 次
宅之契约
0 份
在线时间
107 小时
注册时间
2014-2-22
发表于 2019-6-23 02:53:27 | 显示全部楼层
建议使用WINDOWS定义的ANSI_STRING结构体替代你自定义的结构体:
  1. typedef struct{
  2.     size_t memlen;//内存长度
  3.     size_t strlen;//字符长度
  4.     char* str;//字符串,后面有'\0'
  5. }string;

  6. typedef struct _ANSI_STRING {
  7.   USHORT Length;        //字符串长度
  8.   USHORT MaximumLength; //内存长度
  9.   PCHAR  Buffer;        //字符串指针,结尾不一定有\0,建议一律当作结尾没有\0
  10. } ANSI_STRING;
复制代码

12

主题

50

帖子

386

积分

用户组: 中·技术宅

UID
2285
精华
0
威望
29 点
宅币
277 个
贡献
1 次
宅之契约
0 份
在线时间
30 小时
注册时间
2017-2-25
 楼主| 发表于 2019-6-26 17:31:32 | 显示全部楼层
本帖最后由 乘简 于 2019-6-26 17:33 编辑
美俪女神 发表于 2019-6-23 02:53
建议使用WINDOWS定义的ANSI_STRING结构体替代你自定义的结构体:


不想名字太长,,麻烦,而且USHORT太短了,,,而且结尾没有'\0'的话,肯定要另外写一套内存结构,配套的函数,而不是string结构,这样不管是结尾还是中间,都允许有'\0',string就是结尾带'\0'的。

25

主题

108

帖子

1491

积分

用户组: 版主

UID
1821
精华
6
威望
57 点
宅币
1199 个
贡献
40 次
宅之契约
0 份
在线时间
244 小时
注册时间
2016-7-12
发表于 2019-6-26 21:32:19 | 显示全部楼层
本帖最后由 Ayala 于 2019-6-26 21:43 编辑

用字典或者字符组 这样就可以交叉引用字符串了
另外吐槽下 c语言不是高级语言么 一般来说用c语言 使用strcat的情况不算多 感觉用的最多的地方还是传递参数,索引全路径等 如果只是打印到内存 文件或者控制台这样做就有点造轮子了

12

主题

50

帖子

386

积分

用户组: 中·技术宅

UID
2285
精华
0
威望
29 点
宅币
277 个
贡献
1 次
宅之契约
0 份
在线时间
30 小时
注册时间
2017-2-25
 楼主| 发表于 2019-6-27 10:52:07 | 显示全部楼层
Ayala 发表于 2019-6-26 21:32
用字典或者字符组 这样就可以交叉引用字符串了
另外吐槽下 c语言不是高级语言么 一般来说用c语言 使用strca ...

完全不是这样的,如果你自己要用纯C写一个表格控件的话,,呵呵。。。

每个单元格中的文本,是变长的,我想,高级语言,在低层也是这样实现的吧。。。

30

主题

88

帖子

3071

积分

用户组: 管理员

UID
1043
精华
13
威望
98 点
宅币
2481 个
贡献
241 次
宅之契约
0 份
在线时间
486 小时
注册时间
2015-8-15
发表于 2019-6-27 11:12:46 | 显示全部楼层
USHORT能到65535,塞一篇小文章都够了。
此外建议UNICODE_STRING,微软有相关函数。
以wcsncat函数举例,对应有RtlAppendUnicodeStringToString。
wcsncpy就能对应RtlCopyUnicodeString。
wcsn(i)cmp对应RtlCompareUnicodeString。
这些在ntdll.dll里都导出了。
甚至还能RtlUnicodeStringPrintf,实现swnprintf的操作。
如果知道这个结构体的指针,还能用%wZ把字符串给printf出来。
所以你真的是在过度造轮。
flowers for Broken spirits - a woman turned into stake will hold the world in the basin of fire.

12

主题

50

帖子

386

积分

用户组: 中·技术宅

UID
2285
精华
0
威望
29 点
宅币
277 个
贡献
1 次
宅之契约
0 份
在线时间
30 小时
注册时间
2017-2-25
 楼主| 发表于 2019-6-27 13:16:09 | 显示全部楼层
tangptr@126.com 发表于 2019-6-27 11:12
USHORT能到65535,塞一篇小文章都够了。
此外建议UNICODE_STRING,微软有相关函数。
以wcsncat函数举例,对 ...

USHORT肯定是不够的,万一有一些奇葩的功能需要用到超过65535时,就不好了,所以一劳永逸啊。。。

还有,unicode_string其实也是可以用char *来保存的。

而且这个与ntdll.dll中的那些函数完全无关,只是想用C实现像高级语言那样的不定长字符串合并运算的功能而已。

25

主题

108

帖子

1491

积分

用户组: 版主

UID
1821
精华
6
威望
57 点
宅币
1199 个
贡献
40 次
宅之契约
0 份
在线时间
244 小时
注册时间
2016-7-12
发表于 2019-6-29 11:11:56 | 显示全部楼层
乘简 发表于 2019-6-27 10:52
完全不是这样的,如果你自己要用纯C写一个表格控件的话,,呵呵。。。

每个单元格中的文本,是变长的, ...


大多使用utf或者unicode_string格式 而且也不是所谓的不定长(有最大长度限制的) 对于长文本也不是直接储存的文本指针 大多时候是储存句柄

25

主题

108

帖子

1491

积分

用户组: 版主

UID
1821
精华
6
威望
57 点
宅币
1199 个
贡献
40 次
宅之契约
0 份
在线时间
244 小时
注册时间
2016-7-12
发表于 2019-6-29 11:17:04 | 显示全部楼层
本帖最后由 Ayala 于 2019-6-29 11:22 编辑
乘简 发表于 2019-6-27 10:52
完全不是这样的,如果你自己要用纯C写一个表格控件的话,,呵呵。。。

每个单元格中的文本,是变长的, ...


表格控件使用xml样式处理不定长要好些 文本内容基本上不需要连续 不过用c语言编程很自由 每个人都有自己的开发习惯 可能自己写的代码今天觉得好 明天自己看着都难受

点评

XML看到就烦,还不如JSON简单直接。。。  发表于 2019-7-4 16:25

1041

主题

2328

帖子

5万

积分

用户组: 管理员

一只技术宅

UID
1
精华
217
威望
288 点
宅币
18062 个
贡献
36590 次
宅之契约
0 份
在线时间
1732 小时
注册时间
2014-1-26
发表于 2019-7-30 19:01:16 | 显示全部楼层
美俪女神 发表于 2019-6-23 02:53
建议使用WINDOWS定义的ANSI_STRING结构体替代你自定义的结构体:


我觉得他的这个似乎更好,只是string这个类型名和C艹的stl的string重名了,写成库的话会让调用者骂娘。

好在访问快并且使用了标准类型。USHORT什么的在我看来是魔鬼

XML看到就烦,还不如JSON简单直接。。。


关于这个,不考虑一下NBT嘛?来和我一起解析mca文件,编写新的地图画工具吧

本版积分规则

QQ|申请友链||Archiver|手机版|小黑屋|技术宅的结界 ( 滇ICP备16008837号|网站地图

GMT+8, 2019-8-19 13:43 , Processed in 0.123715 second(s), 36 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表