简体   繁体   English

在C中比较字符串-strcmp

[英]Comparing strings in C - strcmp

I'm having trouble comparing strings in C (with which I am fairly new to). 我在比较C语言中的字符串时遇到了麻烦(我刚接触过)。 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. 在程序的这一特定部分,我希望能够基于从客户端接收的数据执行MySQL查询。 I want to be able to know when the received data has the value of "newuser" to initiate a simple registration procedure. 我希望能够知道何时接收到的数据具有“ newuser”值,以启动简单的注册过程。 Strcmp is returning a positive 1 value where I believe I should be getting a 0 because the values should be equal. Strcmp返回一个正1值,我相信我应该得到一个0,因为这些值应该相等。

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. 我有一种感觉,我没有正确处理传入的缓冲区或错误地复制了缓冲区。

strncpy copies at most - in this case - sizeof check bytes. strncpy最多复制-在这种情况下sizeof检查字节。 If the nul byte is not in that range it is not copied. 如果nul字节不在该范围内,则不会复制该字节。 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 您可能会在较长句子中使用“ newuser”一词,例如“ newuser blah blah”,因此您需要自己放置该nul

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

or use strlcpy , if available. 或使用strlcpy (如果可用)。

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. 您可能从buf []复制的字节多于收到的字节。 This will lead to you comparing against garbage (that might by chance happen to match your "newuser" string). 这将导致您与垃圾进行比较(可能偶然会与您的“ newuser”字符串匹配)。 And as other people have said, you have a second bug due to not NUL terminating one of your strings. 正如其他人所说,由于没有NUL终止您的字符串之一,您还有第二个错误。

In this case, I'd use memcmp(). 在这种情况下,我将使用memcmp()。 This is like strcmp() but it takes a length parameter rather than expecting NUL-terminated strings. 就像strcmp()一样,但是它使用一个length参数,而不是期望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 Not directly related, but recv() can fail by returning -1 with errno==EINTR . PS没有直接关系,但是recv()可能会因errno==EINTR返回-1而失败。 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. 在基于select()的应用程序中,还应该将套接字设置为非阻塞,然后检查errno==EAGAIN ,并在这种情况下返回到select() 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. 如果TCP / IP堆栈收到损坏的数据包,则会发生这种情况-它认为它具有数据包,因此select()会告诉您它是可读的,只有当您尝试读取它时,TCP / IP堆栈才会执行校验和计算并实现它必须丢弃数据。 It'll then either block (bad), or if it's set to nonblocking then it will return -1 with errno==EAGAIN . 然后它将阻塞(坏),或者如果将其设置为非阻塞,则它将以errno==EAGAIN返回-1

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

You miss '\\0' char at the end of fromUser: 您在fromUser的末尾错过了'\\ 0'char:

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

Two changes required: 需要进行两项更改:

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

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;
}

用。。。来代替:

char check[] = "newuser\0";

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM