【问题标题】:VB6 - converting string to double using specific culture?VB6 - 使用特定文化将字符串转换为双精度?
【发布时间】:2019-12-30 14:09:19
【问题描述】:

我是一名长期的 C# 开发人员,最近不得不查看一些 VB6 代码。经过一番挖掘,我们发现在某个地方,不知何故,我们将一个数字存储为一个字符串。现在我们正在阅读它,我们的代码并没有很好地处理文化差异。这是一个例子:

Dim text as String
Dim myVal as Double
Set text = "1,123456"
'This sets the value of myVal to 1123456 on our system - incorrect
myVal = text

Set text = "1.123456"
'This sets the value of myVal to 1.123456 on our system - correct
myVal = text

请记住,这是 VB6 而不是 VB.NET,是否有任何内置方法、函数等可以使用特定文化将字符串转换为双精度值? 或者至少,暗示我们可能正在处理不同格式的转换?

我们仍在挖掘值是如何写入的,看看我们是否可以对流程进行逆向工程,从而为我们提供一致的结果。但是,我们的客户已经拥有(拥有)一种格式或另一种格式的数据(或两者都有,我们正在检查......),因此此时适当的转换算法或实现将是一个更好的答案。

【问题讨论】:

  • 您将需要一些有关数字来自何处的上下文,才能知道如何转换它。对于一个非常简单的方法,您可以将 , 替换为 .并将其传递给Val()。当然,如果你得到 12,345.67,那你就完蛋了。

标签: vb6 localization type-conversion


【解决方案1】:

我过去曾使用过这种快速而肮脏的功能来从文本中获取双精度。在阿根廷,人们有时使用点,有时使用逗号来分隔十进制值,所以这个函数准备好接受这两种格式。如果只有一个标点符号,则假定它是小数分隔符。

function ConvertDBL( texto )
    dim retval, SepDecimal, SepMiles
    If texto = "" then texto = "0"
    retval = replace(trim(texto), " ", "")
    If cdbl("3,24") = 324 then
        SepDecimal = "."
        SepMiles = ","
    else
        SepDecimal = ","
        SepMiles = "."
    end if  
    If InStr( Retval, SepDecimal ) > 0 then
        If InStr( Retval, SepMiles ) > 0 then
            If InStr( Retval, SepDecimal ) > InStr( Retval, SepMiles ) then
                Retval = replace( Retval, SepMiles, "" )
            else
                Retval = replace( Retval, SepDecimal, "" )
                Retval = replace( Retval, SepMiles, SepDecimal )
            end if
        end if      
    else
        Retval = replace( Retval, SepMiles, SepDecimal )
    end if
    ConvertDbl = cdbl( retval ) 
end function

【讨论】:

  • 感谢您的回复。虽然我可能不会按原样使用它,但您尝试转换“3,24”以检测您所在文化的检测机制真是天才!穆哈斯·格拉西亚斯!
【解决方案2】:

您不能像在 .Net 中那样通过传递文化对象来选择任意文化。您可以选择:

  • 始终使用当前区域设置的函数。 CStrFormatCDbl 等。隐式转换(如您问题中的转换)也使用当前的区域设置。
  • 始终使用美国区域设置的函数(类似于 .Net 不变区域性)。 Str, Val

当前的区域设置通常来自控制面板。有rumours,您可以调用SetThreadLocale 来在运行时从代码中更改区域设置——我自己从未尝试过。

【讨论】:

  • 感谢您提供更多信息。我们知道这些限制。然而,由于某种原因,数据最终以不同的格式进入我们客户的数据库。我们确实知道有些用户更喜欢使用 en-US 作为他们的文化,即使他们不在美国。因此,基本上,我们需要能够在 VB6 中将“1,2345”或“1.2345”解析为 1.2345d。是的,我们知道在某些文化中,这两种符号意味着完全不同的东西。但在我们的特殊情况下,我们相当有信心只有十进制数字存储在数据库中。感谢您的意见。
  • 尝试检测格式然后进行相应处理?像这样的东西? bDot = (Instr(test, ".")>0) bComma=(Instr(test,",")>0) If bDot And bComma Then Err.Raise vbObjectError+512, "unable to process value with dot and comma" If bComma Then test = Replace(test, ",", ".") End If value = Val(test)
  • 你是对的。我们可以使用 Eduardo 的代码处理大多数情况。棘手的情况是 1,234,你不能假设它是 1.234。在使用“,”作为数字分组的文化中,它可能是 1234。我们想了解不一致的数据是如何进入数据库的,以便我们可以更有根据地猜测我们是否应该假设 1,234 总是意味着 1.234,或者我们有案例可能意味着 1234。感谢您的帮助。
【解决方案3】:

在 Visual Basic 中测试的工作非常快速和高效。

第 1 步:从字符串转换为值表示。

第 2 步:从值表示形式转换为双整数值。

Dim Str as String
Dim mValue as double
str = "100,10"

mValue = CDbl(Val(str))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多