strcat在简单的getch状密码输入上抛出细分故障
-
28-09-2019 - |
题
我正在使用Linux,并且有一个自定义函数,其中返回ASCII int
当前关键的类似 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阵列进行通行证,但是第二个我输入了一个字母。该函数自行起作用,但在循环中不工作,至少不像getch()在Windows系统上。
您的示例您会看到什么错?我很喜欢学习这个。
编辑: 多亏了我提出以下愚蠢的代码的答案:
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);
解决方案
问题是 strcat
期望 char *
作为其第二个论点(它串联了两个字符串)。您没有两个字符串,您有一个字符串和一个 char
.
如果要添加 c
到达 pass
, ,只保留一个int i
存储当前大小 pass
然后做类似的事情
pass[i] = (char) c
.
确保无效 pass
完成后(通过将最后一个位置设置为0)。
其他提示
单个字符与包含单个字符的字符串不同。
换句话说,“ A”和“ A”是非常不同的事情。
C中的字符串是无效的一系列字符阵列。您的“通行证”是20个字符的阵列 - 一块内存,其中包含20个字符的空间。
函数mygetch()返回char。
您需要做的是将C插入其中一个空间。
代替“ strcat(Pass,c)”,您想做“通过[i] = C”,我以零开始,每次调用mygetch()时会增加一个。
然后,当循环完成时,您需要进行通行[i] =' 0',而我等于您称为mygetch()的次数,以添加null终结器。
您是另一个问题是,您没有设置C的值,您第一次检查它是否是' n'。进行比较之前,您想致电mygetch():
int i = 0;
for (;;)
{
c = mygetch();
if (c == '\n')
break;
c = mygetch();
pass[i++] = c;
}
pass[i] = '\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个字符,第一个循环可能会更好。