Trying to remove certain parts of the line, but I keep getting errors

I have a file that contains lines that look like this:

uniquemember: uid=vojk,ou=people,dc=cms,dc=gov
uniquemember: uid=p2o9,ou=people,dc=cms,dc=gov
etc.

I'm trying to isolate and get - the four letter code sandwiched in between everything (vojk, p2o9). That's all I want to printed out.

I've been looking around and I see that there's a function called "erase" that I can use to try and erase certain parts of the line. However, when I try, I keep getting out of bound errors and it keeps saying "std::out_of_range" and ' > this-> size() (which is 0) '

I'm not sure what I'm doing wrong. Here is my code. I sincerely appreciate your help. Thank you in advance.
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
#include <iostream>
#include <algorithm>
#include <vector>
#include <fstream>
#include <string>

using namespace std;
int main()
{
    vector<string> v;
    vector<string> junk;

    ifstream infile;
    infile.open("list.txt");

    if (infile.fail())
    {
    cout << "Could not open file." << "\n";
    return 1;
    }


    string data;
    string str ("dn");
    string str2 ("uniquemember: ");
    //infile >> data;
    while (getline(infile, data)) {
      transform(data.begin(), data.end(), data.begin(),
      [](unsigned char c) { return tolower(c);});
    //data.erase(data.length()-10);
      if (data.find(str) != string::npos) {
      junk.push_back(data);
      }

      else {
        v.push_back(data);
      }
    }

    sort(v.begin(), v.end());
    auto last = unique(v.begin(), v.end());
    v.erase(last, v.end());
    for (const auto& i : v)
    cout << i << " " << endl;
}
Break the code into manageable and testable steps.
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
#include <iostream>
#include <vector>
#include <string>
using namespace std;

string getCode(const string &from) {
  string result = "";
  size_t begin = from.find("uid=");
  if ( begin != string::npos ) {
    size_t end = from.find(",",begin);
    if ( end != string::npos ) {
      result = from.substr(begin+4,end-begin-4);
    }
  }
  return result;
}

int main()
{
  vector<string> tests = {
    "uniquemember: uid=vojk,ou=people,dc=cms,dc=gov",
    "uniquemember: uid=p2o9,ou=people,dc=cms,dc=gov",
  };
  for ( auto && s : tests ) {
    cout << s << " has ID = " << getCode(s) << endl;
  }
  return 0;
}


What is the point of pushing to junk when you never even use it?

Is there even a point to your pre-filtering step?
If the extractor logic is strong enough, you shouldn't need to do that.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
#include <string>
#include <sstream>

std::string getCode(const std::string& from) {
	std::string result;
	std::istringstream iss(from);

	std::getline(iss, result, '=') && std::getline(iss, result, ',');
	return result;
}

int main()
{
	const std::string tests[] {
	  "uniquemember: uid=vojk,ou=people,dc=cms,dc=gov",
	  "uniquemember: uid=p2o9,ou=people,dc=cms,dc=gov",
	};

	for (const auto& s : tests)
		std::cout << getCode(s) << '\n';
}



vojk
p2o9



Or from a file:

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

std::string getCode(const std::string& from) {
	std::string result;
	std::istringstream iss(from);

	std::getline(iss, result, '=') && std::getline(iss, result, ',');
	return result;
}

int main() {
	std::ifstream infile("list.txt");

	if (!infile.is_open()) {
		std::cout << "Could not open file.\n";
		return 1;
	}

	for (std::string data; std::getline(infile, data); ) {
		transform(data.begin(), data.end(), data.begin(),
			[](auto c) { return tolower(c); });

		std::cout << getCode(data) << '\n';
	}
}

Last edited on
Hello KittyIchigo1,

You could try this:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
while (getline(infile, data))
{
    transform(data.begin(), data.end(), data.begin(),
                [](unsigned char c) { return tolower(c); });
    //data.erase(data.length()-10);

    size_t pos;

    if ((pos = data.find('=', 0)) != string::npos)
    {
        wantedData.push_back(data.substr(pos + 1, 4));
    }

    //else
    //{
    //    junk.push_back(data);
    //}
}

I found that for the moment the else part is not need, but it may be useful in the future.

As I understand what you wrote this will store in the vector "vojk" and "p2o9" and the following sort will sort these in reverse order as it should.

What follows the sort may not be needed.

I did change the vector "v" to "wantedData" because it makes more sense right now. Change it to anything you like, but try to avoid single letters that have no meaning.

Andy
Topic archived. No new replies allowed.