在Linux上的C程序中屏蔽密码字符

在Linux上的C程序中屏蔽密码字符,c,linux,ncurses,stdio,C,Linux,Ncurses,Stdio,我试图创建一个程序,在输入密码时隐藏输入的字符。但我仍然有一个问题,只要我启动程序,“*”字符就会连续写入一个分段错误。这是我编写的代码和程序执行后的行为: #include <stdio.h> #include <curses.h> #define ENTER 13 #define TAB 9 char pwd[100]; int main(){ int i = 0; char ch; printf("Enter your pa

我试图创建一个程序,在输入密码时隐藏输入的字符。但我仍然有一个问题,只要我启动程序,“*”字符就会连续写入一个分段错误。这是我编写的代码和程序执行后的行为:

#include <stdio.h>
#include <curses.h>

#define ENTER 13
#define TAB 9

char pwd[100];

int main(){
    int i = 0;
    char ch;

    printf("Enter your password. Hit ENTER to confirm.\n");
    printf("Password:");

    while(getch() != ENTER){
        ch = getch();
        pwd[i++] = ch;
        printf("* \b");
    }
    if(ch == ENTER || ch == TAB){
        pwd[i] = '\0';
    }

    printf("\n\nPassword:%s\nLength:%d\n\n", pwd, i);
    return 0;
}
#包括
#包括
#定义并输入13
#定义选项卡9
char-pwd[100];
int main(){
int i=0;
char ch;
printf(“输入密码。按Enter键确认。\n”);
printf(“密码:”);
while(getch()!=ENTER){
ch=getch();
pwd[i++]=ch;
printf(“*\b”);
}
如果(ch==输入| | ch==制表符){
pwd[i]='\0';
}
printf(“\n\n密码:%s\n长度:%d\n\n”,pwd,i);
返回0;
}

您应该调用
initscr()。因此,尝试这样做:

int main(){
    int i = 0;
    char ch;

    initscr();
    // ...

更多。

看起来您正从
getch()
返回
ERR

这不等于
ENTER
,因此循环被输入并重复。最终,您在
pwd
中用完了空间,但仍在它之外继续写作。分段错误意味着您试图写入一些不可写入的地址

您还有一个错误,即每个循环调用两次
getch()
,即使在修复循环/segfault问题后,也会给您带来麻烦。

关于:

while(getch() != ENTER){
    ch = getch();
这将在循环中每次传递2个字符。不是你想要的。建议:

while( ( ch = getch() ) != ENTER ){
 WINDOW *mainwin;
 mainwin = initscr();   /* start the curses mode with default window */
 clear()    /* clear the default window */
 ...
 raw();     /* stop terminal driver from interpreting key strokes */ 
 cbreak();  /* input chars without waiting for newline */
 
 nodelay( mainwin, true); /* causes getch() to wait for a key rather than returning ERR */
 keypad( mainwin, true ); /* program must handle all meta keys including newline */

 noecho();  /* stop terminal echo while entering password */

 size_t i = 0;
 while( i < (sizeof( pwd ) -1) && ( ch = getch() ) != ENTER )
 {
     pwd[i] = ch;
     i++;

     printw( "*" );
     refresh();
 }

 echo();               /* resume echoing characters on terminal */
 keypad( mainwin, false );      /* stop passing keypad chars to program */
 noraw();              /* terminal driver resumes interpreting key strokes */

 pwd[i] = '\0';        /* NUL terminate the string */   
 ...
 endwin();
要避免在用户输入字符时回显字符,请执行以下操作: 您需要关闭echo
,然后对于用户输入的每个字符,输出一个掩蔽字符,如
*

由于数组
pwd[]
的长度只有100个字符,因此需要将用户可以输入的字符数限制为99个(为后面的NUL字节留出空间),建议:

while( ( ch = getch() ) != ENTER ){
 WINDOW *mainwin;
 mainwin = initscr();   /* start the curses mode with default window */
 clear()    /* clear the default window */
 ...
 raw();     /* stop terminal driver from interpreting key strokes */ 
 cbreak();  /* input chars without waiting for newline */
 
 nodelay( mainwin, true); /* causes getch() to wait for a key rather than returning ERR */
 keypad( mainwin, true ); /* program must handle all meta keys including newline */

 noecho();  /* stop terminal echo while entering password */

 size_t i = 0;
 while( i < (sizeof( pwd ) -1) && ( ch = getch() ) != ENTER )
 {
     pwd[i] = ch;
     i++;

     printw( "*" );
     refresh();
 }

 echo();               /* resume echoing characters on terminal */
 keypad( mainwin, false );      /* stop passing keypad chars to program */
 noraw();              /* terminal driver resumes interpreting key strokes */

 pwd[i] = '\0';        /* NUL terminate the string */   
 ...
 endwin();
WINDOW*mainwin;
mainwin=initscr();/*使用默认窗口启动诅咒模式*/
clear()/*清除默认窗口*/
...
原始();/*停止终端驱动程序解释按键*/
cbreak();/*在不等待换行的情况下输入字符*/
诺德利(梅因温,真的);/*导致getch()等待一个键,而不是返回ERR*/
键盘(mainwin,true);/*程序必须处理包括换行符在内的所有元键*/
noecho();/*输入密码时停止终端回显*/
尺寸i=0;
而(i<(sizeof(pwd)-1)和&(ch=getch())!=ENTER)
{
pwd[i]=ch;
i++;
printw(“*”);
刷新();
}
echo();/*在终端上恢复回显字符*/
键盘(mainwin,false);/*停止向程序传递键盘字符*/
noraw();/*终端驱动程序继续解释按键*/
pwd[i]='\0';/*NUL终止字符串*/
...
endwin();
以上可能有点过分

由于存在一些问题,建议不要使用C库函数:
getpass()


如果使用
raw()
函数,则程序还需要处理用户的退格(和类似)字符。

我尝试过,但在启动程序时得到了这样的结果:
输入密码。点击回车确认。密码:(B)0
@tecn603——好的,但这解决了您的问题,对吗?插入
initscr()星号不再打印,但程序无论如何都无法运行,如果我插入字符,它们不会被遮挡是的,但这不是您所要求的。:)无论如何,我想你需要打电话给noecho()
。这能回答你的问题吗?我曾设想,分段错误取决于我试图写入其他内存地址,但实际上,即使我不插入任何输入,程序也会尝试写入。从我看到的情况来看,getch()似乎返回了-1,这就是问题所在。