Storing a null terminating string in a tree and retrieving

I’m trying to store a list of strings in a rootfile. As TList or similar objects seem not very straight forward, I decided to use a Tree storing a null terminating string. But I fail. Maybe one could point out what my mistake is? Most probably I’ve missed something stupid. I guess that the address space for a char* must be available to the tree?! That’s why I’ve initialized

char wavename[1000];

The following lines compile (ALIC compiler) and run but do not work.

#include <TFile.h>
#include <TTree.h>
#include <iostream>
#include <map>

using namespace std;

void testmacro(){
	map<string, int> testlist;
	testlist["abc"]++;
	testlist["an other test"]++;
	//testlist["hallo1++0-K*892"]++;
	//testlist["0-2-+rho770"]++;
	//testlist["3-2+K*892.amp_vs_1-2++rho770.amp"]++;

	{
		cout << " writing the wavelist " << endl;
		TFile testfile("testfile.root", "Recreate");
		if (testfile.IsZombie()) return;
		TTree* testtree = new TTree("tree_wavelist", "wavelist");
		char wavename[1000];
		testtree->Branch("wavename", testtree, "C");
		for (map<string, int>::iterator it = testlist.begin(); it != testlist.end(); it++){
			strcpy(wavename,it->first.c_str());
			cout << " Filling " << it->first.c_str() << " as " << wavename << endl;
			testtree->Fill();
		}
		testtree->Write();
		//testfile.Write();
		testfile.Close(); // this should also delete the tree
	}
	testlist.clear();

	{
		cout << " reading the wavelist " << endl;
		TFile testfile("testfile.root", "Read");
		if (testfile.IsZombie()) return;
		TTree* testtree = (TTree*) testfile.Get("tree_wavelist");
		if (!testtree) return;
		char wavename[1000];
		testtree->SetBranchAddress("wavename", wavename);
		for (int iwave = 0; iwave < testtree->GetEntries(); iwave++){
			testtree->GetEntry(iwave);
			string wavenamestring(wavename);
			testlist[wavenamestring]++;
			cout << " retrieving " << wavename << " as " << wavenamestring << endl;
		}
		testfile.Close(); // this should also delete the tree
		cout << " done " << endl;
	}

	cout << " retrieving results " << endl;
	for (map<string, int>::iterator it = testlist.begin(); it != testlist.end(); it++){
		cout << it->first.c_str() << endl;
	}
}

Argh, I just need lunch!

testtree->Branch("wavename", testtree, "C");

goes to

testtree->Branch("wavename", wavename, "C");

Sorry for spamming but anyhow this code might be useful for somebody else.

No, still not working properly. I’m too dump.

Ok, cheating helps:

char* wavename = new char[1000];
testtree->Branch("wavename", wavename, "wavename[1000]/B");
...
delete[] wavename; // free allocated space
...
char* wavename = new char[1000];
testtree->SetBranchAddress("wavename", wavename);
...
delete[] wavename;

But somehow it should work also with the option “C”. One should check this. I guess that the algorithm is confused when finding more then one /0 terminating character due to the strcpy process to the same variable. But this is just a guess.

Cheers

Hi,

You example seems to work correctly when using: testtree->Branch("wavename", wavename, "wavename/C");(i.e. the leaf name is compulsory).

Cheers,
Philippe.

Oh, looks you’ve found my bug. Thank you!