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

Nov 29, 2020 at 5:53am
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;
}
Nov 29, 2020 at 6:41am
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.

Nov 29, 2020 at 10:52am
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 Nov 29, 2020 at 11:03am
Nov 29, 2020 at 11:24am
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.