How to define and assign values to a string array in .header

Hello,

I am trying to declare an Array in .header file and trying to assign values to an Array in .cpp file. But its not working.

I am trying to do is:

ABC.h
#include <iostream.h>

class headerFile {

public:
static const char name [];
};

ABC.cpp

#include “ABC.h”

void ABC()
{
const char headerFile::name[];
char *nameList[20];
TSystemFile file;
int count = 0;
TIter next(files);
while ( (file = (TSystemFile
)next()) ) {
fname = file->GetName();
nameList[0] = fname;
while (nameList[count] != NULL)
{
nameList[count] = fname;
count++;
headerFile::name[count] = nameList[count]; //Basically I want to store nameList in an name Array which I am defining in .header file.
}
for (int j=0;j<count;j++)
{
printf ("—%s\n", headerFile::name[j]);
}
}
}

Please guide me.

You have created an array of const chars (and array of e.g. ‘a’, ‘b’, …) and want to store C strings of type const char* (e.g. “some_name”) in its components. That doesn’t work since the array elements can only hold single characters, not strings.

You should really use the C++ string class which is much simpler to use. Also, instead of using a fixed-size array you should use a vector which can grow to the needed size. Otherwise you might try to write entries beyond the end of the array. It also makes extra (boring) bookkeeping necessary.

Also, don’t include iostream.h, but iostream.

[code]
//ABC.h //////////////////////////////
#include
#include

class headerFile {
public:
static std::vectorstd::string name; // initial size is zero
};

//ABC.cpp//////////////////////////////
#include “ABC.h”
#include

void ABC()
{
std::vectorstd::string headerFile::name;
TSystemFile file;
TIter next(files);
while ( (file = (TSystemFile
)next()) ) {
// Append the current file’s name to the static list of names.
// file->GetName() returns a const char* which is used to construct a
// std::string with std::string(const char*).
headerFile::name.push_back(file->GetName());

// iterate over list, size is known at runtime
for (unsigned i=0; i<headerFile::name.size(); i++) {
  printf ("---%s\n", headerFile::name[i]);
}

}
}[/code]

Hello,

Thank you for the guidance. But its not working. I am getting an error which states:vector<string,allocator >() no default constructor.

The code I posted didn’t contain “states”, probably “std”. Nevertheless, it had some errors which I fixed below.

#include <string>
#include <vector>
#include <string>
class headerFile {
  public:
    static std::vector<std::string> name; // initial size is zero
};

#include <iostream>
#include <TSystemFile.h>
#include <TCollection.h>
#include <TObjArray.h>
void ABC()
{
  TObjArray* files = NULL;   // needs to be properly initialized
  TSystemFile *file = NULL;  // needs to be properly initialized
  TIter next(files);
  while ( (file = (TSystemFile*)next()) ) {
    headerFile::name.push_back(file->GetName());

    for (unsigned i=0; i<headerFile::name.size(); i++) {
      printf ("---%s\n", headerFile::name[i].c_str()); // use std::c_str to convert a std::string to a const char* for printf
    }
  }
}

Thanks. But still not working. When I tries to run ABC.cpp file via a root, root is automatically getting closed. My whole programm is as follows:

//.cpp file
void ABC()
{
const char *dirname = “C:/xyz”;
char *suffix = “.data”;
char *prefix = “Test_one”;

TString pwd(gSystem->pwd()); //Get a current directory
TSystemDirectory dir(dirname, dirname); //TSystemDirectory dir(directoy name, Path);
TList *files = dir.GetListOfFiles(); //Displays a list of all files
gSystem->cd(pwd.Data());

if (files) {
TSystemFile *file; //TSystemFile class is internally used by the TBrowser to represent files.
TString fname;
TIter next(files);

Int_t count = 0;
    
while ( (file = (TSystemFile*)next()) ) {  //Iterating over a loop
  fname = file->GetName();
  if ( !(file->IsDirectory()) &&
       (!prefix || !(*prefix) || fname.BeginsWith(prefix)) &&
       (!suffix || !(*suffix) || fname.EndsWith(suffix)) ) {
    cout << fname.Data() << endl;

headerFile::name.push_back(file->GetName());
        
    for (unsigned i=0; i<headerFile::name.size(); i++) {
        printf ("---%s\n", headerFile::name[i].c_str());
    }    
     	
  }
 }
}

}

Thanks a lot. It works if we remove “static” from std::vectorstd::string name.

A little more info than doesn’t work would be helpful, my crystal ball is broken.

But the code is at least valid C++ (after changing the char* to const char*). Are you sure dir.GetListOfFiles() returns something? The constructor arguments you give it look funny, but I have no experience using it, much less so under Windows. Running the macro in the interpreter should at least give you a line number so you know where to look for errors.

EDIT

OK, our edits crossed. Wrt removing static and it working, I have to say I have no idea what you are trying to do anymore.

[code]// … ABC.hxx …

#include
#include

class headerFile {
public:
static std::vectorstd::string fileName; // static member declaration
};[/code] [code]// … ABC.cxx …

#include “TSystem.h”
#include “TSystemFile.h”
#include “TSystemDirectory.h”
#include “TList.h”
#include “TString.h”

#include
#include

#include “ABC.hxx”

std::vectorstd::string headerFile::fileName; // static member definition

void ABC()
{
const char *dirname = “C:/xyz”;
const char *suffix = “.data”;
const char *prefix = “Test_one”;

TString pwd(gSystem->pwd()); //Get a current directory
TSystemDirectory dir(dirname, dirname); //TSystemDirectory dir(directoy name, Path);
TList *files = dir.GetListOfFiles(); //Displays a list of all files
gSystem->cd(pwd.Data()); // bug fix for ROOT prior to 5.34

if (files) {
TSystemFile *file; //TSystemFile class is internally used by the TBrowser to represent files.
TString fname;
TIter next(files);

while ( (file = (TSystemFile*)next()) ) { //Iterating over a loop
  fname = file->GetName();
  if ( !(file->IsDirectory()) &&
       (!prefix || !(*prefix) || fname.BeginsWith(prefix)) &&
       (!suffix || !(*suffix) || fname.EndsWith(suffix)) ) {
    std::cout << fname << std::endl;
    headerFile::fileName.push_back(fname.Data());
  }
} // while ...

} // if (files) …

delete files; // no longer needed

for (unsigned i = 0; i < headerFile::fileName.size(); i++) {
printf ("— %s\n", headerFile::fileName[i].c_str());
} // for …
} // ABC …[/code]

Hello,

Using vectors a string is getting store in the form of Stack. But if I want to use concatination function of strings then its not working. Because, every time when it reads valu from a stack its appending a particular string.

My code:

ABC.c

#include “TSystem.h”
#include “TSystemFile.h”
#include “TSystemDirectory.h”
#include “TList.h”
#include “TString.h”
#include <TCollection.h>
#include
#include “ABC.h”
#include <string.h>

FILE *fp;
char namefile[100] = “abc_def_123”;

void pTHead()
{
ABC hf; //Header file

const char *dirname = “C:/testFile”;
char *suffix = “.data”;
char *prefix = “abc_def”;

strcat(namefile, suffix);

TString pwd(gSystem->pwd()); //Get a current directory
TSystemDirectory dir(dirname, dirname); //TSystemDirectory dir(directoy name, Path);
TList *files = dir.GetListOfFiles(); //Displays a list of all files
gSystem->cd(pwd.Data());

if (files) {
TSystemFile *file; //TSystemFile class is internally used by the TBrowser to represent files.
TString fname;
TIter next(files);

Int_t count = 0;
    
while ( (file = (TSystemFile*)next()) ) {  //Iterating over a loop
  fname = file->GetName();
  if ( !(file->IsDirectory()) &&
       (!prefix || !(*prefix) || fname.BeginsWith(prefix)) &&
       (!suffix || !(*suffix) || fname.EndsWith(suffix)) ) {
    cout << fname.Data() << endl;

hf.fileName.push_back(file->GetName());
   for (unsigned i=0; i<hf.fileName.size(); i++) {
          printf ("---%s\n", hf.fileName[i].c_str()); 
           // This will list all the files which are starting with a prefix = "abc_def"; 
           // abc_def_456.data  
           // abc_def_123.data

             //Comparison works
     /* if(strcmp(namefile,hf.fileName[i].c_str()) == 0)  //If match with abc_def_123.data found then //ONLY do append operation for only 1 time. But its appending as many times as "hf.fileName.size()" if //match is found.
            {	      
	   printf("\nMatch found for a file = %s\n",hf.fileName[i].c_str());
	    
	    strcat(dirname, "/");
            strcat(dirname,hf.fileName[i].c_str());
	     
	      printf("FULL PATH = %s\n",dirname);   //BUT here we are getting C:/testFile/abc_def_123.data/abc_def_123.data
		 
	    fp = fopen(dirname, "r"); // To open a file using we need a exact PATH e.g: C:/testFile    /abc_def_123.data
         } */
        }    
   }
 }
}

}

Is anything wrong in code? Or Have some way to De-Concatenate a string?
Please guide.

Thank you.

Hi,

you do realize that you are appending to the same dirname variable in the loop? If you want to create a unique dirname for each file you need to use a fresh dirname for each loop iteration, e.g. by moving the dirname declaration inside the loop.

Since ROOT has decent support for C++ I would suggest you to stay away from C-strings (const char*) and use std::strings instead (or TString if that make you feel better). That could make your code simpler and help you avoid issues like that in the first place.

[url]Open files in a directory with a for loop

Hello,

What I am trying to do is … When a respective match for a fileName is found, I want to append a dirName to it. And The repective full path then used by fp to Open that file from that path. I don’t want to append dirName to all the files in the vector list.

[quote=“Pree”]Hello,

What I am trying to do is … When a respective match for a fileName is found, I want to append a dirName to it. And The repective full path then used by fp to Open that file from that path. I don’t want to append dirName to all the files in the vector list.[/quote]

Just as a recommendation …

If you like C-strings so much, you’d better read any book about C-programming language, about memory management, about pointers, about string literals, about C-strings and how they must be programmed in C.

But I would recommend you (as it was already done here) to use either std::string, or TString.
Otherwise - you make the same mistakes again and again in every post and you seem to ignore advices, for example, in your latest code excerpt you have …

const char *dirname = “C:/testFile”;

and several lines later …

strcat(dirname, “/”);
strcat(dirname,hf.fileName[i].c_str());

I’d say, this is the typical example why you should not use C-strings, if you do not understand them (sure, another problem is that CINT does not see an error here).

[quote=“tpochep”]If you like C-strings so much, you’d better read any book about C-programming language, about memory management, about pointers, about string literals, about C-strings and how they must be programmed in C.

But I would recommend you (as it was already done here) to use either std::string, or TString.[/quote] Actually, the [url=https://root-forum.cern.ch/t/open-files-in-a-directory-with-a-for-loop/12471/17 link[/url] that I gave in my previous post here (to [url=https://root-forum.cern.ch/t/open-files-in-a-directory-with-a-for-loop/12471/17 post of mine[/url] in another topic on this forum) contains a “selection” of several references to materials which deal exactly with these problems. :mrgreen:

Yes, but you see, still

const char *dirname = “C:/testFile”;

strcat(dirname, “/”);
strcat(dirname,hf.fileName[i].c_str());

so it looks like your hints were ignored :frowning:

:slight_smile:

Well, note that I gave [url=https://root-forum.cern.ch/t/open-files-in-a-directory-with-a-for-loop/12471/17 web link[/url] RIGHT AFTER I saw this particularly hair-raising piece of source code (I mean the same that you mention, too). :wink: