Sign in to follow this  

STL vector of strings

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

If you intended to correct an error in the post then please contact us.

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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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. :)

Share this post


Link to post
Share on other sites

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

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this