2

Now when I understand how the code works, I would like to translate it to C++.

The original Python code:

def recv_all_until(s, crlf):
 data = ""
 while data[-len(crlf):] != crlf:
 data += s.recv(1)
 return data

Here's what I tried:

std::string recv_all_until(int socket, std::string crlf)
{
 std::string data = "";
 char buffer[1];
 memset(buffer, 0, 1);
 while(data.substr(data.length()-2, data.length()) != crlf)
 {
 if ((recv(socket, buffer, 1, 0)) == 0)
 {
 if (errno != 0)
 {
 close(socket);
 perror("recv");
 exit(1);
 }
 }
 data = data + std::string(buffer);
 memset(buffer, 0, 1);
 }
 return data;
}

But it shows:

terminate called after throwing an instance of 'std::out_of_range'
 what(): basic_string::substr

I understand that the problem is inside the while loop since at first the data string is empty. So how to improve this to make it work the same as it works in Python? Thank you.

asked Apr 7, 2017 at 12:27
1
  • 1
    FYI, Python strings have the method endswith which makes your while loop intention much clearer: while not data.endswith(crlf). With that in mind, this SO answer provides a very elegant solution for you. Commented Apr 7, 2017 at 12:36

2 Answers 2

2

You have the problem in the first iteration of your while loop:

Since the data is an empty string, data.length() is equal to 0, and thus you're calling data.substr(-2, 0).

To fix this, you need to add a check for the line length to the while statement.

Also, there's a method of finding such mistakes faster than writing a stackoverflow question about it. Consider reading this article.

answered Apr 7, 2017 at 12:34
Sign up to request clarification or add additional context in comments.

Comments

1

If we first change your Python code a bit:

def recv_all_until(s, crlf):
 data = ""
 while not data.endswith(crlf):
 data += s.recv(1)
 return data

What we need to do in C++ becomes much clearer:

bool ends_with(const std::string& str, const std::string& suffix)
{
 return str.size() >= suffix.size() &&
 std::equal(suffix.rbegin(), suffix.rend(), str.rbegin());
}
std::string recv_all_until(int socket, const std::string& crlf)
{
 std::string data = "";
 char buffer[1];
 memset(buffer, 0, 1);
 while (!ends_with(data, crlf))
 {
 if ((recv(socket, buffer, 1, 0)) == 0)
 {
 if (errno != 0)
 {
 close(socket);
 perror("recv");
 exit(1);
 }
 }
 data = data + std::string(buffer);
 memset(buffer, 0, 1);
 }
 return data;
}
answered Apr 7, 2017 at 12:59

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.