in reply to Re^5: Reading into array with sscanf
in thread Reading into array with sscanf

If I do a print in the load subroutine I see the expected values from the file. But with the validation calls in the widget commented out and the actual validation subroutine also commented out the displayed value in the widget does NOT change when I do the load. even though I can use the mouse/keyboard to change it doing input to the widget. However, I've just discovered that although the *displayed* value in the Entry widget does *not* change when I do the load from file, the actual *variable* must have changed because the result of a calculation using it *does* change. Also even though I can use the mouse/keyboard to change the displayed value doing input to the widget, it isn't getting into the variable because the calculation result does not change. It's like doing the split alters the storage location of the variable array somehow and the widget doesn't get told.

Replies are listed 'Best First'.
Re^7: Reading into array with sscanf
by tybalt89 (Monsignor) on Jul 16, 2024 at 18:55 UTC

    It's the -textvariable. You made a reference to an element of an array and then changed to an entirely different array. Don't do that. It's not the scanf, it's that you used

    ($c_speed[0], $c_speed[1], $c_speed[2], $c_speed[3]) = sscanf("%d %d % +d %d", $rstring);
    If you had used
    @c_speed = sscanf("%d %d %d %d", $rstring);
    it would have also failed.

    Try
    @c_speed[0 .. $#c_speed] = split ' ', <$rstring>;
    and report back. This should keep your -textvariable reference correct.


    Or not. You didn't provide a SSCCE so it's hard to tell...

      Thanks. That does indeed work. I think I understand your comment about "You made a reference to an element of an array and then changed to an entirely different array." I think I was creating a new list with a different array inside it. Can you point me to something that explains what your suggested code means? I don't recognise what "@c_speed0 .. $#c_speed" is doing. Unless the last bit is a reference to the last element or maybe the array size, which I think would tell split how many pieces I expect.
        Another perl-minded way to do your scanf function would be
        @array[0..3] = ( $buffer =~ /^(\d+) (\d+) (\d+) (\d+)/ ) or die "Buffer didn't match pattern";
        (In list context, the regex match returns a list of the captures, which you can assign to something. If it fails to match, it returns an empty list. Putting the result of the assignment into scalar context converts to the count of list elements, which is nonzero if it matched and zero if it didn't, giving you a boolean to branch off of)

        Using the regex engine might seem like overkill for this simple case, but in most real-world problems the input has some obstacles you want to work around, and using regular expressions is way easier than dancing around with byte offsets and substr and sscanf.

        For even more advanced parsing, checkout the "\G" and "/gc" features of the regex engine, which allow you to iterate along a string without needing to split out substrings, avoiding copying the data over and over into new variables.

        It's perl's array-slice notation.
        my @array= ( 1, 2, 3, 4 ); say $#array; # 3, the max index of the array say @array[0,2] # slice of (1,3) @array[0..3]= ... # assign to first 4 elements @array[0..$#array] # assign to all existing elements