TString.Tokenize() HOWTO problem

Hi,

I want to read a file through tokenizing using the commands

            token.ReadLine(stream);
            TObjArray* Strings = token.Tokenize(delimiters);
            printf("%i:(%i tokens) =%s\n",i, Strings->GetEntriesFast(), token.Data());
            if(Strings->GetEntriesFast())
            {
                for(int j = 0; j< Strings->GetEntriesFast(); j++)
                {
                    TString *T = (TString*) Strings[j];
                    printf("token #%d @%x ='%s'\n",j, T,  T->Data());
                }
            }

The corresponding output

root [3] .L Mydemo.c
root [4] mydemo()
1:(2 tokens) =116.45 17243
token #0 @2629978
Error: C++ exception caught FILE:F:\root\tutorials\Mydemo.c LINE:25
(const int)19
*** Interpreter error recovered ***
root [5]

It looks like that the stream is OK, the tokenizer recognizes the two strings, but either I misinterpret something awfully or the generated string array is in error.

Could you help, please?
(win2k, 4.00/08)

Janos

A little addition:
if I try
if(Strings->GetEntriesFast())
{
TString T = (TString) Strings->First(); int j = 0;
while(T)
{
printf(“token #%d @%x =’%s’\n”,j, T, T->Data());
j++;
T = (TString*) Strings->After(T);
}
}

I receive the output

root [10] .L Mydemo.c
root [11] mydemo()
1:(2 tokens) =116.45 17243
token #0 @85e18e8
Error: Can’t call TObjArray::After(T) in current scopedemo.c LINE:30tutorials\My
Possible candidates are…
filename line:size busy function type and name (in TObjArray)
(compiled) 0:0 0 public: virtual TObject* After(TObject* obj) const;
filename line:size busy function type and name (in TSeqCollection)
(compiled) 0:0 0 public: virtual TObject* After(TObject* obj) const=0;
filename line:size busy function type and name (in TCollection)
filename line:size busy function type and name (in TObject)
Error: Symbol Strings is not defined in current scope demo.c LINE:30tutorials\My
Error: Failed to evaluate Strings->After(T)Possible candidates are…
filename line:size busy function type and name
*** Interpreter error recovered ***
root [12]

What do I wrong?

Janos

Janos,

Nobody is going to put his time into this problem without a
running demo .

Eddy

Actually I might have found part of the problem:

TString *T = (TString*) Strings[j]; Strings is a TObjArray*, so Strings[j] will give you the j-th TObjectArray in the TObjectArray-array, that Strings points to (think of “const char* arr” where arr[j] will give you the j-th character). What you want is

TString *T = (TString*) (*Strings)[j];Also, try to run your macro after calling “.O0”. The var Strings not being known in the loop might be caused by Cint’s loop optimization, which is disabled by “.O0”.
Axel.

[quote=“Axel”]Actually I might have found part of the problem:

TString *T = (TString*) Strings[j]; Strings is a TObjArray*, so Strings[j] will give you the j-th TObjectArray in the TObjectArray-array, that Strings points to (think of “const char* arr” where arr[j] will give you the j-th character). What you want is

TString *T = (TString*) (*Strings)[j];Also, try to run your macro after calling “.O0”. The var Strings not being known in the loop might be caused by Cint’s loop optimization, which is disabled by “.O0”.
Axel.[/quote]

Hi Axel,

I am not sure you are right. Like in the sample program at the end
the elements of the char* array can be reached without dereferencing,
same way should go in the attached sample program, using the attached data.

Using the demo unmodified, i.e. “#if 1”, CINT has the same opinion: the output is
root [0] .L mydemo.C
root [1] mydemo()
1=116.45
1=17243
1:(2 tokens) =116.4 17203.3
token #0 @261b6b8
Error: Can’t call TObjArray::After(T) in current scopedemo.C LINE:35tutorials\my
Possible candidates are…
filename line:size busy function type and name (in TObjArray)
(compiled) 0:0 0 public: virtual TObject* After(TObject* obj) const;
filename line:size busy function type and name (in TSeqCollection)
(compiled) 0:0 0 public: virtual TObject* After(TObject* obj) const=0;
filename line:size busy function type and name (in TCollection)
filename line:size busy function type and name (in TObject)
Error: non class,struct,union object $(*Strings) used with . or ->mo.C LINE:35de
*** Interpreter error recovered ***
root [2]

After modifying the source, i.e “#if 0”, the output is

root [3] .L mydemo.C
root [4] mydemo()
1=116.45
1=17243
1:(2 tokens) =116.4 17203.3
token #0 @262b248

i.e. the number of the tokens in the line is correctly recognized,
the address of the TString received is not wrong, and even ROOT
aborts when trying to access the TString.

Any ideas? Pleasy try them on the attachments.

Regards
Janos

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

main()
{
unsigned int k;
char hello = malloc(6);
strcpy(hello,“Hello”);
printf(“length of ‘%s’ =%i\n”,hello,strlen(hello));
for(k = 0; k<strlen(hello); k++)
{ printf("%c", hello[k]); }
printf("\n");
/
for(k = 0; k<strlen(hello); k++);
{ printf("%c", (hello)[k]); }
This results in:
C:\veghj\projects\wx\ewa\iotest.c(14) : error C2109: subscript requires array or pointer type
Error executing cl.exe.
/
}
Mydemo.C (2.6 KB)

[quote=“Eddy Offermann”]Janos,

Nobody is going to put his time into this problem without a
running demo .

Eddy[/quote]

Eddy,
you are right. I simply forgot that when I asked this for the first time,
I included my source. This time not. Now I did attach it to the reply to Axel. Unfortunately, it looks like I can attach only one file, so I post the datafile to your address :slight_smile:.

Thanks for your help in advance.

Janos

BTW: what is your experience: used to abort ROOT,
like in this simple case?

PS:
I looks like I cannot convince the GUI to attach the file I use,
even if it is the first attachment, so here goes the content of the file
"Si_1s_3000.dat". Sorry.

116.45 17243
116.4 17203.3
116.35 17121.4
116.3 17389.3
116.25 17191.6
116.2 17046.6
116.15 17141.7
116.1 17210.2
116.05 17291.7
116 17196.6
115.95 17230.6

Hi Janos,
I never claimed what you were trying to show with your char* example program. You should have just tried to change your original code accoding to what I suggested; this would have removed at least one of your problems. I’ll try to explain again what you did wrong with your original code, and why

TObjArray* Strings = token.Tokenize(delimiters); TString *T = (TString*) Strings[j];//WRONG!
will not work, with a lot of examples, so it’s hopefully easier to understand (and so people can point back to this post whenever someone’s posts contains this basic c bug again).

Suppose you had

TObjArray* StringsPtr = token.Tokenize(delimiters); TObjArray& StringsRef = *StringsPtr;
How would you access the j-th element of StringsRef? Right, with the exact same syntax:

This shows you that there is something wrong - the method (here: operator) access for TObjArray* and TObjArray& has to be different. Another example:

What does Strings[0] return? Not a TString* - but a TObjArray&! As a final example, I will show you the long version of the operator access:

TObjArray* StringsPtr = token.Tokenize(delimiters); TObjArray& StringsRef = *StringsPtr; TString *T = (TString*) StringsRef.operator[](j); // long version of StringsRef[j] TString *T = (TString*) StringsPtr->operator[](j);
The latter shows that you indeed need to de-reference the StringsPtr first (otherwise you’re calling the c-array operator[]). So the correct syntax for your code is

TObjArray* Strings = token.Tokenize(delimiters); TString *T = (TString*) (*Strings)[j];

Axel.

Hi Axel,

maybe you are right, but: could you make my demo work?

I did the change you suggested:

//-------------------
#if 1
printf(“Axel’s method\n”);
for(int j = 0; j< Strings->GetEntriesFast(); j++)
{
TString T = (TString) (*Strings)[j];
printf(“token #%d @%x =’%s’\n”,j, T, (*T).Data());
printf(“token #%d=\n%i’%s’\n”,j,(*T).Data()[0], (*T).Data());
printf(“token #%d: length =%d, token =’%s’\n”,j,(*T).Length(),(*T).Data());
}
#else
//------------------------

but the result is still

root [1] mydemo()
1=116.45
1=17243
1:(2 tokens) =116.4 17203.3
Axel’s method
token #0 @261b730

and ROOT dies…
Any more ideas?

Janos

Hi,

See attachment. There were several problems. Major one: Tokenize returns a list of TObjStrings (TStrings don’t derive from TObject and thus cannot be stored in TCollections).
Axel.
Mydemo_works.C (1.91 KB)

[quote=“Axel”]Hi,

Axel.[/quote]
Yes you are. Yesterday night I also checked the implementation
and found the TObjString. From this point it was straightforward.

Sorry and thanks for your help

Janos