GNU Forth中如何将含数字的字符串转换为整数部分
问题
我现有代码会生成字符串类型的变量,可通过以下代码输出:
out 2@ type
这些字符串可能包含如3.666、49.888这类带小数的数字。我希望将其转换为整数并置于栈顶,期望实现类似如下效果:
out 2@ convert
即得到3或49这类整数结果。
已尝试的方法
- 编写过如下字符串处理代码,但未成功:
: .$ swap over dabs compiled <# # [CHAR] . hold # # #> ;
- 使用
evaluate命令,但得到的是49888这类异常数字,而非预期的49:
out 2@ evaluate
- 查阅了
/string等字符串处理工具的文档,未找到以"."为分隔符截取子串或实现字符串到对应整数转换的方法,也未在Rosetta Code上找到相关方案。
解决方案
方法1:截取小数点前子串转换
先定位字符串中的小数点位置,截取前面的部分再转换为整数:
: convert ( addr u -- n ) 2dup [CHAR] . index \ 查找小数点位置,返回偏移量或-1 dup 0< if drop then \ 无小数点则保留原长度 >number drop \ 转换子串为整数,丢弃剩余字符计数 ;
逻辑说明:
2dup复制字符串的地址和长度到栈顶[CHAR] . index查找小数点位置,找到返回偏移量,未找到返回-1- 若未找到小数点,丢弃返回的-1,使用原字符串长度
>number将子串转为整数,栈中会返回整数和剩余字符数,用drop丢弃剩余数
方法2:浮点数中转取整
如果你的Forth支持浮点数,可以先转浮点数再取整数部分:
: convert ( addr u -- n ) s>f \ 字符串转浮点数 f>d \ 浮点数转双精度整数(自动截断小数) d>s \ 双精度转单精度整数(按需使用) ;
注意:不同Forth实现的浮点数单词可能有差异,比如部分环境用>float替代s>f。
方法3:逐字符解析终止于小数点
手动遍历字符串,累加数字直到遇到小数点或字符串结束:
: convert ( addr u -- n ) 0 \ 初始化结果为0 swap over + \ 计算字符串结束地址 do i c@ \ 获取当前字符 dup [CHAR] . = if leave then \ 遇小数点退出循环 [CHAR] 0 - \ 字符转数字值 10 * + \ 累加到结果中 loop drop \ 丢弃最后读取的字符(若为小数点) ;
逻辑说明:
- 用
do...loop遍历每个字符 - 遇到小数点立即停止解析
- 数字字符转数值后,通过
10 * +实现十进制数的累加
内容的提问来源于stack exchange,提问作者francois P
相关产品推荐
相关产品推荐

