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 - 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):
- not to mix removing and replacing.
- 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
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
P.S.: Sorrowly, regexps are as unreadable as a code can be
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)