Difference between TString and TString.Data()?

Dear Rooters

I have the following code:

TString ReplaceNonAlpha(const char *name, const char *sep)
{
   Int_t len = strlen(name);

// Test if name exists
   if (!name || (len <= 1)) return name;

// Replace non-alpha chars with sep
   TString outname = name;
   for (Int_t i=0; i<len; i++) {
      if(isalnum(outname[i]) == 0) outname.Replace(i, 1, sep, 1);
   }//for_i

   return outname;
}//ReplaceNonAlpha

void Replace(const char *name, const char *sep = "")
{
   TString type = TString(name);
   type = ReplaceNonAlpha(type.Data(), "");
cout << "type=" << type << endl;
cout << "type.Data()=" << type.Data() << endl;

   type = ReplaceNonAlpha(name, "");
cout << "type=" << type << endl;
cout << "type.Data()=" << type.Data() << endl;
}//ReplaceNonAlpha

This is the output:

root [3] Replace("Test First_Name")
type=TestFirstName
type.Data()=Test
type=TestFirstName
type.Data()=Test
root [4]

Why is the output for “type” and “type.Data()” different?
Is there an error in my function ReplaceNonAlpha()?

Best regards
Christian

Hi.

Try this:

std::cout<<“aaaa\0bbb”<<std::endl; //(1)

Is that clear?

“” is a string literal (its type is const char[1] and it contains one symbol - ‘\0’). After you replace non-alpha symbols, you got something like this:

Test\0lalala\0lululu

Data returns const char * == (1)

But there is an overloaded operator<<(ostream &, const TString &str) - its definition is in base/src/Stringio.cxx - look for details, WHY full string printed.

PS
If you need to remove non alpha, use TString::Remove(pos, number) - your cycle will require modification - because while iterating ‘len’ can change

Thank you for this explanation. Nevertheless, it worries me that I get two different results.
Maybe, the overloaded operator should be changed?

Sorrowly, TString::Remove() does not work, even when considering changing length ‘len’!
I ended up with the following code:

TString ReplaceNonAlpha(const char *name, const char *sep)
{
   Int_t len = strlen(name);

// Test if name exists
   if (!name || (len <= 1)) return name;

   TString outname = TString(name);
// Replace non-alpha chars with sep
   if (strcmp(sep, "") != 0) {
      for (Int_t i=0; i<len; i++) {
         if(isalnum(outname[i]) == 0) outname.Replace(i, 1, sep, 1);
      }//for_i
   } else {
      char *inname = new char[strlen(name) + 1];
      Int_t idx = 0;
      for (Int_t i=0; i<len; i++) {
         if(isalnum(outname[i]) != 0) inname[idx++] = outname[i];
      }//for_i
      outname = TString(inname);
      outname.Resize(idx);
      delete [] inname;
   }//if

   return outname;
}//ReplaceNonAlpha

Maybe, someone knows a more elegant solution.

Best regards
Christian

Sorrowly, TString::Remove() does not work, even when considering changing length ‘len’!

Sorry, this statement is obviously not true:)

TString remove_nonalnum(const char *src)
{
   TString res(src);
   for (Int_t i = 0, e = res.Length(); i < e;) {
      if(!isalnum(res[i]))
         res.Remove(i, 1), --e;
      else ++i;
   }
   
   return res;
}

void repl()
{
   TString test1(remove_nonalnum("Test string"));
   TString test2(remove_nonalnum("The_Second_test_string"));
   
   std::cout<<test1<<' '<<test2<<std::endl;
}

of course, this code is ugly :slight_smile: - a lot of copying (possibly) etc.

I ended up with the following code:
Maybe, someone knows a more elegant solution.

More elegant solution is (IMHO):

  1. not to mix removing and replacing.
  2. use C++ standard library which has convinient algorithms and gives you an opportunity to use predicates etc.[/code]

Hi,
Thank you for your code fragment, this is really elegant :smiley:

Best regards
Christian

Hi Christian,

Searching/Replacing strings can be done in a very compact way through
the TPRegexp class which was introduced in the production version
5.08/00 .

TPRegexp should be able to handle all Perl Regular expressions .
Extensive examples have been given in the tutorial regexp.C .

You seem to want to replace all non-alphanumerc characters by
a certain separator . The following code (replacing all non-alpha by
a “,” ) should give you some idea of the power of the regular
expression :

root [1] TString s("bla-bla-bla");
root [2] TPRegexp("\\W").Substitute(s,",","g");     
root [3] return s
(class TString)"bla,bla,bla"

Eddy

Dear Eddy

Thank you for this hint, this is of course the shortest solution.
However, I must admit that every time I have to use Perl regexps I have to relearn how to use them.
Few weeks ago I had to parse a 4GB text file, which was too complicated for me so I decided to write a
small root macro. Since Perl is written in C anyhow, why not write the parser in C :slight_smile:

P.S.: Sorrowly, regexps are as unreadable as a code can be :frowning:

Best regards
Christian

[quote]Searching/Replacing strings can be done in a very compact way through
the TPRegexp class which was introduced in the production version
5.08/00 . [/quote]

Hi, Eddy!

That’s very interesting. I’m not familiar with reg exps - can you, please, show - how to remove some symbols (our non alphanumeric) in a string?

Hi

After some playing around using the attached tutorial I got:

root [26] TString s("bla_bla-nn nn   nn+mm;bla");
root [27] TPRegexp("[\\W\\_]").Substitute(s,"","g");
root [28] return s                                  
(class TString)"blablannnnnnmmbla"

As I said, regexps are completely unreadable.

Best regards
Christian
perlretut.pdf (216 KB)