我得到了以下内容。
my-app.c
档案:
char username[USERNAME_MAX_LEN] = "\0";
char password[PASSWORD_MAX_LEN] = "\0";
scanf("%s %s", username, password);
printf("username-len: %ld, password-len: %ld\n", strlen(username), strlen(password));
credentials.data
档案:
jdons f4$dsef35fs
所以:
$ ./my-app < credentials.data
username-len: 0, password-len: 0
和
$ cat credentials.data | ./my-app
username-len: 5, password-len: 10
scanf()
以同样的方式处理这两种情况的正确方法是什么?答案 0 :(得分:3)
这一行:
scanf("%s %s", username, password);
本质上是不安全的(除非您完全控制程序标准输入中显示的内容)。 "%s"
格式表示读取任意长的非空白字符序列。无论目标数组多长,一个足够长的单词(比如由你的猫坐在键盘上引起)都会溢出它。
您可以使用长度修改器来限制输入的大小。例如(未经测试):
scanf("%36s %36s", username, password);
或者,更好:
scanf("%*s, %*s", USERNAME_MAX_LEN, username, PASSWORD_MAX_LEN, password);
但最好一次使用fgets()
来读取整行,然后使用sscanf()
来处理读取后的行。
您的printf
电话可能存在问题:
printf("username-len: %ld, password-len: %ld\n",
strlen(username),
strlen(password));
strlen()
会返回size_t
类型的结果,但"%ld"
需要类型为long int
的参数。如果您的系统支持它,您可以使用"%zu"
打印size_t
类型的值,但这不是100%可移植的。或者,您可以将size_t
值转换为unsigned long:
printf("username-len: %lu, password-len: %lu\n",
(unsigned long)strlen(username),
(unsigned long)strlen(password));
可能(但不太可能)可能导致非零size_t
值显示为0.
答案 1 :(得分:2)
Barankin,
嗯......这是一个有趣的行为。标准输入间接技术对我来说都是有用的(如预期的那样)......
landkrc@lasun175:/home/user/landkrc/crap
$ cat lg.c
#include <stdio.h>
#include <strings.h>
#define USERNAME_MAX_LEN 36
#define PASSWORD_MAX_LEN 36
int main(int argc, char *argv[])
{
printf("Hello, world\n");
char username[USERNAME_MAX_LEN];
char password[PASSWORD_MAX_LEN];
*username = 0;
*password = 0;
scanf("%s %s", username, password);
printf("username-len: %ld, password-len: %ld\n", strlen(username), strlen(password));
return 0;
}
landkrc@lasun175:/home/user/landkrc/crap
$ cc -V
cc: Sun C 5.8 2005/10/13
usage: cc [ options] files. Use 'cc -flags' for details
landkrc@lasun175:/home/user/landkrc/crap
$ cc -o lg lg.c
landkrc@lasun175:/home/user/landkrc/crap
$ echo '12345678 1234567890
> ' >data.txt
landkrc@lasun175:/home/user/landkrc/crap
$ lg <data.txt
username-len: 8, password-len: 10
landkrc@lasun175:/home/user/landkrc/crap
$ cat data.txt | lg
username-len: 8, password-len: 10
也许您只需要在credentials.data
文件的末尾添加行尾字符?
干杯。基思。
答案 2 :(得分:0)
检查您的credentials.data末尾是否包含换行符? cat命令会自动将它附加到文件的最后一行之后。
答案 3 :(得分:0)
尽我所能,我无法像你一样重现同样的问题。我甚至手动从credentials.data
文件中删除了行结束字节,它仍然可以正常工作(应该如此)。你在运行什么版本的Linux或shell?