3

我正在使用 Linux,并且有一个自定义函数,它返回int当前密钥类型的ASCII 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;
}

不幸的是,我收到了来自 GCC 的警告:

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 数组进行传递,但第二次我键入了一个它的段错误的字母。该函数独立工作,但不在循环中,至少不像 Windows 系统上的 getch() 那样。

你能看出我的例子有什么问题吗?我很享受学习这个。

编辑:感谢答案,我想出了以下愚蠢的代码:

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);
4

3 回答 3

3

问题是它strcat期望 achar *作为它的第二个参数(它连接两个字符串)。你没有两个字符串,你有一个字符串和一个char

如果要添加c到末尾,只需保留一个存储当前大小的passint ,然后执行类似的操作ipass

pass[i] = (char) c.

完成后确保空终止pass(通过将最后一个位置设置为 0)。

于 2010-11-04T04:18:22.640 回答
1

单个字符与包含单个字符的字符串不同。

换句话说,“a”和“a”是非常不同的东西。

在 C 中,字符串是一个以 null 结尾的字符数组。您的“通行证”是一个包含 20 个字符的数组 - 一块包含 20 个字符的空间的内存块。

函数 mygetch() 返回一个字符。

您需要做的是将 c 插入其中一个空格。

而不是“strcat(pass, c)”,你想做“pass[i] = c”,其中 i 从零开始,每次调用 mygetch() 时递增 1。

然后你需要做一个 pass[i] = '\0',当循环完成时,i 等于你调用 mygetch() 的次数,以添加空终止符。

你的另一个问题是你没有为c设置一个值,第一次检查它是否是'\ n'。您想在进行比较之前调用 mygetch() :

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

    c = mygetch();
    pass[i++] = c;
}
pass[i] = '\0';
于 2010-11-04T04:25:54.907 回答
0

除了使用两个字符串的正确诊断问题之外strcat()- 为什么忽略编译器警告,或者如果没有警告,为什么不打开警告?正如我所说,除了这个问题之外,你还需要考虑如果你得到 EOF 会发生什么,你还需要担心 'c' 的初始值(它可能意外地是 '\n' 虽然它可能是't)。

这导致这样的代码:

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()不必跳过任何内容。但是,使用固定大小的 1 个字符,您可能最好使用第一个循环。

于 2010-11-04T04:36:25.530 回答