标题:分享:截取字N长度的字符串
只看楼主
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:190
帖 子:3125
专家分:8340
注 册:2015-3-25
得分:0 
以下是引用kiff在2017-2-25 11:36:31的发言:

Str1 = "12345人发可个方和方经品他三方登山泛水多福多寿辅导费对方012345678901nLen1-1456789"
nLen1=32
?SUBSTRC(LEFT(str1,nLen1),1)
还可以这样的。
你的是遇到取的最后1位是双字节的第1位时,舍去。
4楼是遇到取的最后1位是双字节的第1位时,取多1位。

把你的和4楼的整合起来,就可以选择最后1为是舍去还是保留了。或者用7楼
整合后如下:
CLEAR


Str1 = "123456人发可个方和方经品他三方登山泛水多福多寿辅导费对方012345678901nLen1-1456789"
nLen1=31

? CutStr(str1,nLen1,0)
? CutStr(str1,nLen1,1)
? _CutStr(str1,nLen1,0)
? _CutStr(str1,nLen1,1)

*!* ======================================
*!* 先计算最后1位是双字节的第1位还是第2位
*!* 根据选择是舍弃还是保留最后1位的双字节
*!* ======================================
FUNCTION CutStr(cStr1,nLen1,nAdd)
LOCAL N1,cStr2

*!* 强行将参数值转换为字符串,并去掉字符串右边的空格
cStr1 = RTRIM(TRANSFORM(cStr1))

*!* 长度参数错误或者大于字符串长度,取字符串最大长度
N1 = LEN(cStr1)
nLen1 = IIF(TYPE("nLen1") # "N",N1,IIF(nLen1>N1,N1,nLen1))

*!* 截取的最后一个字符是半个双字节时,是舍去还是保留
nAdd = IIF(TYPE("nAdd") # "N",0,IIF(nAdd = 1,1,0))

if N1 > nLen1
   LOCAL i,nCount
   nCount = 0
   *!* 计算字符是双字节还是单字节,是第1位还是第2位
   FOR i=1 TO nLen1
       IF ISLEADBYTE(SUBSTR(cStr1,i,1)) = .T. &&判断双字节时计数 +1
          nCount = nCount + 1
       ENDIF
   ENDFOR

   IF ISLEADBYTE(SUBSTR(cStr1,i,1)) = .T. &&判断是不是双字节
      IF MOD(nCount,2)=0 &&判断是否双字节的第2位
         cStr2=SUBSTR(cStr1,1,nLen1)
      ELSE
         cStr2=IIF(nAdd = 0,SUBSTR(cStr1,1,nLen1-1),SUBSTR(cStr1,1,nLen1+1))
      ENDIF
   ELSE  
      cStr2=SUBSTR(cStr1,1,nLen1)
   ENDIF
ELSE
   cStr2 = cStr1   
ENDIF

RETURN cStr2
ENDFUNC

*!  ========================================================
*!* 利用4楼和10方法整合后,可以选择舍去还是保留最后1位双字节
*!  ========================================================
FUNCTION _CutStr(cStr1,nLen1,nAdd)
  LOCAL nCount,N1

  *!* 强行将参数值转换为字符串,并去掉字符串右边的空格
  cStr1 = RTRIM(TRANSFORM(cStr1))

  *!* 长度参数错误或者大于字符串长度,取字符串最大长度
  N1 = LEN(cStr1)
  nLen1 = IIF(TYPE("nLen1") # "N",N1,IIF(nLen1>N1,N1,nLen1))

  *!* 截取的最后一个字符是半个双字节时,是舍去还是保留
  nAdd = IIF(TYPE("nAdd") # "N",0,IIF(nAdd = 1,1,0))

  IF nAdd = 0
     RETURN SUBSTRC(LEFT(cStr1,nLen1),1)
  ELSE
     nCount = 0
     DO WHILE nCount < nLen1
        nCount = nCount + IIF(ISLEADBYTE(SUBSTR(cStr1,nCount+1,1)), 2, 1)
     ENDDO
     RETURN LEFT(cStr1,nCount)
  ENDIF
  
ENDFUNC

[此贴子已经被作者于2017-2-25 12:16编辑过]

2017-02-25 11:46
kiff
Rank: 11Rank: 11Rank: 11Rank: 11
来 自:广州
等 级:贵宾
威 望:46
帖 子:756
专家分:2531
注 册:2013-1-30
得分:0 
以下是引用mywisdom88在2017-2-25 11:46:33的发言:

还可以这样的。
你的是遇到取的最后1位是双字节的第1位时,舍去。
4楼是遇到取的最后1位是双字节的第1位时,取多1位。

把你的和4楼的整合起来,就可以选择最后1为是舍去还是保留了。或者用7楼


活用就可以了
Str1 = "12345人发可个方和方经品他三方登山泛水多福多寿辅导费对方012345678901nLen1-1456789"
nLen1=32
?SUBSTRC(LEFT(str1,nLen1),1)  &遇到取的最后1位是双字节的第1位时,舍去.
?LEFT(str1,2*nLen1-LEN(SUBSTRC(LEFT(str1,nLen1),1)))  &&遇到取的最后1位是双字节的第1位时,取多1位.

[此贴子已经被作者于2017-2-25 12:39编辑过]

2017-02-25 12:17
wengjl
Rank: 14Rank: 14Rank: 14Rank: 14
等 级:贵宾
威 望:108
帖 子:2175
专家分:3785
注 册:2007-4-27
得分:0 
看高手论道真是一种享受。谢谢!

只求每天有一丁点儿的进步就可以了
2017-02-27 10:16
厨师王德榜
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:183
帖 子:942
专家分:4724
注 册:2013-2-16
得分:0 
这个问题当年曾困扰我很久,如何避免取出的是乱码?真的伤脑筋。尤其中英文混的字符串,幸好有你们。
2017-02-27 10:25
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
对于纯文本数据,就是由键盘正常编辑输入的字符(特殊输入的不算,如Ctrl+XXX或Alt+XXX等),这类纯文本数据还有规律可寻,比较好处理。对于一些字节流的数据(如二进制文件数据或网络数据),要在其中取出一段内容的文字显示而不出现“乱码”,除了逐字节分析,还有没有更简的方法?
2017-02-27 10:43
mywisdom88
Rank: 16Rank: 16Rank: 16Rank: 16
等 级:版主
威 望:190
帖 子:3125
专家分:8340
注 册:2015-3-25
得分:0 
以下是引用吹水佬在2017-2-27 10:43:43的发言:

对于纯文本数据,就是由键盘正常编辑输入的字符(特殊输入的不算,如Ctrl+XXX或Alt+XXX等),这类纯文本数据还有规律可寻,比较好处理。对于一些字节流的数据(如二进制文件数据或网络数据),要在其中取出一段内容的文字显示而不出现“乱码”,除了逐字节分析,还有没有更简的方法?

吹版,Kiff 提到的,先用 substr()或者left()取,然后再用 substrc()取,他会把第1次取的,如果最后1位是乱码的去掉的。
不知道,你说的“对于一些字节流的数据(如二进制文件数据或网络数据)”能否适应这种方法,他不用循环,速度比“逐字节分析”快很多。
2017-02-27 12:42
sdta
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
来 自:江苏省连云港市
等 级:版主
威 望:323
帖 子:9621
专家分:26174
注 册:2012-2-5
得分:0 
以下是引用mywisdom88在2017-2-27 12:42:48的发言:


吹版,Kiff 提到的,先用 substr()或者left()取,然后再用 substrc()取,他会把第1次取的,如果最后1位是乱码的去掉的。
不知道,你说的“对于一些字节流的数据(如二进制文件数据或网络数据)”能否适应这种方法,他不用循环,速度比“逐字节分析”快很多。

如果一个文本字节数达到MB级,SUBSTR()速度还是很慢的,最快的方法是fopen(),fread(),fseek()配合使用速度最快

坚守VFP最后的阵地
2017-02-27 12:50
吹水佬
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:432
帖 子:10064
专家分:41463
注 册:2014-5-20
得分:0 
回复 16楼 mywisdom88
好象这类文件数据,每行显示16个字节,左边用内码显示,右边用文本显示,非打印字符是用“.”表示,但那个“?”好象有点“乱码”了。


[此贴子已经被作者于2017-2-27 14:15编辑过]

2017-02-27 14:14
红星二锅头
Rank: 8Rank: 8
等 级:贵宾
威 望:46
帖 子:491
专家分:754
注 册:2016-8-25
得分:0 
fopen(),fread(),fseek() 有容量 (Sizes) 限制的,小于、等于 64KB,不能处理 MB 级的大小。

团队红星二锅头,队长王猛,领队李冲,顾问杨伟,副队张挺,外联马彪,内勤韩秀,人事顾闯,财务赵魁,后勤周强
2017-02-27 14:37
qingfameng
Rank: 12Rank: 12Rank: 12
等 级:贵宾
威 望:35
帖 子:964
专家分:3019
注 册:2010-2-6
得分:0 
如果吹版能给出一篇有各种字符,也有乱码的文件,我测试一下自己搞的那段代码,看看是否可行? 代码是很早时候受kiff 版主的启发,而搞得。

2017-02-27 18:48



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-474515-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.310665 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved