比较 C 中的字符串 - strcmp

发布于 2024-07-25 08:24:16 字数 1308 浏览 9 评论 0原文

我在比较 C 语言中的字符串时遇到了麻烦(我对 C 语言还很陌生)。 我在这个服务器应用程序上有套接字等待接受来自客户端的数据。 在我的程序的这个特定部分中,我希望能够根据从客户端接收到的数据执行 MySQL 查询。 我希望能够知道接收到的数据何时具有“newuser”值以启动简单的注册过程。 Strcmp 返回正值 1,我相信我应该得到 0,因为这些值应该相等。

源代码:

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
    if (nbytes == 0) {
        // connection closed
        printf("selectserver: socket %d hung up\n", i);
    } else {
        perror("recv");
    }
    close(i); // bye!
    FD_CLR(i, &master); // remove from master set
} else {

    char check[] = "newuser";
    char fromUser[sizeof check];

    strncpy(fromUser,buf, sizeof check);
    printf("length of fromUser: %d\n", sizeof fromUser);
    printf("length of check: %d\n", sizeof check);
    printf("message from user: %s\n", fromUser);
    printf("check = %s \n", check);
    int diff = strcmp(fromUser, check);
    printf("compare fromUser to check: %d\n", diff);
    if ( strcmp(fromUser, check) == 0) {
        printf("aha! new user");
    }

输出:

length of fromUser: 8
length of check: 8
newuser from user: newuser
check = newuser 
compare fromUser to check:

我有一种感觉,我没有正确处理传入缓冲区或错误地复制缓冲区。

I'm having trouble comparing strings in C (with which I am fairly new to). I have socket on this server application waiting to accept data from a client. In this particular portion of my program I want to be able to execute a MySQL query based on the data received from the client. I want to be able to know when the received data has the value of "newuser" to initiate a simple registration procedure. Strcmp is returning a positive 1 value where I believe I should be getting a 0 because the values should be equal.

Source Code:

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
// got error or connection closed by client
    if (nbytes == 0) {
        // connection closed
        printf("selectserver: socket %d hung up\n", i);
    } else {
        perror("recv");
    }
    close(i); // bye!
    FD_CLR(i, &master); // remove from master set
} else {

    char check[] = "newuser";
    char fromUser[sizeof check];

    strncpy(fromUser,buf, sizeof check);
    printf("length of fromUser: %d\n", sizeof fromUser);
    printf("length of check: %d\n", sizeof check);
    printf("message from user: %s\n", fromUser);
    printf("check = %s \n", check);
    int diff = strcmp(fromUser, check);
    printf("compare fromUser to check: %d\n", diff);
    if ( strcmp(fromUser, check) == 0) {
        printf("aha! new user");
    }

Output:

length of fromUser: 8
length of check: 8
newuser from user: newuser
check = newuser 
compare fromUser to check:

I have a feeling I'm not handling the incoming buffer correctly or erroneously copying the buffer.

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

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

发布评论

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

评论(7

一绘本一梦想 2024-08-01 08:24:16

strncpy 最多复制 - 在本例中 - sizeof 检查字节。 如果 nul 字节不在该范围内,则不会复制它。 您可能会将“newuser”一词作为较长句子的一部分,例如“newuser blah blah”,因此您需要自己放置该 nul

strncpy(fromUser, buf, sizeof check);
fromUser[sizeof check - 1] = '\0';

或使用 strlcpy(如果有)。

strncpy copies at most - in this case - sizeof check bytes. If the nul byte is not in that range it is not copied. You probably are getting the word "newuser" as part of a longer sentence, like "newuser blah blah" so you need to place that nul yourself

strncpy(fromUser, buf, sizeof check);
fromUser[sizeof check - 1] = '\0';

or use strlcpy, if available.

手心的温暖 2024-08-01 08:24:16

这是您在问题中给出的示例代码(删除了调试代码):

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
    [... exception handling here ...]
} else {
    char check[] = "newuser";
    char fromUser[sizeof check];

    strncpy(fromUser,buf, sizeof check);
    if ( strcmp(fromUser, check) == 0) {
        printf("aha! new user");
    }

此代码是错误的; 您可能从 buf[] 复制的字节数多于已接收的字节数。 这将导致您与垃圾进行比较(可能碰巧与您的“newuser”字符串匹配)。 正如其他人所说,由于没有 NUL 终止字符串之一,您还有第二个错误。

在这种情况下,我将使用 memcmp()。 这类似于 strcmp(),但它需要一个长度参数,而不是期望以 NUL 结尾的字符串。

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
    [... exception handling here ...]
} else {
    static const char check[] = "newuser";
    const size_t check_len = sizeof(check) - 1; // exclude the NUL terminator
    if (nbytes >= check_len && memcmp(buf, check, check_len) == 0) {
        printf("aha! new user");
    }

PS 不直接相关,但 recv() 可能会因返回 < code>-1 与 errno==EINTR。 这不是错误情况,您只需重试。 通常这种情况很少发生,以至于人们在没有检查它的情况下就逃脱了,直到他们与其他使用信号的代码集成并且突然他们的代码随机失败。

在基于 select() 的应用程序中,您还应该将套接字设置为非阻塞,然后检查 errno==EAGAIN,然后返回到 >select() 在这种情况下。 如果 TCP/IP 堆栈收到损坏的数据包,就会发生这种情况 - 它认为它有一个数据包,因此 select() 会告诉您它是可读的,只有当您尝试读取它时,TCP/IP堆栈进行校验和计算并意识到它必须丢弃数据。 然后它会阻塞(坏),或者如果它设置为非阻塞,那么它将返回 -1errno==EAGAIN

Here's the sample code you gave in your question (with debugging code removed):

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
    [... exception handling here ...]
} else {
    char check[] = "newuser";
    char fromUser[sizeof check];

    strncpy(fromUser,buf, sizeof check);
    if ( strcmp(fromUser, check) == 0) {
        printf("aha! new user");
    }

This code is wrong; you're potentially copying more bytes from buf[] than have been received. This will lead to you comparing against garbage (that might by chance happen to match your "newuser" string). And as other people have said, you have a second bug due to not NUL terminating one of your strings.

In this case, I'd use memcmp(). This is like strcmp() but it takes a length parameter rather than expecting NUL-terminated strings.

//setup socket
//loop and select structure to handle multiple connections

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) {
    [... exception handling here ...]
} else {
    static const char check[] = "newuser";
    const size_t check_len = sizeof(check) - 1; // exclude the NUL terminator
    if (nbytes >= check_len && memcmp(buf, check, check_len) == 0) {
        printf("aha! new user");
    }

P.S. Not directly related, but recv() can fail by returning -1 with errno==EINTR. This isn't an error condition, you just need to try again. Normally this happens so rarely that people get away without checking it, until they integrate with some other code that uses signals and suddenly their code randomly fails.

In a select()-based app, you should also be setting your sockets to non-blocking and then check for errno==EAGAIN, and go back to the select() in that case. This can happen if the TCP/IP stack receives a corrupted packet - it thinks it has a packet so select() will tell you it's readable, it's only when you try to read it that the TCP/IP stack does the checksum calculation and realises it has to throw away the data. It'll then either block (bad), or if it's set to nonblocking then it will return -1 with errno==EAGAIN.

坚持沉默 2024-08-01 08:24:16

我相信这里的问题(这里的问题之一)是 fromUser (由于它的创建方式)不是 null 终止的。

I believe the problem here (one of the problems here) is that fromUser (due to the way it is created) is not null terminated.

苦行僧 2024-08-01 08:24:16

您错过了 fromUser 末尾的 '\0' 字符:

...
strncpy(fromUser,buf, sizeof check);
fromUser[strlen(check)] = '\0';

You miss '\0' char at the end of fromUser:

...
strncpy(fromUser,buf, sizeof check);
fromUser[strlen(check)] = '\0';
べ映画 2024-08-01 08:24:16

需要进行两项更改:

char fromUser[sizeof check] = {'\0'}; //Make all null characters
strncpy(fromUser,buf, sizeof check -1); //Last character is for null character.

Two changes required:

char fromUser[sizeof check] = {'\0'}; //Make all null characters
strncpy(fromUser,buf, sizeof check -1); //Last character is for null character.
捎一片雪花 2024-08-01 08:24:16

这段代码似乎关闭:

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) 
{
 // your stuff
} 
else {
const char *pCheck = "newuser";
char *fromUser = new char[nbytes];
strncpy(fromUser, buff, nbytes);
fromUser[nbytes] = '\0';
if(strcmp(fromUser,check)==0)
 // blah

delete [] fromUser;
}

This code seems off:

if ((nbytes = recv(i, buf, sizeof buf, 0)) <= 0) 
{
 // your stuff
} 
else {
const char *pCheck = "newuser";
char *fromUser = new char[nbytes];
strncpy(fromUser, buff, nbytes);
fromUser[nbytes] = '\0';
if(strcmp(fromUser,check)==0)
 // blah

delete [] fromUser;
}
惯饮孤独 2024-08-01 08:24:16

用。。。来代替:

char check[] = "newuser\0";

Replace with:

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