Search code examples
scriptingautoitdata-conversion

Why does my script multiply values by 30.48?


My AutoIt script has users paste text into a field, then click a button to convert the customary units into metric units. It converts not only words, but the numbers preceding them as well.

The text below is the input:

1 foot 1 inch
2 feet 2 inches
3 feet 3 inches
1 inch
2 inches
3 in
1 foot
2 feet
3 ft

This is the expected output:

33.02 centimeters
66.04 centimeters
99.06 centimeters
2.54 centimeters
5.08 centimeters
7.62 cm  
30.48 centimeters
60.96 centimeters
91.44 cm

But this is what I get:

1006.4496 centimeters
2012.8992 centimeters
3019.3488 centimeters
2.54 centimeters
5.08 centimeters
7.62 cm
30.48 centimeters
60.96 centimeters
91.44 centimeters

Seems first three lines are multiplied by 30.48. I do not want that. Here is the code:

Case $msg = $CTRL_i
    ;For unit measurements of feet and inches
    $input_str = GUICtrlRead($Textbox)
    $WordArray = StringRegExp($input_str, "[\s\.:;,]*([a-zA-Z0-9-_]*\.?[a-zA-Z0-9-_]+)[\s\.:;,]*", 3)
    ;MsgBox($MB_OK, "Size:", UBound($WordArray))
    For $i = 0 To (UBound($WordArray) - 1) Step 1
        If (($i + 3) <= UBound($WordArray)) Then
            If (StringIsDigit($WordArray[$i]) Or StringIsFloat($WordArray[$i])) And ($WordArray[$i + 1] = "feet" Or "foot" Or "ft") And (StringIsDigit($WordArray[$i + 2]) Or StringIsFloat($WordArray[$i + 2])) And ($WordArray[$i + 3] = "inches" Or "inch" Or "in") Then
                $cm_value = ($WordArray[$i] * 30.48) + ($WordArray[$i + 2] * 2.54)
                $old_string = $WordArray[$i] & " " & $WordArray[$i + 1] & " " & $WordArray[$i + 2] & " " & $WordArray[$i + 3]
                $new_string = $cm_value & " centimeters"
                $input_str = StringReplace($input_str, $old_string, $new_string, 1)
                MsgBox($MB_OK, "Feet and inches", $WordArray[$i])
            EndIf
        EndIf
    Next
    $WordArray = StringRegExp($input_str, "[\s\.:;,]*([a-zA-Z0-9-_]*\.?[a-zA-Z0-9-_]+)[\s\.:;,]*", 3)
    ;MsgBox($MB_OK, "Size:", UBound($WordArray))
    For $i = 0 To (UBound($WordArray) - 1) Step 1
        If (($i + 1) <= UBound($WordArray)) Then
            ;This is for when a measurement of inches is represented as plural.
            If (StringIsDigit($WordArray[$i]) Or StringIsFloat($WordArray[$i])) And $WordArray[$i + 1] = "inches" Then
                $cm_value = $WordArray[$i] * 2.54
                $old_string = $WordArray[$i] & " " & $WordArray[$i + 1]
                $new_string = $cm_value & " centimeters"
                $input_str = StringReplace($input_str, $old_string, $new_string, 1)
                MsgBox($MB_OK, "inches", $WordArray[$i])
                ;This is for when a measurement of inches is represented as singular.
            ElseIf (StringIsDigit($WordArray[$i]) Or StringIsFloat($WordArray[$i])) And $WordArray[$i + 1] = "inch" Then
                $cm_value = $WordArray[$i] * 2.54
                $old_string = $WordArray[$i] & " " & $WordArray[$i + 1]
                $new_string = $cm_value & " centimeters"
                $input_str = StringReplace($input_str, $old_string, $new_string, 1)
                MsgBox($MB_OK, "inch", $WordArray[$i])
                ;This is for when a measurement of inches is represented as an abbreviation.
            ElseIf (StringIsDigit($WordArray[$i]) Or StringIsFloat($WordArray[$i])) And $WordArray[$i + 1] = "in" Then
                $cm_value = $WordArray[$i] * 2.54
                $old_string = $WordArray[$i] & " " & $WordArray[$i + 1]
                $new_string = $cm_value & " cm"
                $input_str = StringReplace($input_str, $old_string, $new_string, 1)
                MsgBox($MB_OK, "in", $WordArray[$i])
            EndIf
        EndIf
    Next
    $WordArrayC = StringRegExp($input_str, "[\s\.:;,]*([a-zA-Z0-9-_]*\.?[a-zA-Z0-9-_]+)[\s\.:;,]*", 3)
    ;MsgBox($MB_OK, "Size:", UBound($WordArray))
    For $i = 0 To (UBound($WordArray) - 1) Step 1
        If (($i + 1) <= UBound($WordArray)) Then
            ;This is for when a measurement of feet is represented as plural or singular.
            If (StringIsDigit($WordArray[$i]) Or StringIsFloat($WordArray[$i])) And ($WordArray[$i + 1] = "feet" Or "foot") Then
                $cm_value = $WordArray[$i] * 30.48
                $old_string = $WordArray[$i] & " " & $WordArray[$i + 1]
                $new_string = $cm_value & " centimeters"
                $input_str = StringReplace($input_str, $old_string, $new_string, 1)
                MsgBox($MB_OK, "feet", $WordArray[$i])
                ;This is for when a measurement of feet is represented as an abbreviation.
            ElseIf (StringIsDigit($WordArray[$i]) Or StringIsFloat($WordArray[$i])) And $WordArray[$i + 1] = "ft" Then
                $cm_value = $WordArray[$i] * 30.48
                $old_string = $WordArray[$i] & " " & $WordArrayC[$i + 1]
                $new_string = $cm_value & " cm"
                $input_str = StringReplace($input_str, $old_string, $new_string, 1)
                MsgBox($MB_OK, "ft", $WordArray[$i])
            EndIf
        EndIf
    Next
    GUICtrlSetData($Textbox, $input_str)

Solution

  • This kind of syntax:

    ($WordArray[$i+1] = "feet" Or "foot" Or "ft")
    

    is actually interpreted as

    (($WordArray[$i+1] = "feet") Or ("foot") Or ("ft"))
    

    which "foot" is always True and "ft" is always True as neither are empty strings.

    Use instead this syntax:

    ($WordArray[$i+1] = "feet" Or $WordArray[$i+1] = "foot" Or $WordArray[$i+1] = "ft")
    

    The later compares $WordArray[$i+1] with each string.

    Change all instances of that kind of syntax and your code may work as expected.