strcat يلقي خطأ تجزئة على إدخال كلمة مرور تشبه getch البسيطة

StackOverflow https://stackoverflow.com/questions/4093847

  •  28-09-2019
  •  | 
  •  

سؤال

أنا أستخدم Linux وهناك وظيفة مخصصة لإرجاع ASCII int من نوع المفتاح الحالي مثل getch(). عند محاولة التعود عليها وكيفية تخزين كلمة المرور التي وصلت إلى مشكلة ، فإن الكود الخاص بي هو كما يلي:

int main() {
    int c;
    char pass[20] = "";

    printf("Enter password: ");
    while(c != (int)'\n') {
        c = mygetch();
        strcat(pass, (char)c);
        printf("*");
    }

    printf("\nPass: %s\n", pass);

    return 0;
}

للأسف أحصل على التحذير من مجلس التعاون الخليجي:

pass.c:26: warning: passing argument 2 of ‘strcat’ makes pointer from integer without a cast
/usr/include/string.h:136: note: expected ‘const char * __restrict__’ but argument is of type ‘char’

حاولت استخدام المؤشرات بدلاً من صفيف char للمرور ، ولكن في الثانية أنا أكتب حرفًا يتصاعد. تعمل الوظيفة من تلقاء نفسها ولكن ليس في الحلقة ، فلا تشبه GetCh () على نظام Windows.

ما الذي يمكنك رؤيته خطأ في مثالي؟ أنا أستمتع بتعلم هذا.

تعديل: بفضل الإجابات التي توصلت إليها بالرمز السخيف التالي:

int c;
int i = 0;
char pass[PASS_SIZE] = "";

printf("Enter password: ");
while(c != LINEFEED && strlen(pass) != (PASS_SIZE - 1)) {
    c = mygetch();
    if(c == BACKSPACE) {
        //ensure cannot backspace past prompt
        if(i != 0) {
            //simulate backspace by replacing with space
            printf("\b \b");
            //get rid of last character
            pass[i-1] = 0; i--;
        }
    } else {
        //passed a character
        pass[i] = (char)c; i++;
        printf("*");
    }
}
pass[i] = '\0';
printf("\nPass: %s\n", pass);
هل كانت مفيدة؟

المحلول

المشكلة هي strcat يتوقع char * كحجة ثانية لها (تسلس سلسلتين). ليس لديك سلاسلان ، لديك سلسلة واحدة وواحدة char.

إذا كنت تريد إضافة c حتى نهاية pass, ، فقط احتفظوا i الذي يخزن الحجم الحالي لـ pass ثم افعل شيئًا مثل

pass[i] = (char) c.

تأكد pass عند الانتهاء (عن طريق تحديد الموضع الأخير إلى 0).

نصائح أخرى

حرف واحد ليس هو نفس سلسلة تحتوي على حرف واحد.

وبعبارة أخرى ، "أ" و "أ" أشياء مختلفة جدا.

السلسلة ، في C ، هي مجموعة من chars المنتهية الفارغة. "Pass" الخاص بك عبارة عن مجموعة من 20 Chars - كتلة من الذاكرة تحتوي على مساحة 20 Chars.

وظيفة mygetch () إرجاع char.

ما عليك القيام به هو إدراج C في أحد المساحات.

بدلاً من "strcat (pass ، c)" ، تريد القيام به "تمرير [i] = c" ، حيث أبدأ في الصفر ، وزيادات واحدة لكل مرة تتصل بها mygetch ().

ثم تحتاج إلى إجراء تمريرة [i] = ' 0' ، عندما يتم الانتهاء من الحلقة ، مع تساوي عدد المرات التي اتصلت بها mygetch () ، لإضافة Terminator NULL.

لديك مشكلة أخرى هي أنك لم تقم بتعيين قيمة لـ C ، في المرة الأولى التي تقوم فيها بالتحقق لمعرفة ما إذا كانت " n". تريد الاتصال mygetch () قبل إجراء المقارنة:

int i = 0;
for (;;)
{
    c = mygetch();
    if (c == '\n')
        break;

    c = mygetch();
    pass[i++] = c;
}
pass[i] = '\0';

علاوة على المشكلة التي تم تشخيصها بشكل صحيح مع strcat() أخذ سلسلتين - لماذا تجاهلت التحذيرات المترجم ، أو إذا لم تكن هناك تحذيرات ، فلماذا لم يتم تشغيل تحذيرات؟ كما كنت أقول ، علاوة على هذه المشكلة ، تحتاج أيضًا إلى التفكير في ما يحدث إذا حصلت على EOF ، وتحتاج أيضًا إلى القلق بشأن القيمة الأولية لـ "C" (والتي يمكن أن تكون عن طريق الخطأ " n" على الرغم من أنها على الأرجح 'ر).

هذا يؤدي إلى كود مثل هذا:

int  c;
char pass[20] = "";
char *end = pass + sizeof(pass) - 1;
char *dst = pass;

while ((c = getchar()) != EOF && c != '\n' && dst < end)
    *dst++ = c;
*dst = '\0';  // Ensure null termination

لقد تحولت من "mygetch ()" إلى "getchar ()" - في المقام الأول لأن ما أقوله ينطبق على ذلك وقد لا ينطبق على وظيفة "mygetch () ؛ ليس لدينا مواصفات لما تفعله هذه الوظيفة على EOF.

بدلاً من ذلك ، إذا كان يجب عليك استخدامه strcat(), ، لا تزال بحاجة إلى متابعة مسار على طول السلسلة ، ولكن يمكنك القيام بذلك:

char c[2] = "";
char pass[20] = "";
char *end = pass + sizeof(pass) - 1;
char *dst = pass;

while (c[0] !=  '\n' && dst < end)
{
    c[0] = mygetch();
    strcat(dst, c);
    dst++;
}

ليست أنيقة مثل كل ذلك - باستخدام strcat() في السياق مبالغة. يمكنك ، على ما أظن ، القيام بالعد البسيط واستخدامها مرارًا وتكرارًا strcat(pass, c), ، لكن هذا له سلوك تربيعي strcat() يجب أن تتخطى 0 ، 1 ، 2 ، 3 ، ... الشخصيات على التكرارات اللاحقة. على النقيض من ذلك ، فإن الحل الذي يشير فيه DST إلى NUL في نهاية السلسلة يعني ذلك strcat() ليس من الضروري تخطي أي شيء. مع إضافة حجم ثابت من حرف واحد ، رغم ذلك ، من المحتمل أن تكون أفضل حالًا مع الحلقة الأولى.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top