比较C - strcmp中的字符串

时间:2009-06-22 15:18:28

标签: c string sockets network-programming strcmp

我在比较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:

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

7 个答案:

答案 0 :(得分:6)

strncpy最多复制 - 在这种情况下 - sizeof检查字节。如果nul字节不在该范围内,则不会复制。您可能会将“newuser”这个词作为较长句子的一部分,例如“newuser blah blah”,所以你需要自己放置那个

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

或使用strlcpy(如果有)。

答案 1 :(得分:3)

以下是您在问题中提供的示例代码(删除了调试代码):

//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");
    }

P.S。不直接相关,但-1可能会因errno==EINTR返回select()而失败。这不是错误情况,您只需要再试一次。通常这种情况很少发生,人们在没有检查的情况下逃脱,直到他们与其他一些使用信号的代码集成,突然他们的代码随机失败。

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

答案 2 :(得分:2)

我认为这里的问题(这里的问题之一)是fromUser(由于它的创建方式)不是空终止。

答案 3 :(得分:2)

你在来自用户:

的末尾错过'\ 0'char
...
strncpy(fromUser,buf, sizeof check);
fromUser[strlen(check)] = '\0';

答案 4 :(得分:1)

需要进行两项更改:

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

答案 5 :(得分:0)

此代码似乎已关闭:

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

答案 6 :(得分:-1)

替换为:

char check[] = "newuser\0";