解析字符串并尝试查找“\0”时出错特点

发布于 2024-08-11 04:24:09 字数 1645 浏览 5 评论 0原文

我试图让一侧向客户端发送错误消息,但客户端无法正确解析它。

我的错误是>>>>>在我的 parseString 函数中,它让 index = 0,因此我的“substr”调用超出范围。

服务器端:::

   #define ERRBUFSIZE 51

    string error = "Error - Already Registered: ";
                error.append(name);
                char err[ERRBUFSIZE];
                err[0] = 0;
                std::copy(error.begin(), error.end(), err+1);

                err[error.size() + 2] = '\0';

                if (send(sock, &err, ERRBUFSIZE, 0) < 0)
                {
                DieWithError("send() failed");
                }

客户端(谁正在接收)::

   char msgBuffer[ERRBUFSIZE];
        int bytesRcvd = 0;
        int totalRcvd = 0;
        while(totalRcvd != ERRBUFSIZE)
        {   
            // Get Message from Server
            if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
            DieWithError("recv() failed or connection closed prematurely");

            totalRcvd += bytesRcvd; 
        }

        cout << "Bytes received: " << totalRcvd << endl;
        msgBuffer[totalRcvd] = '\0';

        string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
        cout << rcvMsg << endl;
        rcvMsg = parseString(rcvMsg);

        return rcvMsg;

在哪里....

   string TCPClient::parseString(string message)
    {
        cout << "parsing new string" << endl;
        int index = message.find('\0');
        string result = message.substr(0, index);
        cout << "THE RESULT :: " << result << endl;
        return result;
    }

I'm trying to get one side to send an error message to client, but client isn't able to parse it correctly.

My error is >>>>> in my parseString function, it lets index = 0 and therefore I get an out of range for my 'substr' call.

Server Side:::

   #define ERRBUFSIZE 51

    string error = "Error - Already Registered: ";
                error.append(name);
                char err[ERRBUFSIZE];
                err[0] = 0;
                std::copy(error.begin(), error.end(), err+1);

                err[error.size() + 2] = '\0';

                if (send(sock, &err, ERRBUFSIZE, 0) < 0)
                {
                DieWithError("send() failed");
                }

Client side ( who is receiving )::

   char msgBuffer[ERRBUFSIZE];
        int bytesRcvd = 0;
        int totalRcvd = 0;
        while(totalRcvd != ERRBUFSIZE)
        {   
            // Get Message from Server
            if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
            DieWithError("recv() failed or connection closed prematurely");

            totalRcvd += bytesRcvd; 
        }

        cout << "Bytes received: " << totalRcvd << endl;
        msgBuffer[totalRcvd] = '\0';

        string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
        cout << rcvMsg << endl;
        rcvMsg = parseString(rcvMsg);

        return rcvMsg;

where....

   string TCPClient::parseString(string message)
    {
        cout << "parsing new string" << endl;
        int index = message.find('\0');
        string result = message.substr(0, index);
        cout << "THE RESULT :: " << result << endl;
        return result;
    }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

当爱已成负担 2024-08-18 04:24:09

为什么不将 parseString 更改为以下内容:

string TCPClient::parseString(const string& message, int strLength )
{
    cout << "parsing new string" << endl;
    string result = message.substr( 0, strLength );
    cout << "THE RESULT :: " << result << endl;
    return result;
}

然后将调用代码更改为:

rcvMsg = parseString(rcvMsg, totalRcvd );

如果失败,您甚至可以使用字符串的“size()”函数。

编辑:还值得注意的是, find 将在字符串中前进,直到找到 '\0' 字符,但实际上不会查找它。将字符串放入字符串对象(存储长度),然后尝试通过缓慢的迭代过程自己计算长度,这似乎有点奇怪。

Edit2:如果您只想使用字符数组来执行此操作,您可以按如下方式进行手动搜索。

int index = 0;
while( *charString++ != '\0' ) index++;

就这么简单:)

Why not change your parseString to the following:

string TCPClient::parseString(const string& message, int strLength )
{
    cout << "parsing new string" << endl;
    string result = message.substr( 0, strLength );
    cout << "THE RESULT :: " << result << endl;
    return result;
}

And then change the calling code to:

rcvMsg = parseString(rcvMsg, totalRcvd );

Failing that you could even use the string's "size()" function.

Edit: Its also worth noting that find will advance through the string until the '\0' character is found but WON'T actually look for it. It seems a bit of an odd plan to put a string into a string object (Which stores length) and then try and calculate length yourself through a, slow, iterative process.

Edit2: If you just want to do it with a character array you can do a manual search as follows.

int index = 0;
while( *charString++ != '\0' ) index++;

Its that simple :)

拒绝两难 2024-08-18 04:24:09

从(非常难以阅读)代码来看,我认为您可能会遇到“索引地狱”。

检查 totalRecvd 实际上是您想要写入 \0 的索引,并且在创建 rcvMsg 时添加 >\0 对其进行索引(当您将字符串结尾标记放在 totalRcvd 字节上时,msgBuffer + TotalRcvd 看起来很糟糕,通常您会得到您编写的 (start, end-1) 索引之间的字符串)。

另外 - 搜索 \0 没有任何意义,因为它只是一个标记。

另外 (2) - 如果 totalRcvd == ERRBUFSIZE 您无法访问 msgBuffer [totalRcvd],您只能访问范围 (0, ERRBUFSIZE -1)

From the (very-difficult-to-read-)code, I think you might be running into "indexing hell".

Check that totalRecvd actually is the index where you want to write that \0 and that when you create your rcvMsg you're adding the \0 index to it (msgBuffer + totalRcvd looks dogdy when you've put your end-of-string marker on the totalRcvd byte, usually you get a string between (start, end-1) indexes you write).

Also - searching for the \0 makes no sense as that is just a marker.

Also (2) - if totalRcvd == ERRBUFSIZE you can't access msgBuffer [totalRcvd], you only have access to the indexes in range (0, ERRBUFSIZE -1)

别在捏我脸啦 2024-08-18 04:24:09

当您想要管理缓冲区时,请使用 std::vector 而不是 std::string。 '\0' 和 std::basic_string 结合得不好。

Use std::vector instead of std::string when you want to manage buffers. '\0' and std::basic_string doesn't combine well.

绮烟 2024-08-18 04:24:09

首先,协议很糟糕。当您想要发送以 null 结尾的字符串时,您正在发送固定大小的块...将字符串长度放在消息的前面会更简单。

其次,您没有从套接字正确读取数据,只要管道中没有任何其他消息,它就会正常工作。
如果您的 while 循环曾经真正被执行过,您将用任何后续读取覆盖第一个片段。

无论如何,该错误的直接原因是您在字符串前面添加了一个 nul 终止符(分隔符?)。这难道不能解释为什么你总是在索引 0 处找到 nul 吗?
如果看不到它,请尝试写出发送时缓冲区的内容。

#define ERRBUFSIZE 51

void server(string const &name)
{
    string error = "Error - Already Registered: ";
    error.append(name);
    char err[ERRBUFSIZE];
    // you sure you want a NUL terminator at index 0??
    err[0] = 0;
    // can replace both lines with strcpy(err, error.c_str())
    std::copy(error.begin(), error.end(), err+1);
    err[error.size() + 2] = '\0';

    if (send(sock, &err, ERRBUFSIZE, 0) < 0)
        DieWithError("send() failed");
}

string parseString(string const &message) // no need to copy
{
    // ... this is redundant anyway, see below
}

string client()
{
    char msgBuffer[ERRBUFSIZE];
    int bytesRcvd = 0;
    int totalRcvd = 0;
    while(totalRcvd != ERRBUFSIZE)
    {       
        // Get Message from Server
        // ... recv(sock, msgBuffer+totalRcvd, ERRBUFSIZE-totalRcvd) ...
        if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
            DieWithError("recv() failed or connection closed prematurely");

        totalRcvd += bytesRcvd; 
    }

    cout << "Bytes received: " << totalRcvd << endl;
    //sizeof(msgBuffer)==ERRBUFSIZE==totalRcvd, so this overflows
    msgBuffer[totalRcvd] = '\0';

    // assuming you skip the leading \0, msgBuffer is already nul-terminated
    // so use string rcvMsg(msgBuffer) and skip the parseString/substr
    string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
    cout << rcvMsg << endl;
    // rcvMsg = parseString(rcvMsg);

    return rcvMsg;
}

First, the protocol is nasty. You're sending fixed-size blocks when you want to send a nul-terminated string ... it would be simpler just to put the string length at the front of the message.

Second, you're not reading correctly from the socket, it just happens to work so long as you don't have any other messages in the pipeline.
If your while loop was ever really exercised, you'd overwrite the first fragment with any subsequent reads.

Anyway, the proximate cause of the bug is that you prepend a nul terminator (separator?) to the string. Doesn't that explain why you always find your nul at index 0?
If you can't see it, try writing out the contents of the buffer as sent.

#define ERRBUFSIZE 51

void server(string const &name)
{
    string error = "Error - Already Registered: ";
    error.append(name);
    char err[ERRBUFSIZE];
    // you sure you want a NUL terminator at index 0??
    err[0] = 0;
    // can replace both lines with strcpy(err, error.c_str())
    std::copy(error.begin(), error.end(), err+1);
    err[error.size() + 2] = '\0';

    if (send(sock, &err, ERRBUFSIZE, 0) < 0)
        DieWithError("send() failed");
}

string parseString(string const &message) // no need to copy
{
    // ... this is redundant anyway, see below
}

string client()
{
    char msgBuffer[ERRBUFSIZE];
    int bytesRcvd = 0;
    int totalRcvd = 0;
    while(totalRcvd != ERRBUFSIZE)
    {       
        // Get Message from Server
        // ... recv(sock, msgBuffer+totalRcvd, ERRBUFSIZE-totalRcvd) ...
        if ((bytesRcvd = recv(sock, msgBuffer, ERRBUFSIZE, 0)) < 0)
            DieWithError("recv() failed or connection closed prematurely");

        totalRcvd += bytesRcvd; 
    }

    cout << "Bytes received: " << totalRcvd << endl;
    //sizeof(msgBuffer)==ERRBUFSIZE==totalRcvd, so this overflows
    msgBuffer[totalRcvd] = '\0';

    // assuming you skip the leading \0, msgBuffer is already nul-terminated
    // so use string rcvMsg(msgBuffer) and skip the parseString/substr
    string rcvMsg( msgBuffer , msgBuffer + totalRcvd);
    cout << rcvMsg << endl;
    // rcvMsg = parseString(rcvMsg);

    return rcvMsg;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文