Find in vector

Jan 6, 2012 at 10:30am
Hi all,

I've been trying to find part of a string in a vector. The problem being that I can only get it to work if I enter the entire string, but I need it so that I only search for the first part of the string in the vector.

Here's what I've got:
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
int i =1;
while (i < 4000)
{
	std::fstream file1("Chinese.txt");
	std::vector<std::string> load;
	std::stringstream integer;
	integer<<i;
	std::string thisString;
	thisString=integer.str();
	thisString.insert(0,"IDS_STRING");
	while(!file1.eof())
	{
		std::string line1;
		std::getline(file1,line1);
		load.push_back(line1);
	}
      bool isPresent=std::find(load.begin(),load.end(),thisString)!=load.end());
	if(isPresent==false)
	{
		file1<<thisString + "\t";
	}
	else {}
	file1.close();
	i++;
}


So what's happening here is that the file contains strings that begin with "IDS_STRING" followed by a number, a tab and then a command. I'm basically trying to go through the file and see if each IDS_STRING number exists, so from 1 to 4000, and if it doesn't I want to write a new line in the file with the IDS_STRING number.

Example file contents:

IDS_STRING3 "Exhaust in"
IDS_STRING10 "Actuator off"
IDS_STRING4 "Service"

And say, I search for IDS_STRING12, which doesn't exist, I'd want that line to be inserted into the file, so:

IDS_STRING3 "Exhaust in"
IDS_STRING10 "Actuator off"
IDS_STRING4 "Service"
IDS_STRING12

Now, I don't know what the second part of the string is going to be (the command) so can only search for the IDS_STRING part. How can I achieve that?

Thanks in advance
Jan 6, 2012 at 12:02pm
It looks to me that you should separate IDS_STRINGX from the actual std::string.
I mean, use an std::map container: std::map<int, std::string>, instead of std::vector.
The int will be IDS_STRINGX and it'll be the key with which you will retrieve the std::string value.

http://www.cplusplus.com/reference/stl/map/
http://www.cplusplus.com/reference/stl/ (other containers)

But if you proceed with your current strategy, have a look at std::string::find():
http://www.cplusplus.com/reference/string/string/find/
Jan 6, 2012 at 12:11pm
find() can only do an exact match. To do anything more complicated, use find_if (or consider a different data structure, as Catfish suggests)

(while at it, I've fixed the "while not eof" loop (almost always an error) and moved reading from file out of the loop: did you really want to open and read the entire file 4000 times?)

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
#include <sstream>
#include <iostream>
#include <string>
#include <fstream>
#include <algorithm>

struct StartsWith {
    const std::string val;
    StartsWith(const std::string& s) : val(s) {}
    bool operator()(const std::string& in) const
    {
        return in.find(val) == 0;
    }
};

int main()
{
    std::vector<std::string> load;
    // load file
    {
        std::ifstream file1("Chinese.txt");
        for(std::string line1; getline(file1, line1); )
        {
            load.push_back(line1);
        }
    }

    // output to file
    std::ofstream file1("Chinese.txt", std::ios::app);
    for(int i = 1; i < 4000; ++i)
    {
        std::ostringstream integer;
        integer << "IDS_STRING" << i;
            std::string thisString = integer.str();
        bool isPresent = std::find_if(load.begin(), load.end(), StartsWith(thisString)) != load.end();
        if(isPresent == false)
        {
            file1 << thisString + "\n";
        }
    }
}


bonus: same code, modern C++

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
#include <vector>
#include <iostream>
#include <string>
#include <fstream>
#include <algorithm>

int main()
{
    std::vector<std::string> load;
    // load file
    {
        std::ifstream file1("Chinese.txt");
        for(std::string line1; getline(file1, line1); )
        {
            load.push_back(line1);
        }
    }

    // output to file
    std::ofstream file1("Chinese.txt", std::ios::app);
    for(int i = 1; i < 4000; ++i)
    {
        std::string thisString = "IDS_STRING" + std::to_string(i);
        bool isPresent = std::any_of(load.begin(), load.end(),
                                    [&](const std::string& in) {
                                            return in.find(thisString) == 0;
                                     });
        if(isPresent == false)
        {
            file1 << thisString + "\n";
        }
    }
}
Last edited on Jan 6, 2012 at 12:14pm
Jan 10, 2012 at 3:56pm
Thanks Cubbi, that works perfectly after I added a couple of little amendments so it fitted with the rest of my code.

And no, I'm pretty sure I didn't want to open the file 4000 times, oops. Thanks again!
Topic archived. No new replies allowed.