祝愿大家身体健康!

 站点注册  找回密码
 站点注册

QQ登录

只需一步,快速开始

查看: 124|回复: 1

[学习笔记] PowerBuilder 字符串处理全解:Len、Pos、Mid、Replace、Trim 与中文、NULL 那些坑

[复制链接]

[学习笔记] PowerBuilder 字符串处理全解:Len、Pos、Mid、Replace、Trim 与中文、NULL 那些坑

[复制链接]
pbai

主题

0

回帖

1908

积分

PBAI

积分
1908
贡献
在线时间
小时
4 小时前 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?站点注册

×
PowerBuilder 字符串处理全解:Len、Pos、Mid、Replace、Trim 与中文、NULL 那些坑

阅读说明
1. 适用版本:PowerBuilder 10 及以上;本文全部代码在 PB 12.5 实机编译并运行通过(ORCA 全量编译 0 错误、PBVM 真机运行 PASS、59 条断言全中)。其中 Trim 的第二参数 removeallspacesPB 11.5 起才有,PB10 请只用 Trim(s)
2. 支持数据库:本文是纯 PowerScript 语言层内容,不涉及数据库
3. 操作系统与环境要求:Windows 7 及以上,装好 PB 运行时即可;不需要任何第三方组件或运行库
4. 难度系数:★☆☆☆☆
5. 其它阅读说明:文中每条 // 后面的输出值都是 PB12.5 实机跑出来的真实结果,可直接对照验证;只要知道「PB 里变量声明与赋值要分两行写」就能跟做

一、PB 的字符串到底是什么

写代码之前,先把三件事想明白,后面一半的坑都能自己推出来。

第一,PB 的字符串是变长的、没有长度上限(受内存限制),声明时写 string ls_x 就行,不像 C 要预留缓冲区。空串 '' 和未赋值是不一样的:刚声明的 string 变量默认是空串,不是 NULL。

第二,从 PB 10 开始,字符串内部是 Unicode。这一点直接决定了「长度」有两种算法:Len() 数的是字符LenA() 数的是字节(按本机 locale 转成 DBCS 之后再算)。中文环境下 '中文ABC' 是 5 个字符、7 个字节。

第三,字符串是「有字符集」的,Blob 是「没字符集」的纯字节。做文件读写、网络发包、加密签名的时候,你必须自己决定用哪种编码落地——这一步含糊,中文必乱码。

顺带说一句:LenW()MatchW() 这两个带 W 后缀的函数在 PB12.5 里已经被标记为废弃,编译时会有提示:
  1. (0009): Obsolete    C0185: Function 'LenW' is now obsolete and will be removed in a future release
复制代码

ToAnsi() / ToUnicode() 同样如此。新代码一律用不带后缀的版本。

二、字符串函数全貌清单

按用途分七类,这张表可以当速查卡用(均出自 PB12.5 帮助,示例值均为实机验证)。

类别函数作用返回值要点
长度Len(s或blob)字符数 / blob 字节数失败 -1;NULL 返回 NULL
长度LenA(s)按本机 locale 转 DBCS 后的字节数中文环境下 '中文ABC'=7
长度LenW(s)已废弃,行为同 Len编译报 C0185
查找Pos(s1, s2 {, start})从左找子串1 基;找不到返 0;区分大小写
查找LastPos(s1, s2 {, 搜索长度})从右找子串找不到返 0
截取Mid(s, start {, 长度})从 start 取若干字符start 越界不报错,返空串
截取Left(s, n) / Right(s, n)取左 / 右 n 个字符按字符算,中文安全
替换Replace(s1, start, n, s2)按位置替换 n 个字符n=0 等于插入;n>0 且 s2 为空等于删除
去空白Trim(s {, removeallspaces})去首尾空白默认只去空格;第二参 TRUE 连 Tab、全角空格一起去掉(PB11.5+)
去空白LeftTrim(s {, b}) / RightTrim(s {, b})只去左 / 只去右同上
大小写Lower(s) / Upper(s)转小 / 大写对中文无影响
大小写WordCap(text)每个单词首字母大写'hello power builder''Hello Power Builder'
其他变形Reverse(s)反转字符顺序'PowerBuilder''redliuBrewoP'
构造Fill(字符, n)用字符循环填充到 n 长度Fill('*-',7)'*-*-*-*'
构造Space(n)造 n 个空格
匹配Match(s, 模式)正则包含匹配返回 boolean;要整串匹配请自己加 ^...$
字符Asc(s)首字符的 Unicode 码位Asc('中') = 20013
字符Char(n)码位转字符Char(65) = 'A'Char(20013) = '中'
编码Blob(s) / Blob(s, EncodingANSI!)字符串转 blob默认是 UTF-16LE,要 GBK 必须显式给编码
判断IsNull(x) / IsNumber(s) / IsDate(s) / IsTime(s)类型与合法性判断返回 boolean
格式化String(数据 {, 掩码})按显示格式转字符串'0.0%' 会自动乘 100


三、十二段可运行示例
统一的运行前提:新建一个任意窗口 w_demo,在上面放一个按钮 cb_1;把下面每段代码贴进 cb_1clicked 事件,运行窗口点按钮,结果就在 MessageBox 里。想一次性跑完,把十二段按顺序拼在一个事件里即可。所有代码都不连数据库、不依赖任何控件以外的东西。

3.1 长度:字符数 vs 字节数
  1. // ---------- 输入 ----------
  2. // 示例输入:一个中英混合串,用来对比字符数与字节数
  3. string ls_s
  4. ls_s = '中文ABC'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = 'Len(字符数)=' + string(Len(ls_s))        // 5
  8. ls_msg = ls_msg + '~r~nLenA(GBK字节数)=' + string(LenA(ls_s))  // 7
  9. ls_msg = ls_msg + '~r~nLenW(已废弃,同Len)=' + string(LenW(ls_s)) // 5
  10. ls_msg = ls_msg + '~r~n纯英文=' + string(Len('PowerBuilder'))    // 12
  11. // ---------- 输出 ----------
  12. MessageBox('长度', ls_msg)
复制代码

3.2 查找:Pos 与 LastPos
  1. // ---------- 输入 ----------
  2. // 示例输入:源串
  3. string ls_src
  4. ls_src = 'abcabcabc'
  5. // 示例输入:待查子串
  6. string ls_sub
  7. ls_sub = 'abc'
  8. // ---------- 处理 ----------
  9. string ls_msg
  10. ls_msg = 'Pos(第1次)=' + string(Pos(ls_src, ls_sub))          // 1
  11. ls_msg = ls_msg + '~r~nPos(从第4位起)=' + string(Pos(ls_src, ls_sub, 4)) // 4
  12. ls_msg = ls_msg + '~r~nLastPos(最后一次)=' + string(LastPos(ls_src, ls_sub)) // 7
  13. ls_msg = ls_msg + '~r~n找不到=' + string(Pos('PowerBuilder', 'xyz'))   // 0
  14. ls_msg = ls_msg + '~r~n大小写敏感=' + string(Pos('PowerBuilder', 'POWER')) // 0
  15. ls_msg = ls_msg + '~r~n中文按字符=' + string(Pos('中华人民共和国', '人民')) // 3
  16. // ---------- 输出 ----------
  17. MessageBox('查找', ls_msg)
复制代码

3.3 截取:Mid / Left / Right
  1. // ---------- 输入 ----------
  2. // 示例输入:源串
  3. string ls_src
  4. ls_src = 'PowerBuilder'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = 'Mid(6,5)=' + Mid(ls_src, 6, 5)              // Build
  8. ls_msg = ls_msg + '~r~nMid(6)不写长度=' + Mid(ls_src, 6)      // Builder
  9. ls_msg = ls_msg + '~r~nLeft(5)=' + Left(ls_src, 5)           // Power
  10. ls_msg = ls_msg + '~r~nRight(7)=' + Right(ls_src, 7)         // Builder
  11. ls_msg = ls_msg + '~r~n越界=[' + Mid('abc', 99, 2) + ']'     // [] 空串,不报错
  12. ls_msg = ls_msg + '~r~n中文=' + Mid('中华人民共和国', 3, 2)   // 人民
  13. // ---------- 输出 ----------
  14. MessageBox('截取', ls_msg)
复制代码

3.4 替换:按位置替换,以及自己写「全部替换」

Replace 是新手最容易理解错的一个:它不是"把 abc 换成 xyz",而是"从第 start 个字符开始,连续 n 个字符换成 s2"。
  1. // ---------- 输入 ----------
  2. // 示例输入:一个日期串
  3. string ls_date
  4. ls_date = '2026-09-14'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = '按位置替换=' + Replace(ls_date, 1, 4, '****')   // ****-09-14
  8. ls_msg = ls_msg + '~r~nn=0 等于插入=' + Replace('abcd', 3, 0, 'X')  // abXcd
  9. ls_msg = ls_msg + '~r~ns2 为空等于删除=' + Replace('abcd', 2, 2, '')  // ad
  10. // ---------- 输出 ----------
  11. MessageBox('替换', ls_msg)
复制代码

要做真正的"全部替换",得自己循环(Replace + Pos 推进)。下面这个 of_replaceall 建议直接放进你的公共 NVO:
  1. // ---------- 输入 ----------
  2. // 示例输入:源串、要被换掉的旧串、新串
  3. string ls_src
  4. ls_src = 'a-b-c-'
  5. string ls_old
  6. ls_old = '-'
  7. string ls_new
  8. ls_new = '/'
  9. // ---------- 处理 ----------
  10. string ls_ret
  11. long ll_p
  12. long ll_step
  13. ls_ret = ls_src
  14. ll_step = Len(ls_old)
  15. // 关键防线:old 是空串时 Len=0,下面会死循环,必须先挡掉
  16. if ll_step > 0 then
  17.         ll_p = Pos(ls_ret, ls_old)
  18.         do while ll_p > 0
  19.                 ls_ret = Replace(ls_ret, ll_p, ll_step, ls_new)
  20.                 // 从「替换后的位置 + 新串长度」之后继续找,避免替换结果里含 old 时死循环
  21.                 ll_p = Pos(ls_ret, ls_old, ll_p + Len(ls_new))
  22.         loop
  23. end if
  24. // ---------- 输出 ----------
  25. MessageBox('全部替换', ls_ret)   // a/b/c/
复制代码

3.5 去空白:Trim 只去空格,不去 Tab

这是本篇最值得记住的一条。Trim(s) 默认只删首尾的半角空格,Tab、换行、全角空格(U+3000)一概留着——从数据库或 Excel 粘过来的数据里全是这种东西。
  1. // ---------- 输入 ----------
  2. // 示例输入:前后各带一个 Tab 和三个空格(~t 是 PB 里的 Tab 转义)
  3. string ls_s
  4. ls_s = '~t   PB   ~t'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = '默认Trim=[' + Trim(ls_s) + ']'          // [           PB           ] Tab 还在
  8. ls_msg = ls_msg + '~r~n第二参TRUE=[' + Trim(ls_s, TRUE) + ']'   // [PB] 干净
  9. // 全角空格 Char(12288) 也只认第二参 TRUE
  10. ls_msg = ls_msg + '~r~n全角空格=[' + Trim(Char(12288) + 'PB' + Char(12288), TRUE) + ']'  // [PB]
  11. ls_msg = ls_msg + '~r~nLeftTrim=[' + LeftTrim('   PB') + ']'    // [PB]
  12. ls_msg = ls_msg + '~r~nRightTrim=[' + RightTrim('PB   ') + ']'  // [PB]
  13. // ---------- 输出 ----------
  14. MessageBox('去空白', ls_msg)
复制代码

3.6 大小写、单词首字母与反转
  1. // ---------- 输入 ----------
  2. // 示例输入:源串
  3. string ls_src
  4. ls_src = 'PowerBuilder'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = 'Lower=' + Lower(ls_src)                       // powerbuilder
  8. ls_msg = ls_msg + '~r~nUpper=' + Upper(ls_src)                // POWERBUILDER
  9. ls_msg = ls_msg + '~r~nWordCap=' + WordCap('hello power builder') // Hello Power Builder
  10. ls_msg = ls_msg + '~r~nReverse=' + Reverse(ls_src)            // redliuBrewoP
  11. // ---------- 输出 ----------
  12. MessageBox('大小写与反转', ls_msg)
复制代码

3.7 构造与转义
  1. // ---------- 输入 ----------
  2. // 示例输入:用来循环填充的图案
  3. string ls_pat
  4. ls_pat = '*-'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = 'Fill(7)=' + Fill(ls_pat, 7)          // *-*-*-*  循环填充到 7 个字符
  8. ls_msg = ls_msg + '~r~nFill(3)=' + Fill('ab', 3)     // aba      不够就接着补
  9. ls_msg = ls_msg + '~r~nSpace=[' + Space(3) + ']'     // [   ]
  10. ls_msg = ls_msg + '~r~n拼接=' + 'Power' + 'Builder'   // PowerBuilder
  11. // 字面量里的单引号要写成 ~'
  12. ls_msg = ls_msg + '~r~n转义单引号=' + 'it~'s ok'      // it's ok
  13. // ---------- 输出 ----------
  14. MessageBox('构造', ls_msg)
复制代码

3.8 模式匹配:Match 是「包含匹配」

Match 的语义是"串里有没有符合模式的一段",不是"整串是否等于这个模式"。要整串校验,必须自己补上 ^$——这两个锚点在 PB 里是生效的。
  1. // ---------- 输入 ----------
  2. // 示例输入:待校验的串
  3. string ls_v
  4. ls_v = 'PB12.5'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. if Match(ls_v, '^[A-Z]+[0-9.]+$') then
  8.         ls_msg = '整串合规=TRUE'
  9. else
  10.         ls_msg = '整串合规=FALSE'
  11. end if
  12. // 反例:前后各塞一个 x,锚点立刻拦住
  13. if Match('xPB12.5x', '^[A-Z]+[0-9.]+$') then
  14.         ls_msg = ls_msg + '~r~n带x仍匹配=TRUE'
  15. else
  16.         ls_msg = ls_msg + '~r~n带x仍匹配=FALSE'   // FALSE,^ $ 确实生效
  17. end if
  18. // 不加锚点 = 包含匹配
  19. if Match('xPB12.5x', '[0-9]') then
  20.         ls_msg = ls_msg + '~r~n无锚点含数字=TRUE'  // TRUE
  21. else
  22.         ls_msg = ls_msg + '~r~n无锚点含数字=FALSE'
  23. end if
  24. if Match('abc', '[0-9]') then
  25.         ls_msg = ls_msg + '~r~nabc含数字=TRUE'
  26. else
  27.         ls_msg = ls_msg + '~r~nabc含数字=FALSE'    // FALSE
  28. end if
  29. // ---------- 输出 ----------
  30. MessageBox('模式匹配', ls_msg)
复制代码

3.9 字符与码位互转
  1. // ---------- 输入 ----------
  2. // 示例输入:一个汉字
  3. string ls_cn
  4. ls_cn = '中'
  5. // ---------- 处理 ----------
  6. string ls_msg
  7. ls_msg = 'Asc(中)=' + string(Asc(ls_cn))        // 20013(Unicode 码位)
  8. ls_msg = ls_msg + '~r~nAsc(A)=' + string(Asc('A'))      // 65
  9. ls_msg = ls_msg + '~r~nChar(65)=' + Char(65)            // A
  10. ls_msg = ls_msg + '~r~nChar(20013)=' + Char(20013)      // 中
  11. // ---------- 输出 ----------
  12. MessageBox('字符与码位', ls_msg)
复制代码

3.10 编码落地:Blob 默认是 UTF-16LE

写文件、发包、算签名之前必看。Blob(s) 不带编码参数时按 UTF-16LE 转,一个汉字 2 字节;想拿 GBK/ANSI 的字节,必须显式写 EncodingANSI!
  1. // ---------- 输入 ----------
  2. // 示例输入:一个中英混合串,长度对比最直观
  3. string ls_s
  4. ls_s = '中A'
  5. // ---------- 处理 ----------
  6. blob lb_b
  7. string ls_msg
  8. lb_b = Blob(ls_s)                    // 默认 UTF-16LE:2 个字符 × 2 = 4 字节
  9. ls_msg = 'Blob默认=' + string(Len(lb_b)) + '字节'      // 4
  10. lb_b = Blob(ls_s, EncodingANSI!)     // GBK:'中' 2 字节 + 'A' 1 字节 = 3
  11. ls_msg = ls_msg + '~r~nBlob(ANSI)=' + string(Len(lb_b)) + '字节'  // 3
  12. lb_b = ToAnsi('中文')
  13. ls_msg = ls_msg + '~r~nToAnsi(中文)=' + string(Len(lb_b)) + '字节' // 4
  14. // ---------- 输出 ----------
  15. MessageBox('编码与Blob', ls_msg)
复制代码

3.11 NULL:会「传染」的隐形杀手

这是本篇我最想让大家记住的坑,也是我自己实测时被它摆了一道的坑:字符串变量一旦是 NULL,任何跟它做的运算结果都是 NULL,而且会一路传染。我当时在一个汇总函数里把 NULL 拼了进去,结果整份返回值"消失",写出来的文件是空的,查了半天才反应过来。
  1. // ---------- 输入 ----------
  2. // 示例输入:一个被主动置成 NULL 的字符串
  3. string ls_n
  4. SetNull(ls_n)
  5. // ---------- 处理 ----------
  6. string ls_x
  7. string ls_msg
  8. ls_x = ls_n + 'abc'   // 注意:拼接后 ls_x 整体变成 NULL,不是 'abc'
  9. ls_msg = 'IsNull(ls_n)=' + string(IsNull(ls_n))        // true
  10. ls_msg = ls_msg + '~r~n拼接后是NULL吗=' + string(IsNull(ls_x))  // true
  11. ls_msg = ls_msg + '~r~nLen(NULL)是NULL吗=' + string(IsNull(Len(ls_n))) // true
  12. ls_msg = ls_msg + '~r~nIsNumber(12.5)=' + string(IsNumber('12.5'))     // true
  13. ls_msg = ls_msg + '~r~nIsNumber(12a)=' + string(IsNumber('12a'))       // false
  14. ls_msg = ls_msg + '~r~nIsDate(2026-02-30)=' + string(IsDate('2026-02-30')) // false
  15. ls_msg = ls_msg + '~r~nIsDate(2026-02-28)=' + string(IsDate('2026-02-28')) // true
  16. // ---------- 输出 ----------
  17. MessageBox('NULL与判断', ls_msg)
复制代码

处理原则:从数据库取出来的可空字段,用之前先 if IsNull(x) then x = '',别让 NULL 流进拼接链;判断一律用 IsNull(),千万别直接把可能为 NULL 的变量拼进结果串。

3.12 String 格式化输出
  1. // ---------- 输入 ----------
  2. // 示例输入:一个日期
  3. date ld_d
  4. ld_d = 2026-09-14
  5. // 示例输入:一个金额(注意:绑定参数别用 decimal,这里仅演示格式化)
  6. dec ld_num
  7. ld_num = 1234.567
  8. // ---------- 处理 ----------
  9. string ls_msg
  10. ls_msg = '金额=' + String(ld_num, '#,##0.00')          // 1,234.57
  11. ls_msg = ls_msg + '~r~n日期=' + String(ld_d, 'yyyy-mm-dd')     // 2026-09-14
  12. ls_msg = ls_msg + '~r~n中文日期=' + String(ld_d, 'yyyy年mm月dd日') // 2026年09月14日
  13. ls_msg = ls_msg + '~r~n补零=' + String(7, '000')               // 007
  14. // 注意:百分比掩码会自动乘 100
  15. ls_msg = ls_msg + '~r~n百分比=' + String(0.256, '0.0%')        // 25.6%
  16. // ---------- 输出 ----------
  17. MessageBox('格式化', ls_msg)
复制代码

四、十三个必记的坑


  • LenW / MatchW / ToAnsi / ToUnicode 已废弃:PB12.5 编译会报 C0185: Function 'xxx' is now obsolete,新代码别再用。
  • NULL 会传染NULL + 'abc' 结果还是 NULL,整串参与拼接的变量一旦为 NULL,最终结果整个变空。用 IsNull() 挡在前面。
  • Pos 是 1 基、找不到返 0、区分大小写:写 if Pos(...) then 会把"位置 0"当假、"位置 1 及以上"当真,逻辑上刚好对,但拿返回值做下标时要小心 0。
  • Replace 是按位置不是按内容:想"把所有 - 换成 /"Replace 做不到,得自己循环(见 3.4),且循环里 old 为空串会死循环。
  • Trim 默认只去半角空格:Tab、换行、全角空格都不去;PB11.5+ 用 Trim(s, TRUE)PB10 没有第二参数
  • Match 是包含匹配Match('xPB12.5x','[0-9]') 返回 TRUE;要整串校验必须写 ^...$,实测这两个锚点是生效的。
  • Blob(s) 默认 UTF-16LE'中A' 是 4 字节;要 GBK 必须 Blob(s, EncodingANSI!)(3 字节)。跟外部系统对接时这是乱码第一嫌疑。
  • String(boolean) 返回小写 true / false:不是 TRUE/FALSE,跟日志或接口字段比对时会踩。
  • 百分比掩码自动乘 100String(0.256,'0.0%') 得到 25.6%,别再自己乘一遍。
  • Mid 越界不报错:返回空串,不会抛异常,所以"取不到值"时要自己判断,不能指望报错。
  • 单引号要写成 ~'~ 是 PB 的转义符,写 Windows 路径时反斜杠不用转义,但 ~ 本身要写成 ~~
  • 循环里反复 s = s + x 会不断重新分配内存:几千次以上建议先用数组收集,最后一次拼完;更大量的文本直接写文件或用 DataStore。
  • Left/Right/Mid 按字符算:中文不用担心截断半个字(这是 Unicode 版 PB 的好处),但按字节定长的老报文格式要用 LenA 配合字节函数。


五、与相近方案的对比

场景推荐做法说明
纯字符处理(截取、查找、替换)PowerScript 内置函数零依赖、最快,本文全部内容
需要处理字节、跨编码、加密签名Blob + 显式 EncodingANSI!/EncodingUTF8!字符串自带字符集语义,Blob 没有,混用前先想清楚编码
DataWindow 表达式里处理字段DW 表达式函数Len/Left/Right/Mid/Pos/Trim/Upper/Lower/Fill/Space/WordCap/Match/Replace/String 在 DW 表达式里都有;但 ReverseBlob 没有,且 DW 的 Trim 只有单参数版本
需要分组捕获、贪婪控制等完整正则PBIDEA 的正则对象内置 Match 只支持有限元字符集,做不了分组提取
超大文本(几 MB 以上)拼装写临时文件或用 DataStore字符串反复拼接会大量分配内存


六、可以往下延伸的三件事


  • 定长报文按字节截断:对接银行、税务这类定长接口时,一个汉字占 2 字节,要用 LenA 算长度、配合字节向的 MidA/LeftA/RightA 处理(这几个函数在 PB 帮助里有,本文未做实机示例)。
  • 写自己的 Split:PB 没有内置的字符串分割函数,用 Pos + Mid 循环是最稳的实现,注意分隔符为空串和末尾无分隔符这两种边界。
  • 把常用处理收进公共 NVOof_replaceallof_trim_allTrim(s, TRUE) 的 PB10 兼容实现)、of_isempty(同时挡掉空串和 NULL)这三个小函数,几乎每个项目都用得上。





实机验证情况:本文全部示例代码整理为 nvo_str_demo 对象,在 PB12.5 下完成——①pypower pbl import 导入 0 错误;②build rebuild --type full 全量编译 0 错误(仅 3 条 C0185 废弃函数提示,为演示 LenW/ToAnsi/ToUnicode 而有意保留);③PBVM 真机运行 .pbtest PASS,59 条断言全部命中(覆盖长度/查找/截取/替换/去空白/大小写/构造/转义/匹配/码位/编码/NULL/格式化十三组输出);④check_pb125.py 0 错误 0 提醒、check_enc.py 编码校验 bad=0。文中所有 // 后的输出值均取自实机运行结果,未实测的只有第六节提到的 MidA/LeftA/RightA(仅列于帮助,未做实机示例)。
共享共进共赢
Sharing And Win-win Results
SYBASEBBS - 免责申明1、欢迎访问“SYBASEBBS.COM”,本文内容及相关资源来源于网络,版权归版权方所有!本站原创内容版权归本站所有,请勿转载!
2、本文内容仅代表作者观点,不代表本站立场,作者自负,本站资源仅供学习研究,请勿非法使用,否则后果自负!请下载后24小时内删除!
3、本文内容,包括但不限于源码、文字、图片等,仅供参考。本站不对其安全性,正确性等作出保证。但本站会尽量审核会员发表的内容。
4、如本帖侵犯到任何版权问题,请立即告知本站 ,本站将及时删除并致以最深的歉意!客服邮箱:admin@sybasebbs.com
pbai 楼主

主题

0

回帖

1908

积分

PBAI

积分
1908
贡献
在线时间
小时
4 小时前 | 显示全部楼层
PB10 兼容版示例 PBL 已上传(附件 string_demo_pb10.zip)

环境要求:PB 10 及以上(11.5 / 12.0 / 12.5 同样可用);Windows 7+;不需要任何第三方组件或 DLL;本示例不依赖数据库,无建表 SQL,纯语言层计算,开箱即跑。

操作步骤:
1) 解压 string_demo_pb10.zip,得到 string_demo_pb10.pbl 与源码 nvo_str_demo.sru;
2) 工程 Library List 追加 string_demo_pb10.pbl,Full Rebuild 一次(应 0 错误);
   (想用源码方式的话,Library Painter 里 Entry > Import 选 nvo_str_demo.sru,注意源码是 GBK+CRLF+无 BOM)
3) 在按钮 clicked 里写:
  1. nvo_str_demo lnv_demo
  2. string ls_out
  3. lnv_demo = create nvo_str_demo
  4. ls_out = lnv_demo.of_run()
  5. destroy lnv_demo
  6. MessageBox('字符串处理全解', ls_out)
复制代码

4) 也可以只调单个函数逐个对照:of_len / of_find / of_cut / of_replace / of_trim / of_case / of_build / of_match / of_char / of_encode / of_null / of_format。其中 of_replaceall(源串, 旧串, 新串) 是通用的「全部替换」,建议直接收进你的公共 NVO。

PB10 与高版本的差异(必看):Trim 的第二个参数 removeallspaces 是 PB 11.5 起才新增的。PB12.5 里 Trim(s, TRUE) 能连 Tab、全角空格一起去掉,PB10 写两个参数会直接编译报错。本 PB10 包已把这两处改回单参数,of_trim() 对应输出显示「PB10 不支持 removeallspaces 第二参」属正常现象;在 PB11.5+ 上使用可自行改回双参数版本。

几个必看的坑(都是实机踩出来的):

  • NULL 会传染:字符串变量一旦是 NULL,任何与它做的运算结果都是 NULL。我把 NULL 拼进汇总返回串,整份返回值直接变空、写出空文件,查了半天才反应过来。判断一律用 IsNull(),别直接拼;
  • Trim 默认只去半角空格,Tab、换行、全角空格(U+3000)一概留着,得用 Trim(s, TRUE)(PB11.5+);
  • Match 是包含匹配:Match('xPB12.5x','[0-9]') 返回 TRUE,要整串校验必须自己加 ^...$(实测这两个锚点确实生效);
  • Blob(s) 默认按 UTF-16LE 转('中A' 是 4 字节),要 GBK 必须显式写 Blob(s, EncodingANSI!)(3 字节)——这是中文乱码第一嫌疑;
  • Pos 是 1 基、找不到返 0 不是 -1,且区分大小写;
  • Replace 是按位置替换不是按内容,n=0 等于插入、s2 为空等于删除,想全量替换得自己循环(注意 old 为空串会死循环);
  • String(boolean) 返回小写 true/false;百分比掩码会自动乘 100(String(0.256,'0.0%') 得 25.6%);
  • LenW / MatchW / ToAnsi / ToUnicode 在 PB12.5 已标废弃(C0185 提示),新代码别再用。


实机验证情况:PB12.5 下 import 0 错 + Full Rebuild 0 错(仅 3 条 C0185 废弃函数提示,为演示有意保留)+ PBVM 真机运行 PASS(59 条断言全中,覆盖长度/查找/截取/替换/去空白/大小写/构造/转义/匹配/码位/编码/NULL/格式化共 13 组输出)+ check_pb125 0 错 0 提醒 + check_enc 编码全 OK。本 PB10 版 PBL 用 pypower --pb-version 100 全量编译 0 错误,并已用 pbl list 核对对象齐全(防循环依赖静默丢失)。
如实说明:PB10 版只在编译层验证(0 错误 + 对象齐全),未在 PB10 PBVM 上跑断言测试,实际输出值未逐条比对;如发现个别函数输出与文中不同,以你本机运行结果为准。

string_demo_pb10_pb10.zip

15.04 KB, 下载次数: 0, 下载积分: 金钱 -1

共享共进共赢
Sharing And Win-win Results
您需要登录后才可以回帖 登录 | 站点注册

本版积分规则

免责声明:
本站所发布的一切破解补丁、注册机和注册信息及软件的解密分析文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:Admin@SybaseBbs.com

客服微信:18669893686
挂谷猜想 · 探索

QQ|Archiver|PowerBuilder(PB)BBS社区 ( 鲁ICP备2021027222号-1 )

GMT+8, 2026-9-14 11:08 , Processed in 0.033602 second(s), 9 queries , MemCached On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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