سؤال

وأواجه صعوبة في المقارنة بين السلاسل في C (التي أنا جديدة إلى حد ما). لدي مأخذ على هذا التطبيق الخادم انتظار لقبول البيانات من العميل. في هذا جزء معين من برنامجي أريد أن أكون قادرة على تنفيذ استعلام الخلية استنادا إلى البيانات الواردة من العميل. أريد أن أكون قادرة على معرفة عندما يكون البيانات الواردة قيمة "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:

ولدي شعور أنني لست التعامل مع المخزن المؤقت واردة بشكل صحيح أو خطأ نسخ المخزن المؤقت.

هل كانت مفيدة؟

المحلول

ونسخ strncpy على الأكثر - في هذه الحالة - بايت الاختيار sizeof. إذا البايت نول ليست في هذا النطاق لا يتم نسخها. ربما كنت الحصول على كلمة "NEWUSER" كجزء من عقوبة أطول، مثل "NEWUSER بلاه بلاه" لذلك تحتاج إلى المكان الذي نول نفسك

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

وأو استخدام strlcpy، إذا كانت متوفرة.

نصائح أخرى

وهنا هو رمز عينة ما قدمتموه في سؤالك (مع رمز التصحيح إزالة):

//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() في هذه الحالة. يمكن أن يحدث هذا إذا تلقى كومة TCP / IP حزمة التالفة - أنه يعتقد أن لديها حزمة حتى select() سوف اقول لكم انها قابلة للقراءة، انها فقط عند محاولة قراءتها إلى أن مكدس TCP / IP لا حساب اختباري ويدرك أن لديها لتتخلص من البيانات. انها سوف ثم إما كتلة (سيئة)، أو إذا تم ضبطه لتوصيل nonblocking ثم فإنه سيعود -1 مع errno==EAGAIN.

وأعتقد أن المشكلة هنا (واحدة من المشاكل هنا) هو أن fromUser (بسبب الطريقة التي يتم إنشاؤه) لا فارغة إنهاء.

وأنت تفوت '\ 0' شار في نهاية fromUser:

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

واثنين من التغييرات المطلوبة:

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

وهذا الرمز يبدو قبالة:

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 مع الإسناد
لا تنتمي إلى StackOverflow
scroll top