如何使用 CLion 在 C 中显示输入密码的星号

新手上路,请多包涵

网上有很多密码程序的示例代码,它用星号隐藏输入。当我使用我的 CodeBlocks IDE 编译它们时,这些程序可以工作,每次我输入一个字母时都会输出 *

 Enter Password  : ******
You entered : iiiiii
Process returned 0 (0x0)   execution time : 6.860 s
Press any key to continue.

但是,当我使用 CLion IDE 时,我可以看到我输入的字母:

 Enter Password  :iiiiii
 ******
You entered : iiiiii
Process finished with exit code 0

有人可以解释为什么两个 IDE 之间存在这种差异吗?

我正在使用的代码(我在网上找到的)是:

 #include <iostream>
#include <conio.h>
#include <stdlib.h>
using namespace std; //needed for cout and etc

int main()
{
    START:
    system("cls");
    cout<<"\nEnter Password  : ";
    char pass[32];//to store password.
    int i = 0;
    char a;//a Temp char
    for(i=0;;)//infinite loop
    {
        a=getch();//stores char typed in a
        if((a>='a'&&a<='z')||(a>='A'&&a<='Z')||(a>='0'&&a<='9'))
            //check if a is numeric or alphabet
        {
            pass[i]=a;//stores a in pass
            ++i;
            cout<<"*";
        }
        if(a=='\b'&&i>=1)//if user typed backspace
            //i should be greater than 1.
        {
            cout<<"\b \b";//rub the character behind the cursor.
            --i;
        }
        if(a=='\r')//if enter is pressed
        {
            pass[i]='\0';//null means end of string.
            break;//break the loop
        }
    }
    cout<<"\nYou entered : "<<pass;
    //here we can even check for minimum digits needed
    if(i<=5)
    {
        cout<<"\nMinimum 6 digits needed.\nEnter Again";
        getch();//It was not pausing :p
        goto START;
    }
    return 0;
}
//Lets check for errors.
//You can even put file system.

我知道有很多类似的问题,但是,没有一个可以解释为什么在使用 CLion IDE 时它不起作用。

原文由 BusyProgrammer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 870
2 个回答

也许

#include <conio.h>

int main()
{
    char s[10] = { 0 };
    int i;
    for (i = 0; i < 10;i++) {
        s[i] = _getch(); _putch('*');
        if (s[i] == 13) break;
    };
    printf("\nYour pass is %s", s);
    getchar();
    return 0;
}

原文由 Stilet 发布,翻译遵循 CC BY-SA 3.0 许可协议

只要您的平台支持 \b 和 C++ 11,这可能是一个跨平台解决方案(或解决方法)。它使用两个线程执行以下操作:

  1. 线程A( std::future<std::string> ):监听用户输入并返回下一个 std::getline
  2. 线程 B(主线程):等待监听器返回。同时,它使用 \b* \b 足够快(在以下代码中每 10 毫秒一次)来有效地:
    • 擦除前一个字符,将其替换为 *
    • 删除当前字符,以防用户删除字符。

这是它的样子:

密码输入示例

但是,它会在用户开始输入之前打印第一个 * 。也许使用其他占位符字符,例如 (需要Unicode)对用户来说更直观。

PasswordField 代码:

 #include <chrono>
#include <future>
#include <iostream>
#include <string>

class PasswordField {
private:
  const std::string placeholder;
  const int precedings;
  const int trailers;

  void refreshPlaceholder() {
    for (int i = 0; i != precedings; ++i) {
      std::cout << '\b';
    }
    std::cout << placeholder;
    for (int i = 0; i != trailers; ++i) {
      std::cout << '\b';
    }
    std::cout << std::flush;
  }

public:
  PasswordField(const std::string& placeholder, int precedingLength, int trailingLength)
  : placeholder(placeholder), precedings(precedingLength), trailers(trailingLength) {}

  std::string getline() {
    std::future<std::string> listener = std::async([]() {
      std::string answer;
      std::getline(std::cin, answer);
      return answer;
    });

    for (int i = 0; i != precedings; ++i) {
      std::cout << placeholder[i];
    }
    std::cout << std::flush;
    while (listener.wait_for(std::chrono::milliseconds(10))
          != std::future_status::ready) {
      refreshPlaceholder();
    }
    return listener.get();
  }
};

你可以这样使用它:

 PasswordField field("* ", 1, 1);
std::cout << "Password: " << field.getline() << std::endl;

// or Unicode
PasswordField field("█ ", 1, 1);
std::cout << "Password: " << field.getline() << std::endl;

// or erasing all input (note that std::endl is needed)
PasswordField field(" ", 1, 1);
std::cout << "Password: " << std::endl << field.getline() << std::endl;

// or something complex
PasswordField field("* (Enter to confirm) ", 1, 20);
std::cout << "Password: " << field.getline() << std::endl;

原文由 Kana 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题