原理比较简单,直接上代码:
#include <stdio.h>
#include <curses.h>
void refill(char ch, int num) {
int i = 0;
putchar('\r');
for (i = 0; i < num; ++i) {
putchar(ch);
}
}
// gcc ./main.c -o main -lcurses
int get_pass(char *passwd, int max_len) {
int i = 0;
char ch = 0;
initscr();
noecho();
for (i = 0; i < max_len;) {
ch = getchar();
if (ch == 13) {
break;
}
if (ch == 8 || ch == 127) {
if (i > 0) {
refill(' ', i);
passwd[--i] = 0;
refill('*', i);
}
continue;
}
passwd[i++] = ch;
putchar('*');
}
passwd[i] = 0;
endwin();
return i;
}
int main(void) {
char passwd[32];
int len = get_pass(passwd, 32);
printf("\nyou input: %s, len: %d\n", passwd, len);
return 0;
}
效果:
$ ./main
*******
you input: zhoumin, len: 7
1、主要用到了curses的三个常用函数,initscr()、noecho()、endwin()。通过这些函数,可以让程序实时接收用户的按键,参见:https://tldp.org/HOWTO/NCURSES-Programming-HOWTO/init.html#ECHONOECHO
2、为什么不用ncurses自带的getch?因为getch会清屏,参见:https://stackoverflow.com/questions/19748685/curses-library-why-does-getch-clear-my-screen
3、在ncurses里面回车符CR(\r)和换行符LF(\n)是分开的,敲击回车键后读入字符的ascii码是13(\r),而不是10(\n)。回车符CR和换行符LF的区别及联系参见:http://c.biancheng.net/c/ascii/
4、如果不需要将输入的字符显示为“*”,那就直接用getpass()函数吧,定义在unistd.h头文件里。
#include <unistd.h>
#include <stdio.h>
#include <string.h>
int main(void) {
char *passwd = getpass("please input password: ");
printf("you input: %s, len: %d\n", passwd, strlen(passwd));
return 0;
}
效果:
$ ./main
please input password:
you input: zhoumin, len: 7