scanf(),Linux的shell输入处理不同,为什么?
我得到以下内容。
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()
能够以相同的方式处理这两种情况的正确方法是什么?
I got the following.
my-app.c
file:
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
file:
jdons f4$dsef35fs
So:
$ ./my-app < credentials.data
username-len: 0, password-len: 0
and:
$ cat credentials.data | ./my-app
username-len: 5, password-len: 10
- Why in the both ways the input is handled differently? What is the difference to be so?
- What is the right way to use
scanf()
to be able to handle both cases in the same way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
此行:
本质上是不安全的(除非您可以完全控制程序标准输入上显示的内容)。
"%s"
格式表示读取任意长的非空白字符序列。无论目标数组有多长,足够长的单词(例如,由你的猫坐在键盘上引起的)都会溢出它。您可以使用长度修饰符来限制输入的大小。例如(未经测试):
或者更好:
但最好使用
fgets()
一次读取整行,然后使用sscanf()
> 阅读完该行后对其进行处理。您的
printf
调用中可能存在问题:strlen()
返回size_t
类型的结果,但"%ld"< /code> 需要一个
long int
类型的参数。如果您的系统支持,您可以使用"%zu"
打印size_t
类型的值,但这并不是 100% 可移植的。或者,您可以将size_t
值转换为 unsigned long:有可能(但不太可能)导致非零
size_t
值显示为 0 。This line:
is inherently unsafe (unless you have complete control over what will appear on your program's standard input). The
"%s"
format says to read an arbitrarily long sequence of non-whitespace characters. However long the target array is, a sufficiently long word (say, caused by your cat sitting on the keyboard) will overflow it.You can use a length modifier to limit the size of the input. For example (untested):
or, better:
But it's probably better to use
fgets()
to read an entire line at a time, and then use, say,sscanf()
to process the line after you've read it.And there's a possible problem in your
printf
call:strlen()
returns a result of typesize_t
, but"%ld"
requires an argument of typelong int
. If your system supports it, you can use"%zu"
to print a value of typesize_t
, but that's not 100% portable. Or you can convert thesize_t
value to, say, unsigned long:It's possible, but not very likely, that that could cause non-zero
size_t
values to be displayed as 0.巴兰金,
嗯……这是一个有趣的行为。
两种标准输入间接技术都对我有效(如预期)...
也许您只需要在
credentials.data
文件末尾添加一个行结束符?干杯。基思.
Barankin,
Hmmm... that's an interesting behavior.
Both standard input indirection techniques work (as expected) for me...
Maybe you just need an end-of-line-character on the end of your
credentials.data
file?Cheers. Keith.
检查您的credentials.data末尾是否包含换行符? cat 命令自动将其附加到文件的最后一行之后。
Check if your credentials.data contains a a newline character at the end? cat command appends it after the last line of file automatically.
尽管我尽力了,但我无法重现与您相同的问题。我什至手动从credentials.data文件中删除了行尾字节,它仍然可以正常工作(正如它应该的那样)。您正在运行什么版本的 Linux 或 shell?
As much as I try, I can't manage to reproduce the same problem as you. I even manually removed the end of line byte from the
credentials.data
file and it still works fine (as it should). What version of Linux or the shell are you running?