Как я могу прочитать пароль из консоли, повторяя знаки?

здесь я написал код для принятия пароля, введенного пользователем после того, как он ввел свое имя пользователя, я написал небольшой код, используя оператор do while, чтобы распечатать звезду каждый раз, когда пользователь вводит какой-либо символ, и цикл завершается, когда пользователь вводит '!'. но меня удивило, когда я увидел пароль, введенный пользователем, и длину строки введенного пароля, в моем случае длина СТРОКИ всегда равна 21, а вывод пароля представляет собой комбинацию пароля, введенного пользователь и имя пользователя......что происходит??????

#include<iostream.h>
#include<conio.h>
#include<string.h>
int main()
{
    char username[15],password[15];
    int i=0;
    cout<<"\nEnter your USERNAME:";
    cin>>username;
    cout<<"\nenter your password:";

    do 
    {
        password[i]=getch();


        if(password[i]=='!')break;
        cout<<"*";
        i++;
    }while(i<15);
    cout<<"\n\nthe password entered was"<<password<<"\nthe length of the password is"           <<strlen(password);
    getch();
    return 0;
} 

person nobalG    schedule 29.07.2011    source источник
comment
Использование буферизованных потоков на готовом терминале, вероятно, не лучший способ чтения паролей. Раньше в <unistd.h> была функция getpass(), но она не является потокобезопасной. Предположительно, часто задаваемые вопросы программистов Unix описывает, как читать без эха ( раздел 3.1).   -  person Kerrek SB    schedule 29.07.2011


Ответы (5)


Вы определили:

char password[15];

И согласно вашему циклу он продолжается до тех пор, пока i не станет равным 14 (т. е. 15-й символ). Таким образом, нет места для завершения NULL. Пусть будет так:

char password[16];

Теперь, сразу после цикла, добавьте:

password[i] = 0;

i будет 15, если пользователь не ввел '!' и если он это сделал, он будет заменен символом NULL. Я думаю, что это самое простое исправление. Если вы не хотите '!' для замены поставьте i++; перед break;

person Ragesh Chakkadath    schedule 29.07.2011
comment
хорошо, это круто, но почему длина строки всегда равна 21, почему имя пользователя объединяется, когда я распечатываю строку пароля...?? - person nobalG; 29.07.2011
comment
Я согласен с @Blaze, без NULL в конце следующий адрес памяти может быть выделен для имени пользователя и, следовательно, конкатенации. - person Ragesh Chakkadath; 30.07.2011

Вы не завершаете свою строку с помощью NULL.

do 
{
    password[i]=getch();
    if(password[i]=='!') break;
    cout<<"*";-
    i++;
}while(i<15);
if (i < 15) password[i] = '\0';
person Blazes    schedule 29.07.2011
comment
Прекращение должно быть безоговорочным. Было бы лучше иметь строку на один элемент длиннее, чем ввод. - person Nobody moving away from SE; 29.07.2011
comment
хорошо, это круто, но почему длина строки всегда равна 21, почему имя пользователя объединяется, когда я распечатываю строку пароля...?? - person nobalG; 29.07.2011
comment
strlen просматривает индекс 15 и находит нулевое значение в 21. - person Blazes; 29.07.2011
comment
Пароль — это просто адрес памяти. strlen просто сканирует память до тех пор, пока не встретится NULL. Если вам не удалось установить NULL для пароля, остальные символы являются случайным мусором (т.е. не NULL). - person Blazes; 29.07.2011

Строка C должна заканчиваться специальным символом '\0', что не относится к вашему паролю/имени пользователя. Вы должны установить i+1th символ на '\0':

password[i]=getch();
password[i+1] = '\0';

Также вы должны учитывать, что ваш буфер паролей также должен содержать эту строку, поэтому у вас есть место только для 14 символов, если вы определяете char password[15];, поэтому ваш цикл может просто перейти к 14.

person Constantinius    schedule 29.07.2011

Вы читаете 15 символов, но никогда не пишете '\0' в строке, поэтому она не завершается.

person Karoly Horvath    schedule 29.07.2011

It is

#include <iostream>
#include <string>

пожалуйста, исправьте это. Если ваш компилятор не знает этих файлов, то ваш компилятор никуда не годится.

Тогда почему бы вам не использовать std::string вместо массивов символов?
Это позволит избежать любой из этих ошибок. То, что вы здесь делаете, представляет собой смесь c и c++.

person Community    schedule 29.07.2011
comment
но операции, которые я выполнил, полностью действительны и для С++, я был бы признателен, если бы вы рассказали мне о причине вышеуказанного поведения строки...... - person nobalG; 29.07.2011
comment
Вас не будут беспокоить такие ошибки, как забытое завершение \0. Кроме того, строка является классом и имеет множество удобных функций. Вы также можете получить доступ к одному символу с помощью оператора []. У вас есть доступ к длине с помощью length() и size(), вы можете изменить размер(), если это необходимо для предварительного выделения и так далее. Есть много причин. #include ‹string.h› делает ваш код несовместимым с более новыми компиляторами. .h устарел для включения компилятора в С++. И теперь я вне пространства здесь xP. - person ; 29.07.2011
comment
YO... но я нашел этого более чем достаточно...:p..thanx..:) - person nobalG; 29.07.2011
comment
Читайте также здесь: cplusplus.com/forum/beginner/39622 и здесь: cplusplus.com/forum/beginner/4878 - person ; 29.07.2011