I am reading a program which contains the following function, which is
int ft_isalnum(int c)
{
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
|| (c >= '0' && c <= '9'));
}
I don't quite understand what does this function intend to do?
As suggested by its name, the function checks if the given character is alphanumeric.
Assuming ASCII character encoding where A-Z and a-z are stored consecutively, it checks if the character is in either the 'A' to 'Z' range, the 'a' to 'z' range, or the '0' to '9' range and returns true if any of those conditions are satisfied.
Write a program to figure it out:
#include <stdio.h>
#include <ctype.h>
int ft_isalnum(int c)
{
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9'));
}
int main(void)
{
for (int i = 0; i < 128; putchar(++i % 8 ? ' ' : '\n'))
printf("%3d '%c' %c ", i, isprint((char unsigned)i) ? i : '?', ft_isalnum(i) ? 'X' : ' ');
putchar('\n');
}
Output
0 '?' 1 '?' 2 '?' 3 '?' 4 '?' 5 '?' 6 '?' 7 '?'
8 '?' 9 '?' 10 '?' 11 '?' 12 '?' 13 '?' 14 '?' 15 '?'
16 '?' 17 '?' 18 '?' 19 '?' 20 '?' 21 '?' 22 '?' 23 '?'
24 '?' 25 '?' 26 '?' 27 '?' 28 '?' 29 '?' 30 '?' 31 '?'
32 ' ' 33 '!' 34 '"' 35 '#' 36 '$' 37 '%' 38 '&' 39 '''
40 '(' 41 ')' 42 '*' 43 '+' 44 ',' 45 '-' 46 '.' 47 '/'
48 '0' X 49 '1' X 50 '2' X 51 '3' X 52 '4' X 53 '5' X 54 '6' X 55 '7' X
56 '8' X 57 '9' X 58 ':' 59 ';' 60 '' 63 '?'
64 '#' 65 'A' X 66 'B' X 67 'C' X 68 'D' X 69 'E' X 70 'F' X 71 'G' X
72 'H' X 73 'I' X 74 'J' X 75 'K' X 76 'L' X 77 'M' X 78 'N' X 79 'O' X
80 'P' X 81 'Q' X 82 'R' X 83 'S' X 84 'T' X 85 'U' X 86 'V' X 87 'W' X
88 'X' X 89 'Y' X 90 'Z' X 91 '[' 92 '\' 93 ']' 94 '^' 95 '_'
96 '`' 97 'a' X 98 'b' X 99 'c' X 100 'd' X 101 'e' X 102 'f' X 103 'g' X
104 'h' X 105 'i' X 106 'j' X 107 'k' X 108 'l' X 109 'm' X 110 'n' X 111 'o' X
112 'p' X 113 'q' X 114 'r' X 115 's' X 116 't' X 117 'u' X 118 'v' X 119 'w' X
120 'x' X 121 'y' X 122 'z' X 123 '{' 124 '|' 125 '}' 126 '~' 127 '?'
The output indicates, on my machine, that characters 0 to 9 and letters A to Z and a to z return a 1 while everything else returns a 0.
Note
Not all characters are printable.
Thanks
To #Swordfish for making the output more attractive and readable.
Related
char* buf;
...
(gdb) x/s buf
0x7fffef8f5f80: "35=DC\001\064\071=ABCD\001"
(gdb) x/12cb buf
0x7fffef8f5f80: 51 '3' 53 '5' 61 '=' 65 'D' 66 'C' 1 '\001' 52 '4' 57 '9'
0x7fffef8f5f88: 61 '=' 83 'A' 80 'B' 88 'C' 84 'D' 1 '\001'
Question> How can I enable gdb to print the buf as the following:
"35=DC\00149=ABCD\001"?
Thank you
Question> How can I enable gdb to print the buf as the following:
There is no way to do this right now. You could file a gdb bug report if you like.
What is going on here is that gdb's string-printing function has a special case to escape a digit when it follows a character that was emitted as an escape sequence. That is why you see \064 and not 4.
I've been working on this problem over at the code golf exchange which is why my code looks so funny.
Here's a program with use strict and use warnings that recreates the problem:
use strict;
use warnings;
$_ = "";
for my $i (1..33){
s//1/; # Just prepends 1 to the string $_
}
print "$_\n";
for my $i (34..127) {
if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
print chr y/1/1/;
}
s/^/1/; # Prepends 1 to the start of the string.
}
Here is the output:
111111111111111111111111111111111
#$%&04689#ABDOPQRabdegopq
This works as I would expect. However, when I take ^ out of the second regex, the regex no longer matches and lengthens the string.
use strict;
use warnings;
$_ = "";
for my $i (1..33){
s//1/;
}
print "$_\n";
for my $i (34..127) {
if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
print chr y/1/1/;
}
s//1/; # No Longer matches!
}
Why does this happen? s//1/ works in the first loop, so why does changing it in the second one break everything?
For an additional point of confusion, if you put the if block in braces, the regex matches again:
for my $i (34..127) {
{
if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
print chr y/1/1/;
}
}
s//1/; # This prepends 1 to the string $_ again.
}
edit:
I wanted to edit my original code back into the question for reference:
use strict;
use warnings;
$_="";
until( y/1/1/ > 32){
print "test1";
s//1/;
print "test";
}
print "$_\n";
until( y/1/1/ > 125+1 ) {
if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
print chr y/1/1/;
}
s/^/1/; # this is the line we remove ^ from
}
When we remove ^ from the line, the output changes from:
test1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1testtest1test111111111111111111111111111111111
#$%&04689#ABDOPQRabdegopq
to
hanging with no output
So in this case, the line change in the second loop changes the behavior of the first one it seems.
s//1/; does not check for any or empty string. It checks against the last successful regex text before. So, the first loop uses default regex and the second one uses the last successful check from the if above.
Quote:
If the PATTERN evaluates to the empty string, the last successfully
matched regular expression is used instead. In this case, only the g
and c flags on the empty pattern are honored
Please, see The empty pattern //
To expand on VladimirM answer
print "regex have dynamic scope\n";
$_ = 1;
{
m/1/;
s//2/;
print "$_ one becomes two, s//2/ is really s/1/2/\n";
}
$_=1;
{
m/1/;
{
s//2/;
}
print "$_ one still becomes two, s//2/ is really s/1/2/\n";
}
$_=1;
{
{
m/1/;
}
s//2/;
print "$_ one becomes twentyone, s//2/; is really s/(?:)//2;\n";
}
__END__
regex have dynamic scope
2 one becomes two, s//2/ is really s/1/2/
2 one still becomes two, s//2/ is really s/1/2/
21 one becomes twentyone, s//2/; is really s/(?:)//2;
since regex have dynamic scope, using The empty pattern // really means using the previous pattern from same dynamic scope so don't do that :)
If you add use re 'debug'; you can see the regex engine use the previous pattern (focus on Matching REx statements, NOTHING(2) is empty without previous, EXACT <1>(3) is the previous pattern)
regex have dynamic scope
Guessing start of match in sv for REx "1" against "1"
Found anchored substr "1" at offset 0...
Guessed: match at offset 0
Guessing start of match in sv for REx "1" against "1"
Found anchored substr "1" at offset 0...
Guessed: match at offset 0
Matching REx "1" against "1"
0 <> <1> | 1:EXACT <1>(3)
1 <1> <> | 3:END(0)
Match successful!
2 one becomes two, s//2/ is really s/1/2/
Guessing start of match in sv for REx "1" against "1"
Found anchored substr "1" at offset 0...
Guessed: match at offset 0
Guessing start of match in sv for REx "1" against "1"
Found anchored substr "1" at offset 0...
Guessed: match at offset 0
Matching REx "1" against "1"
0 <> <1> | 1:EXACT <1>(3)
1 <1> <> | 3:END(0)
Match successful!
2 one still becomes two, s//2/ is really s/1/2/
Guessing start of match in sv for REx "1" against "1"
Found anchored substr "1" at offset 0...
Guessed: match at offset 0
Matching REx "" against "1"
0 <> <1> | 1:NOTHING(2)
0 <> <1> | 2:END(0)
Match successful!
21 one becomes twentyone, s//2/; is really s/(?:)//2;
update: because you have an infinite loop; last pattern always has 1 in it, so the substitution is essentially s/1/1/; which means your string doesn't grow, its always 33 chars ... see update :)
$_="";
until( y/1/1/ > 32){
print "test1";
s//1/;
print "test";
}
print "$_\n";
my $max = 126;
my $count = 0;
my $reps = 0;
until( y/1/1/ > 125+1 ) {
if( chr(y/1/1/) !~ /[!"'()*+,-.\/12357:;<=>?CEFGHIJKLMNSTUVWXYZ[\\\]^_`cfhijklmnrstuvwxyz{|}~]/ ) {
print chr y/1/1/;
}
$reps =
#~ s/^/1/; # win
s//1/; # fail
$count++;
last if $count > $max;
}
print "m $max c $count r $reps l #{[ length $_ ]}\n";
__END__
win #$%&04689#ABDOPQRabdegopqm 126 c 94 r 1 l 127
fail m 126 c 127 r 1 l 33
Unless you're obfuscating append is $_ .= 1; and prepend is $_ = 1 . $_;
To expand a second time on VladimirM's answer that the empty pattern // is the problem, the following is from perldoc:
The empty pattern //
If the PATTERN evaluates to the empty string, the last successfully matched regular expression is used instead. In this case, only the g and c flags on the empty pattern are honored; the other flags are taken from the original pattern. If no match has previously succeeded, this will (silently) act instead as a genuine empty pattern (which will always match).
Basically, if there is another regex within the same scope that matched, then the LHS of the regex with the empty pattern will actually be the LHS of the previous regex.
In the below example inspired by the OP, I expand the string using the ones digit of the incrementer instead. However, once the other regex matches chr(33) which is a exclamation point, the LHS of the empty regex will change. It will then start matching the digits 12357 and replacing them with our ones place of the incrementer. Therefore the string will stay the same length from then on.
use strict;
use warnings;
$_ = "";
for my $i (1..127) {
my $chr = chr(length);
if( $chr =~ m'(?![#$%&])[[:punct:]12357CE-NS-Zcfh-nr-z]' ) {
print "'$chr'";
} else {
print " ";
}
s//$i % 10/e;
printf "% 4d %s\n", $i, $_;
}
The following output clearly demonstrates this:
1 1
2 21
3 321
4 4321
5 54321
6 654321
7 7654321
8 87654321
9 987654321
10 0987654321
11 10987654321
12 210987654321
13 3210987654321
14 43210987654321
15 543210987654321
16 6543210987654321
17 76543210987654321
18 876543210987654321
19 9876543210987654321
20 09876543210987654321
21 109876543210987654321
22 2109876543210987654321
23 32109876543210987654321
24 432109876543210987654321
25 5432109876543210987654321
26 65432109876543210987654321
27 765432109876543210987654321
28 8765432109876543210987654321
29 98765432109876543210987654321
30 098765432109876543210987654321
31 1098765432109876543210987654321
32 21098765432109876543210987654321
33 321098765432109876543210987654321
'!' 34 421098765432109876543210987654321
'!' 35 451098765432109876543210987654321
'!' 36 461098765432109876543210987654321
'!' 37 467098765432109876543210987654321
'!' 38 468098765432109876543210987654321
'!' 39 468098965432109876543210987654321
'!' 40 468098960432109876543210987654321
'!' 41 468098960412109876543210987654321
'!' 42 468098960422109876543210987654321
'!' 43 468098960432109876543210987654321
'!' 44 468098960442109876543210987654321
'!' 45 468098960445109876543210987654321
'!' 46 468098960446109876543210987654321
'!' 47 468098960446709876543210987654321
'!' 48 468098960446809876543210987654321
'!' 49 468098960446809896543210987654321
'!' 50 468098960446809896043210987654321
'!' 51 468098960446809896041210987654321
'!' 52 468098960446809896042210987654321
'!' 53 468098960446809896043210987654321
'!' 54 468098960446809896044210987654321
'!' 55 468098960446809896044510987654321
'!' 56 468098960446809896044610987654321
'!' 57 468098960446809896044670987654321
'!' 58 468098960446809896044680987654321
'!' 59 468098960446809896044680989654321
'!' 60 468098960446809896044680989604321
'!' 61 468098960446809896044680989604121
'!' 62 468098960446809896044680989604221
'!' 63 468098960446809896044680989604321
'!' 64 468098960446809896044680989604421
'!' 65 468098960446809896044680989604451
'!' 66 468098960446809896044680989604461
'!' 67 468098960446809896044680989604467
'!' 68 468098960446809896044680989604468
'!' 69 468098960446809896044680989604468
'!' 70 468098960446809896044680989604468
'!' 71 468098960446809896044680989604468
'!' 72 468098960446809896044680989604468
'!' 73 468098960446809896044680989604468
'!' 74 468098960446809896044680989604468
'!' 75 468098960446809896044680989604468
'!' 76 468098960446809896044680989604468
'!' 77 468098960446809896044680989604468
'!' 78 468098960446809896044680989604468
'!' 79 468098960446809896044680989604468
'!' 80 468098960446809896044680989604468
'!' 81 468098960446809896044680989604468
'!' 82 468098960446809896044680989604468
'!' 83 468098960446809896044680989604468
'!' 84 468098960446809896044680989604468
'!' 85 468098960446809896044680989604468
'!' 86 468098960446809896044680989604468
'!' 87 468098960446809896044680989604468
'!' 88 468098960446809896044680989604468
'!' 89 468098960446809896044680989604468
'!' 90 468098960446809896044680989604468
'!' 91 468098960446809896044680989604468
'!' 92 468098960446809896044680989604468
'!' 93 468098960446809896044680989604468
'!' 94 468098960446809896044680989604468
'!' 95 468098960446809896044680989604468
'!' 96 468098960446809896044680989604468
'!' 97 468098960446809896044680989604468
'!' 98 468098960446809896044680989604468
'!' 99 468098960446809896044680989604468
'!' 100 468098960446809896044680989604468
'!' 101 468098960446809896044680989604468
'!' 102 468098960446809896044680989604468
'!' 103 468098960446809896044680989604468
'!' 104 468098960446809896044680989604468
'!' 105 468098960446809896044680989604468
'!' 106 468098960446809896044680989604468
'!' 107 468098960446809896044680989604468
'!' 108 468098960446809896044680989604468
'!' 109 468098960446809896044680989604468
'!' 110 468098960446809896044680989604468
'!' 111 468098960446809896044680989604468
'!' 112 468098960446809896044680989604468
'!' 113 468098960446809896044680989604468
'!' 114 468098960446809896044680989604468
'!' 115 468098960446809896044680989604468
'!' 116 468098960446809896044680989604468
'!' 117 468098960446809896044680989604468
'!' 118 468098960446809896044680989604468
'!' 119 468098960446809896044680989604468
'!' 120 468098960446809896044680989604468
'!' 121 468098960446809896044680989604468
'!' 122 468098960446809896044680989604468
'!' 123 468098960446809896044680989604468
'!' 124 468098960446809896044680989604468
'!' 125 468098960446809896044680989604468
'!' 126 468098960446809896044680989604468
'!' 127 468098960446809896044680989604468
Basically, I'm tasked with implementing Floyd's algorithm to find the shortest path of a matrix. A value, in my case, arg, is taken in and the matrix becomes size arg*arg. The next string of values are applied to the matrix in the order received. Lastly, a -1 represents infinity.
To be quite honest, I've no idea where my problem is coming in. When ran through the tests, the first couple pass, but the rest fail. I'll only post the first two failures along with the passes. I'll just post the relevant segment of code.
int arg, var, i, j;
cin >> arg;
int arr[arg][arg];
for (i = 0; i < arg; i++)
{
for(j = 0; j < arg; j++)
{
cin >> var;
arr[i][j] = var;
}
}
for(int pivot = 0; pivot < arg; pivot++)
{
for(i = 0; i < arg; i++)
{
for(j = 0; j < arg; j++)
{
if((arr[i][j] > (arr[i][pivot] + arr[pivot][j])) && ((arr[i][pivot] != -1) && arr[pivot][j] != -1))
{
arr[i][j] = (arr[i][pivot] + arr[pivot][j]);
arr[j][i] = (arr[i][pivot] + arr[pivot][j]);
}
}
}
}
And here are the failures that I'm receiving. The rest of them get longer and longer, up to a 20*20 matrix, so I'll spare you from that:
floyd>
* * * Program successfully started and correct prompt received.
floyd 2 0 14 14 0
0 14 14 0
floyd> PASS : Input "floyd 2 0 14 14 0" produced output "0 14 14 0".
floyd 3 0 85 85 85 0 26 85 26 0
0 85 85 85 0 26 85 26 0
floyd> PASS : Input "floyd 3 0 85 85 85 0 26 85 26 0" produced output "0 85 85 85 0 26 85 26 0".
floyd 3 0 34 7 34 0 -1 7 -1 0
0 34 7 34 0 -1 7 -1 0
floyd> FAIL : Input "floyd 3 0 34 7 34 0 -1 7 -1 0" did not produce output "0 34 7 34 0 41 7 41 0".
floyd 4 0 -1 27 98 -1 0 41 74 27 41 0 41 98 74 41 0
0 -1 27 68 -1 0 41 74 27 41 0 41 68 74 41 0
floyd> FAIL : Input "floyd 4 0 -1 27 98 -1 0 41 74 27 41 0 41 98 74 41 0" did not produce output "0 68 27 68 68 0 41 74 27 41 0 41 68 74 41 0".
Imagine the situation arr[i][j] == -1, obviously (arr[i][j] > (arr[i][pivot] + arr[pivot][j])) && ((arr[i][pivot] != -1) && arr[pivot][j] != -1) fails, but it shouldn’t if arr[i][pivot] and arr[pivot][j] are not -1
Since you are using -1 instead of infinity, you have to have something like if ((arr[i][j] == -1 || arr[i][j] > (arr[i][pivot] + arr[pivot][j])) && ((arr[i][pivot] != -1) && arr[pivot][j] != -1)) i.e. you check against 2 things: the first one is your condition and the 2nd one is the situation when arr[i][j] is infinity and the path through pivot exists, as in this case any valid path is less then infinity.
I have to get a string of numbers of 2 digits separated by spaces, take the numbers out somehow and do operations with them. But the values are all going wrong, see for yourselves:
...
string = "08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08"; //example
for (int i = 0; i < string.size()-2; i += 3){
arr[i] = 10 * string[i] + string[i+1];
cout << arr[i] <<' '<< 10 * string[i] <<' '<< string[i] << string[i+1] <<endl;
}
output:
536 480 08 i guess 0 times 10 isn't 480 as well as that plus 8 equals 536
530 480 02
550 500 22
625 570 97
566 510 38
543 490 15
528 480 00
568 520 40
528 480 00
603 550 75
532 480 04
533 480 05
535 480 07
606 550 78
580 530 52
540 490 12
578 530 50
605 550 77
619 570 91
536 480 08
You're doing your calculation with the ASCII values of the characters, not the numeric values of the digits. E.g. '0' is 48, '1' is 49, and so on.
for (int i = 0; i < string.size()-2; i += 3){
arr[i] = 10 * (string[i]-'0') + (string[i+1]-'0');
cout << arr[i] <<' '<< 10 * string[i] <<' '<< string[i] << string[i+1] <<endl;
}
You're misunderstanding the int values you're retrieving. Just as an example, the 08 you're pulling.
'0' is not 0, it's 48
'8' is not 8, it's 56
48 * 10 + 56 = 536
instead of taking the ASCII representation of a character and using that in your calculations, use atoi.
Also, instead of going char by char you might want to look into the many ways to split a string of text in C++.
Converting a character to an integer gives you the numeric value that represents the character; for the numeric digits, that's not the same as the value of the digit. Just about every computer you'll find these days uses ASCII coding, where '0' is represented by the value 48, '1' by 49, and so on.
You want to subtract the value that represents '0' so that '0' becomes 0, '1' becomes 1, and so on:
arr[i] = 10 * (string[i] - '0') + (string[i+1] - '0');
You could use the stoi()(string to integer) to convert your string to numerical values and then perform your operations.
I am trying to put together a little script which would track back the history of an object, by analyzing the R history. I am stuck at efficiently parsing R commands and splitting them. Consider the following R command:
for( i in 1:10 ) { a[i] <- myfunc() ; print( sprintf( "done step %d; proceeding", i ) ) }
Splitting at semicolons or curly brackets is not a problem, but what about the semicolons (or other special things) which are in quotes? I end up going char by char and keeping track of whether I am in a quote of not (and also of the backslashes...). This is footwork, and I'm sure there is something simpler, probably invented around the time Unix was born. A clever regex, maybe?
Use parse. It returns an expression which can be subsetted into the various components of the parse tree:
x <- parse(text='for( i in 1:10 ) { a[i] <- myfunc() ; print( sprintf( "done step %d; proceeding", i ) ) }',n=1)
x[[1]]
for (i in 1:10) {
a[i] <- myfunc()
print(sprintf("done step %d; proceeding", i))
}
x[[1]][[1]]
`for`
x[[1]][[4]]
{
a[i] <- myfunc()
print(sprintf("done step %d; proceeding", i))
}
x[[1]][[4]][[2]]
a[i] <- myfunc()
It depends on how much details you need, but beside the base parse function you might also check out the awesome parser package that is really fast to do its job and also returns much more details compared to parse. Quick demo:
> library(parser)
> parser(text='for( i in 1:10 ) { a[i] <- myfunc() ; print( sprintf( "done step %d; proceeding", i ) ) }')
expression(for (i in 1:10) {
a[i] <- myfunc()
print(sprintf("done step %d; proceeding", i))
})
attr(,"data")
line1 col1 byte1 line2 col2 byte2 token id parent top_level token.desc terminal text
1 1 0 0 1 3 3 270 1 77 0 FOR TRUE for
2 1 3 3 1 4 4 40 2 77 0 '(' TRUE (
3 1 5 5 1 6 6 263 4 77 0 SYMBOL TRUE i
4 1 7 7 1 9 9 271 6 77 0 IN TRUE in
5 1 10 10 1 11 11 261 8 9 0 NUM_CONST TRUE 1
6 1 10 10 1 11 11 78 9 15 0 expr FALSE
7 1 11 11 1 12 12 58 10 15 0 ':' TRUE :
8 1 12 12 1 14 14 261 11 12 0 NUM_CONST TRUE 10
9 1 12 12 1 14 14 78 12 15 0 expr FALSE
10 1 15 15 1 16 16 41 14 77 0 ')' TRUE )
11 1 10 10 1 14 14 78 15 77 0 expr FALSE
12 1 17 17 1 18 18 123 18 74 0 '{' TRUE {
13 1 19 19 1 20 20 263 20 22 0 SYMBOL TRUE a
14 1 20 20 1 21 21 91 21 28 0 '[' TRUE [
15 1 19 19 1 20 20 78 22 28 0 expr FALSE
16 1 21 21 1 22 22 263 23 25 0 SYMBOL TRUE i
17 1 22 22 1 23 23 93 24 28 0 ']' TRUE ]
18 1 21 21 1 22 22 78 25 28 0 expr FALSE
19 1 19 19 1 23 23 78 28 40 0 expr FALSE
20 1 24 24 1 26 26 265 30 40 0 LEFT_ASSIGN TRUE <-
21 1 27 27 1 33 33 297 32 34 0 SYMBOL_FUNCTION_CALL TRUE myfunc
22 1 33 33 1 34 34 40 33 37 0 '(' TRUE (
23 1 27 27 1 33 33 78 34 37 0 expr FALSE
24 1 34 34 1 35 35 41 35 37 0 ')' TRUE )
25 1 27 27 1 35 35 78 37 40 0 expr FALSE
26 1 36 36 1 37 37 59 39 74 0 ';' TRUE ;
27 1 19 19 1 35 35 78 40 74 0 expr FALSE
28 1 38 38 1 43 43 297 44 46 0 SYMBOL_FUNCTION_CALL TRUE print
29 1 43 43 1 44 44 40 45 69 0 '(' TRUE (
30 1 38 38 1 43 43 78 46 69 0 expr FALSE
31 1 45 45 1 52 52 297 48 50 0 SYMBOL_FUNCTION_CALL TRUE sprintf
32 1 52 52 1 53 53 40 49 64 0 '(' TRUE (
33 1 45 45 1 52 52 78 50 64 0 expr FALSE
34 1 54 54 1 80 80 260 52 54 0 STR_CONST TRUE "done step %d; proceeding"
35 1 80 80 1 81 81 44 53 64 0 ',' TRUE ,
36 1 54 54 1 80 80 78 54 64 0 expr FALSE
37 1 82 82 1 83 83 263 58 61 0 SYMBOL TRUE i
38 1 84 84 1 85 85 41 60 64 0 ')' TRUE )
39 1 82 82 1 83 83 78 61 64 0 expr FALSE
40 1 45 45 1 85 85 78 64 69 0 expr FALSE
41 1 86 86 1 87 87 41 66 69 0 ')' TRUE )
42 1 38 38 1 87 87 78 69 74 0 expr FALSE
43 1 89 89 1 90 90 125 71 74 0 '}' TRUE }
44 1 17 17 1 90 90 78 74 77 0 expr FALSE
45 1 0 0 1 90 90 78 77 0 0 expr FALSE