Storing list of file names as a string array?

Pages: 12
Hi, I am using the following code I found to list all files with a .txt extension within a folder.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//GetFileNames Function
void getFileNames()
{
   WIN32_FIND_DATA search_data;

   memset(&search_data, 0, sizeof(WIN32_FIND_DATA));

   HANDLE handle = FindFirstFile("C:\\textfiles\\*.txt", &search_data);
  
   while(handle != INVALID_HANDLE_VALUE)
   {
      std::cout <<"Found file: " << search_data.cFileName << std::endl;
	
      if(FindNextFile(handle, &search_data) == FALSE)
         break;
	}
   
}


inside the text files folder I have text1 , text 2 , text 7 , text 9 etc all listed correctly in the console. My question is how can I store the file names in an array? I will change the function from a void to an int and I want it to grab all the filenames, store them in an array and pass them back to the main function. So the end result will have

string fileName[5000];

fileName[0] holds first file , fileName[1] next etc etc.

Cheers
Last edited on
closed account (Dy7SLyTq)
http://www.cplusplus.com/reference/vector/vector
like an array only better. and to return it alls you have to do is:
1
2
3
4
5
6
vector<string> GetFileNames()
{
     vector<string> FileList;
     //your code
     return FileList;
}
I know how to create and use a string array but the question is how can I get each file name individually from the list of all the files into the array and pass it back.

I Have not used vectors yet but I guess no better time than the present! , when I return the file list vector do I have to store that return into another vector as the file list vector is outside my main functions scope?

So given the code I posted how would I store each file name correctly? I am unsure of where I can loop to store
I second DTSCode… Vectors are much better and would work perfectly here.

If I get what you're saying here…
I Have not used vectors yet but I guess no better time than the present! , when I return the file list vector do I have to store that return into another vector as the file list vector is outside my main functions scope?

…I think there is a better solution than copying that result into yet another vector.

You could change your code to something like…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// A file to include...
#include <vector>

/* Note the new function signature...
 * We are passing in a pointer to an existing vector
 */
void getFileNames(std::vector<std::string> *fileList)
{
	WIN32_FIND_DATA search_data;
	
	memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
	
	HANDLE handle = FindFirstFile("C:\\textfiles\\*.txt", &search_data);
	
	while(handle != INVALID_HANDLE_VALUE)
	{
		std::cout <<"Found file: " << search_data.cFileName << std::endl;
		
		/* Here, you append another found file to the end of the vector.
		 * However, unlike arrays, you do NOT have to worry about resizing.
		 * The vector is resized for you!
		 */
		fileList->push_back(search_data.cFileName);
		
		if(FindNextFile(handle, &search_data) == FALSE)
			break;
	}
	
	/* Because you are passing vector as pointer to function, there is
	 * nothing to return, thus, we don't have to:
	 *   (1) write all the file names to a vector
	 *   (2) copy that vector to a new vector
	 * You'll just end up doing number 1.
	 */
}


A sample call to that function could go something like…
1
2
3
4
5
6
7
8
9
std::vector listOfFiles;
getFileNames(&listOfFiles); // <-- Using function here

std::cout << "A list of .txt files:\n";

for (std::vector<int>::iterator it = listOfFiles.begin() ; it != listOfFiles.end(); ++it)
{
	std::cout << *it << '\n' ;
}


The code I gave may not be 100% correct because I can't test it (I'm not using Windows), but you should get the idea. Yeah vectors may sound intimidating, but they're really, really useful and easier to deal with than arrays.
Last edited on
Thanks for the reply Im giving it a shot ! getting a few compiler errors through when trying to define listOfFiles for the call. I changed

std::vector listOfFiles; (red underscore error with listOfFiles)

to

std::vector <std::string> *listOfFiles;

that worked fine but

getFileNames(&listOfFiles); gives a red underscore under the &

Any suggestions? appreciate the help!
closed account (Dy7SLyTq)
could you post your code?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <Windows.h>
#include <vector>

/* Note the new function signature...
 * We are passing in a pointer to an existing vector
 */

//Prototype
void getFileNames(std::vector<std::string> *fileList);

int main()
{
	std::vector listOfFiles;
	getFileNames(&listOfFiles); // <-- Using function here

	std::cout << "A list of .txt files:\n";

	for (std::vector<int>::iterator it = listOfFiles.begin() ; it != listOfFiles.end(); ++it)
	{
		std::cout << *it << '\n' ;
	}
}

void getFileNames(std::vector<std::string> *fileList)
{
	WIN32_FIND_DATA search_data;
	
	memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
	
	HANDLE handle = FindFirstFile("C:\\textfiles\\*.txt", &search_data);
	
	while(handle != INVALID_HANDLE_VALUE)
	{
		std::cout <<"Found file: " << search_data.cFileName << std::endl;
		
		/* Here, you append another found file to the end of the vector.
		 * However, unlike arrays, you do NOT have to worry about resizing.
		 * The vector is resized for you!
		 */
		fileList->push_back(search_data.cFileName);
		
		if(FindNextFile(handle, &search_data) == FALSE)
			break;
	}
	
	/* Because you are passing vector as pointer to function, there is
	 * nothing to return, thus, we don't have to:
	 *   (1) write all the file names to a vector
	 *   (2) copy that vector to a new vector
	 * You'll just end up doing number 1.
	 */
}


Pmuch an exact copy and paste to test, line 14 is completley underscored and listOfFiles in line 15 is underscored.
closed account (Dy7SLyTq)
@line 14 you need a type for vector to hold
@ line 41 i would do fileList->push_back(std::string(search_data.cFileName));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <Windows.h>
#include <vector>

/* Note the new function signature...
 * We are passing in a pointer to an existing vector
 */

//Prototype
void getFileNames(std::vector<std::string> *fileList);

int main()
{
std::vector <std::string> listOfFiles;
getFileNames(&listOfFiles); // <-- Using function here

std::cout << "A list of .txt files:\n";

for (std::vector<int>::iterator it = listOfFiles.begin() ; it != listOfFiles.end(); ++it)
{
	std::cout << *it << '\n' ;
}
}

void getFileNames(std::vector<std::string> *fileList)
{
	WIN32_FIND_DATA search_data;
	
	memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
	
	HANDLE handle = FindFirstFile("C:\\textfiles\\*.txt", &search_data);
	
	while(handle != INVALID_HANDLE_VALUE)
	{
		std::cout <<"Found file: " << search_data.cFileName << std::endl;
		
		/* Here, you append another found file to the end of the vector.
		 * However, unlike arrays, you do NOT have to worry about resizing.
		 * The vector is resized for you!
		 */
		fileList->push_back(std::string(search_data.cFileName));
		
		if(FindNextFile(handle, &search_data) == FALSE)
			break;
	}
	
	/* Because you are passing vector as pointer to function, there is
	 * nothing to return, thus, we don't have to:
	 *   (1) write all the file names to a vector
	 *   (2) copy that vector to a new vector
	 * You'll just end up doing number 1.
	 */
}


Ok I made the changes, but line 19 is giving errors on:

listOfFiles.begin() (list of files is underscored) and

it != listOfFiles.end(); ++it) the != is underscored
closed account (Dy7SLyTq)
vector::iterator not vector<int>::iterator
I knew I would forget the type for the vector somewhere!

Either change lines 14 & 15 to...

1
2
std::vector<std::string> listOfFiles; // No pointer
getFileNames(&listOfFiles);


...or…

1
2
std::vector<std::string> *listOfFiles; // Pointer
getFileNames(listOfFiles);  // Passing pointer instead of value 

Tried DTS suggestion which did not work alo tried both of your Blakek and I a still getting the same errors in line 19 but this time both underscores are under listOfFiles. If I try DTS method I get underscored under most of line 19, hmm
closed account (Dy7SLyTq)
a) i would honestly use a range based for loop
b) could you post the code and errors?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <iostream>
#include <Windows.h>
#include <vector>

/* Note the new function signature...
 * We are passing in a pointer to an existing vector
 */

//Prototype
void getFileNames(std::vector<std::string> *fileList);

int main()
{
std::vector<std::string> listOfFiles; // No pointer
getFileNames(&listOfFiles);

std::cout << "A list of .txt files:\n";

for (std::vector::iterator it = listOfFiles.begin() ; it != listOfFiles.end(); ++it)
{
	std::cout << *it << '\n' ;
}
}

void getFileNames(std::vector<std::string> *fileList)
{
	WIN32_FIND_DATA search_data;
	
	memset(&search_data, 0, sizeof(WIN32_FIND_DATA));
	
	HANDLE handle = FindFirstFile("C:\\textfiles\\*.txt", &search_data);
	
	while(handle != INVALID_HANDLE_VALUE)
	{
		std::cout <<"Found file: " << search_data.cFileName << std::endl;
		
		/* Here, you append another found file to the end of the vector.
		 * However, unlike arrays, you do NOT have to worry about resizing.
		 * The vector is resized for you!
		 */
		fileList->push_back(std::string(search_data.cFileName));
		
		if(FindNextFile(handle, &search_data) == FALSE)
			break;
	}
	
	/* Because you are passing vector as pointer to function, there is
	 * nothing to return, thus, we don't have to:
	 *   (1) write all the file names to a vector
	 *   (2) copy that vector to a new vector
	 * You'll just end up doing number 1.
	 */
}


The error is:

1>------ Build started: Project: Testing vector, Configuration: Debug Win32 ------
1> Source.cpp
1>c:\users\ben\documents\visual studio 2012\projects\programming exercises\hh project\testing vector\testing vector\source.cpp(19): error C2955: 'std::vector' : use of class template requires template argument list
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see declaration of 'std::vector'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see declaration of 'std::vector'
1> c:\program files (x86)\microsoft visual studio 11.0\vc\include\vector(655) : see declaration of 'std::vector'
1>c:\users\ben\documents\visual studio 2012\projects\programming exercises\hh project\testing vector\testing vector\source.cpp(21): warning C4552: '<<' : operator has no effect; expected operator with side-effect
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

Its not declaring the vector when I make the changes you suggested , I also tried changing it from std::vector<int>::iterator to std::vector<std::string>::iterator which didnt work either , currently using whats in the source though. Sorry it probably seems basic and dumb for me to be getting this wrong but as I said I have no experience with vectors yet.
Last edited on
closed account (Dy7SLyTq)
replace your for loop with mine

for(auto &Itr : ListOfFiles)
cout<< Itr << endl;
1
2
for(auto &Itr : listOfFiles)
cout << Itr << endl;


the first << is giving an error, mouseover shows "No operator << match these operands , operand types are std::ostream << std::string"
Last edited on
Okay, so I finally fired up a Windows machine so I could run the code being typed.

The following worked for me. However, I noticed <string> is not being included, but the program still compiles fine for me. However, you will probably need to include the file, as I am using MinGW-supplied headers with g++. You seem to be using the Microsoft supplied headers with VC++ compiler. For another example of having to include <string> in VC++ but not MinGW, see http://stackoverflow.com/a/9084404/1130172.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <iostream>
#include <Windows.h>
#include <vector>

/* Note the new function signature...
 * We are passing in a pointer to an existing vector
 */

//Prototype
void getFileNames(std::vector<std::string> *fileList);

int main()
{
	std::vector<std::string> listOfFiles; // No pointer
	getFileNames(&listOfFiles);

	std::cout << "A list of .txt files:\n";

	for (std::vector<std::string>::iterator it = listOfFiles.begin() ; it != listOfFiles.end(); ++it)
	{
		std::cout << *it << '\n' ;
	}
}

void getFileNames(std::vector<std::string> *fileList)
{
	WIN32_FIND_DATA search_data;

	memset(&search_data, 0, sizeof(WIN32_FIND_DATA));

	HANDLE handle = FindFirstFile("C:\\textfiles\\*.txt", &search_data);

	while(handle != INVALID_HANDLE_VALUE)
	{
		std::cout << "Found file: " << search_data.cFileName << std::endl;

		/* Here, you append another found file to the end of the vector.
		 * However, unlike arrays, you do NOT have to worry about resizing.
		 * The vector is resized for you!
		 */
		fileList->push_back(std::string(search_data.cFileName));

		if(FindNextFile(handle, &search_data) == FALSE)
			break;
	}

	/* Because you are passing vector as pointer to function, there is
	 * nothing to return, thus, we don't have to:
	 *   (1) write all the file names to a vector
	 *   (2) copy that vector to a new vector
	 * You'll just end up doing number 1.
	 */
}
Last edited on
Oh god! how embarrassing I forgot to include string haha , works great :D.

So thats working great, my vector has all the information stored, how would I access elements of that vector?

for example if this was a string array and it found 4 text files then the 4th would in array[3] , the first would be in array[0] and i could simple

std::cout << array[0] ;

but with a vector how do I access elements for a simple cout?
Last edited on
closed account (Dy7SLyTq)
same way. there are others but thats the most common. there is also at(I) where I is an int and it returns the corresponding element
Working perfectly , thank you both for your help ill no doubt be posting a new question in a few hours when I get stuck , cheers!
Pages: 12