• 12
• 27
• 9
• 9
• 20

STL vector of strings

This topic is 4929 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

Can anyone tell me how i would initialize a vector that would contain character arrays? How would i add these character arrays to the vector, just use push back? Any few lines of example code you could provide would be much appreciated. Thanks in advance.

Share on other sites
I wouldn't recomend it, you should use std::string instead but how about:
int main(){std::vector<char *> charvector;char stackstring[1024] = "Hello, this is a stack string";char *heapstring = new char[1024];sprintf(heapstring,"Hello, this is a heap string");charvector.push_back(stackstring);charvector.push_back(heapstring);printf("%s",charvector[0]);printf("%s",charvector[1]);charvector.clear();delete heapstring;return 0;};

That's a way to do it, though I wondt be surpriced is someone points out lots of design flaws, they would probably be right [smile]

Share on other sites
well the reason i ask this is because i am making something to search a drive for files of a specific type. When it finds a file match, it adds its name, which is a string, to the vector. Here is the code:

//#define _WIN32_WINNT 0x0501#include <windows.h>#include <string.h>#include <stdio.h>#include <iostream.h>#include <vector>std::vector<char *> charvector;int main(int argc, char *argv[]){   WIN32_FIND_DATA FindFileData;   HANDLE hFind = INVALID_HANDLE_VALUE;   char DirSpec[MAX_PATH];  // directory specification   DWORD dwError;   char* lpstrDirectory = "c:";   printf ("Target directory is %s.\n", lpstrDirectory);   strncpy (DirSpec, lpstrDirectory, strlen(lpstrDirectory)+1);   strncat (DirSpec, "\\*", 3);   hFind = FindFirstFile(DirSpec, &FindFileData);   if (hFind == INVALID_HANDLE_VALUE)    {      printf ("Invalid file handle. Error is %u\n", GetLastError());      return (-1);   }    else    {      printf ("First file name is %s\n", FindFileData.cFileName);      while (FindNextFile(hFind, &FindFileData) != 0)       {         printf ("Next file name is %s\n", FindFileData.cFileName);		 //store the found file name to the vector here		 charvector.push_back(FindFileData.cFileName);      }      dwError = GetLastError();      if (dwError == ERROR_NO_MORE_FILES)       {         FindClose(hFind);      }       else       {         printf ("FindNextFile error. Error is %u\n", dwError);         return (-1);      }   }   //just putting this print here so i can test to see if the vector is holding strings properly   printf ("charvector contains this string: %s\n", charvector[0]);   return (0);}

seems simple, right? i use push_back to add the file name to the vector every time i find a file. Here is my problem though. If i were to check all of the elements of the vector later on, they are all the same. All of them. Can anyone spot what i'm doing wrong? Run this code yourself and you'll see what i mean.

Share on other sites
You could store char* and use push_back, etc., but it would be much better to use std::strings.

Any reason you aren't using them?

Share on other sites
Oh yeah, don't use those headers, they are out of date. Take the '.h' off.

EDIT: The STL headers, that is, not windows.h.

Share on other sites
here is your code C++'ified

//#define _WIN32_WINNT 0x0501#include <windows.h>// C++ 'Must-Haves'#include <cstring>#include <cstdio>#include <iostream>// STL#include <string>#include <vector>using namespace std;vector<string> files;int main(int argc, char *argv[]){	WIN32_FIND_DATA FindFileData;	HANDLE hFind = INVALID_HANDLE_VALUE;	string DirSpec = "c:";  // directory specification	cout << "Target directory is" << DirSpec << endl;	DirSpec += string("\\*");	hFind = FindFirstFile(DirSpec.c_str(), &FindFileData);	if( hFind == INVALID_HANDLE_VALUE ) 	{		cout << "Invalid file handle. Error is " << GetLastError() << endl << flush;		return 1;	} 	else 	{		cout << "First file name is " << FindFileData.cFileName << endl;                // dont forget to include the first file		files.push_back( string(FindFileData.cFileName) );		while( FindNextFile(hFind, &FindFileData) != 0 ) 		{			cout << "Next file name is " << FindFileData.cFileName << endl;			//store the found file name to the vector here			files.push_back( string(FindFileData.cFileName) );		}		dwError = GetLastError();		if( dwError == ERROR_NO_MORE_FILES ) {			FindClose(hFind);		} 		else {			cout << "FindNextFile error. Error is " << dwError << endl << flush;			return 1;		}	}	//just putting this print here so i can test to see if the vector is holding strings properly	cout << "files vector contains this string: " << files[0] << endl;	return 0;}

Share on other sites
The reason all your data in the vector is the same, is because you keep pushing back the same pointer. After each FindNextFile(), the buffer pointed to by the 'char * cFileName' member of FindFileData contains a different filename, but it's still the same buffer, at the same location. And since it's locations that you're storing...

The solution, of course, is to make copies of the buffer as you find filenames, and push back those copies (or pointers thereto). But fixed-size buffers are probably a bad idea, and actually, all of that kind of char * manipulation is probably a bad idea, so you'd probably rather store std::strings.

Notice that std::string has a constructor which accepts a char * argument, and will (AFAIK) create a new string which no longer depends on that char *'s pointed-at data (because it makes a copy). Thus silvermace's code: make a string from the cFileName buffer, and push_back that string. Nice and clean. :)