- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我试图运行两个程序。
<强> Case 1
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int n;
int k = 10;
int ret_val = 0;
ret_val = write (0, &k, sizeof(int));
if (-1 == ret_val)
{
printf ("Failed to write");
exit (EXIT_FAILURE);
}
scanf ("%d", &n);
printf ("Integer read is %d \n", n);
return 0;
}
然后我尝试了下一个。
<强> Case 2
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main()
{
int n;
int k = 10;
int ret_val = 0;
/* Open file from which content shall be inserted to stdin_buffer */
int source_fd = open ("file_in.txt", O_CREAT | O_RDWR, S_IRWXU);
if (-1 == source_fd)
{
printf ("Failed to open file for reading");
exit (EXIT_FAILURE);
}
int stdin_fd;
/* Close STDIN_FILENO */
close(0);
/* dup the source */
stdin_fd = dup (source_fd);
if (-1 == stdin_fd)
{
printf ("Failed to dup");
exit (EXIT_FAILURE);
}
/* write to stdin_buffer (content will be taken from file_in.txt) */
ret_val = write (stdin_fd, &k, sizeof(int));
if (-1 == ret_val)
{
printf ("Failed to write to stdin_buffer");
exit (EXIT_FAILURE);
}
scanf ("%d", &n);
printf ("Integer read is %d \n", n);
close(source_fd);
return 0;
}
现在,在第一种情况下,我无法写入标准输入。在第二种情况下,我能够从文件“file_in.txt”获取输入,并将内容发送到标准输入缓冲区。
对于为什么我的第一个案例没有成功,我无法得到很好的解释。有人可以解释一下吗?
stdin
应该像任何其他文件一样,对吗?如果是写保护就好了。但是当我重定向输入时(在第二种情况下),没有“权限被拒绝”问题。该代码似乎不可移植。是否有一种可移植且安全的方法来从文件重定向标准输入?
在查看了评论后,我想出了一个更好的工作代码。我想要一些关于此代码的反馈
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#define LEN 100
int main()
{
int n;
char buffer[LEN];
memset (buffer, '\0', LEN);
int ret_val = 0;
/* Open file from which content shall be inserted to stdin_buffer */
int source_fd = open ("file_in.txt", O_CREAT | O_RDONLY, S_IRWXU);
if (-1 == source_fd)
{
perror ("Failed to open file for reading");
exit (EXIT_FAILURE);
}
/* Temp stdin_buffer */
int temp_fd = open ("temp_in.txt", O_CREAT | O_RDWR, S_IRWXU);
if (-1 == temp_fd)
{
perror ("Failed to open temp stdin");
exit (EXIT_FAILURE);
}
int stdin_fd;
/* Close STDIN_FILENO */
close(0);
/* dup the source */
stdin_fd = dup (temp_fd);
if (-1 == stdin_fd)
{
perror ("Failed to dup");
exit (EXIT_FAILURE);
}
ret_val = read (source_fd, buffer, LEN);
if (-1 == ret_val)
{
perror ("Failed to read from source");
exit (EXIT_FAILURE);
}
else
{
printf ("%s read from Source file\n", buffer);
}
/* write to stdin_buffer (content taken from file_in.txt) */
ret_val = write (stdin_fd, buffer, LEN);
if (-1 == ret_val)
{
perror ("Failed to write to stdin_buffer");
exit (EXIT_FAILURE);
}
ret_val = lseek (stdin_fd, 0, SEEK_SET);
if (-1 == ret_val)
{
perror ("Failed lseek");
exit (EXIT_FAILURE);
}
ret_val = scanf ("%d", &n);
if (-1 == ret_val)
{
perror ("Failed to read stdin_buffer");
exit (EXIT_FAILURE);
}
printf ("Integer read is %d \n", n);
close(source_fd);
return 0;
}
最佳答案
在第一个程序中,3 个空字节和一个换行符(可能)被写入屏幕(不一定按照这个顺序);然后程序尝试从键盘读取(假设命令行上没有 I/O 重定向)。写入标准输入不会加载输入缓冲区。您经常可以写入标准输入(并从标准输出和标准错误读取),因为经典技术使用 O_RDWR
打开文件描述符。然后将其连接到标准 I/O channel 。但是,不能保证您可以这样做。 (顺便说一句,第一个程序需要 <unistd.h>
。)
第二个程序有太多未定义的行为,很难分析。 open()
call 需要三个参数,因为它包含 O_CREAT
;第三个参数是文件的模式(例如 0644
)。您没有检查open()
成功了。您不检查写入是否成功;它不会,因为文件描述符已打开 O_RDONLY
(或者更确切地说, source_fd
打开 O_RDONLY
,并且 dup()
将该模式复制到文件描述符 0),这意味着 write()
将失败。不检查输入操作(您不确保 scanf()
成功)。 (第二个程序实际上并不需要 <sys/types.h>
或 <sys/stat.h>
。)
基本上,您对正在发生的事情一无所知,因为您没有检查任何关键函数调用。
请注意,错误消息应写入标准错误,并应以换行符终止。
我让第一个程序按所述工作(Mac OS X 10.10 Yosemite,GCC 4.8.1),尽管很难证明空字节已写入标准输入(但在那里写入了换行符)。然后我可以输入 10(或 20、或 100、或……)加上 Return,然后就会打印该整数。
第二个程序在 scanf()
上失败因为当您尝试读取时,文件指针位于文件末尾。您可以通过程序的这个变体看到:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main(void)
{
/* Open file from which content shall be inserted to stdin_buffer */
int source_fd = open ("file_in.txt", O_CREAT | O_RDWR, S_IRWXU);
if (-1 == source_fd)
{
printf ("Failed to open file for reading\n");
exit (EXIT_FAILURE);
}
close(0);
int stdin_fd = dup (source_fd);
if (-1 == stdin_fd)
{
printf("Failed to dup\n");
exit(EXIT_FAILURE);
}
int k = 10;
int ret_val = write(stdin_fd, &k, sizeof(int));
if (-1 == ret_val)
{
printf("Failed to write to stdin_buffer\n");
exit(EXIT_FAILURE);
}
int rc;
int n;
if ((rc = scanf("%d", &n)) != 1)
printf("Failed to read from standard input: rc = %d\n", rc);
else
printf("Integer read is %d (0x%08x)\n", n, n);
close(source_fd);
return 0;
}
它产生:
Failed to read from standard input: rc = -1
如果在读取之前倒回文件,则会返回 0;写入文件的二进制数据不是整数的有效字符串表示形式。
我写了一个小函数err_exit()
因为它允许页面上的代码更小。我在几个地方修改了您的代码以报告先前函数的返回值。缺少输入并不是错误。当您读取 0 字节时,这不是错误;而是错误。是EOF。当有数据要读取但不是整数值的文本格式时,不会发生任何转换,但这不是错误。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define LEN 100
static void err_exit(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(void)
{
int n = 99;
char buffer[LEN];
memset(buffer, '\0', LEN);
int ret_val = 0;
/* Open file from which content shall be inserted to stdin_buffer */
int source_fd = open("file_in.txt", O_CREAT | O_RDONLY, S_IRWXU);
if (-1 == source_fd)
err_exit("Failed to open file for reading");
/* Temp stdin_buffer */
int temp_fd = open("temp_in.txt", O_CREAT | O_RDWR, S_IRWXU);
if (-1 == temp_fd)
err_exit("Failed to open temp stdin");
/* Close STDIN_FILENO */
close(0);
/* dup the source */
int stdin_fd = dup(temp_fd);
if (-1 == stdin_fd)
err_exit("Failed to dup");
ret_val = read(source_fd, buffer, LEN);
if (-1 == ret_val)
err_exit("Failed to read from source");
else
printf("(%d bytes) <<%s>> read from Source file\n", ret_val, buffer);
/* write to stdin_buffer (content taken from file_in.txt) */
ret_val = write(stdin_fd, buffer, LEN);
if (-1 == ret_val)
err_exit("Failed to write to stdin_buffer");
ret_val = lseek(stdin_fd, 0, SEEK_SET);
if (-1 == ret_val)
err_exit("Failed lseek");
ret_val = scanf("%d", &n);
if (-1 == ret_val)
err_exit("Failed to read stdin_buffer");
printf("Integer read is %d (ret_val = %d)\n", n, ret_val);
close(source_fd);
return 0;
}
输出:
(0 bytes) <<>> read from Source file
Integer read is 99 (ret_val = 0)
何时 scanf()
无法读取值,它(通常)不会将任何内容写入相应的变量。这就是99幸存下来的原因。如果你想要scanf()
可以读取的数据作为整数,您需要:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define LEN 100
static void err_exit(const char *msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
int main(void)
{
int n = 99;
char buffer[LEN] = "";
int ret_val = 0;
/* Open file from which content shall be inserted to stdin */
int source_fd = open("file_in.txt", O_CREAT | O_RDONLY, S_IRWXU);
if (-1 == source_fd)
err_exit("Failed to open file for reading");
/* Temp stdin */
int temp_fd = open("temp_in.txt", O_CREAT | O_RDWR, S_IRWXU);
if (-1 == temp_fd)
err_exit("Failed to open temp stdin");
/* Close STDIN_FILENO */
close(0);
/* dup the source */
int stdin_fd = dup(temp_fd);
if (-1 == stdin_fd)
err_exit("Failed to dup");
ret_val = read(source_fd, buffer, LEN);
if (-1 == ret_val)
err_exit("Failed to read from source");
else
printf("(%d bytes) <<%s>> read from Source file\n", ret_val, buffer);
/* write to stdin (content taken from file_in.txt) */
ret_val = write(stdin_fd, "10\n", sizeof("10\n")-1);
if (-1 == ret_val)
err_exit("Failed to write to stdin");
ret_val = lseek(stdin_fd, 0, SEEK_SET);
if (-1 == ret_val)
err_exit("Failed lseek");
ret_val = scanf("%d", &n);
if (-1 == ret_val)
err_exit("Failed to read stdin");
printf("Integer read is %d (ret_val = %d)\n", n, ret_val);
close(source_fd);
return 0;
}
输出:
(0 bytes) <<>> read from Source file
Integer read is 10 (ret_val = 1)
关于c - 使 stdin 以安全且可移植的方式可写,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26696811/
我是 Mercurial 的新手,并且不知何故仍处于评估过程中,所以这四个概念对我来说有点困惑。有些被提到等同于 Git 的 Staging/Index 概念,有些甚至比 Git 的 Staging
如何将在某些网站 (www.example1.com) 上用某种语言即 (java) 制作的 session 传送到用其他语言制作的网站,即在某些其他网站上的 (php),即 (www.example
我有以下代码行我想移植到 Torch Matmul rotMat = xmat @ ymat @ zmat 我能知道这是不是正确的顺序: rotMat = torch.matmul(xmat, tor
我正在尝试移植一个内部有一个联合的 C 结构。 Winapi.Winsock2.pas 中的默认结构记录中缺少某些字段。 但这是正确的方法吗?谢谢。 typedef struct _WSACOMPLE
我想将基于 webkit 的浏览器移植到我的堆栈中。谁能介绍一下 webkit 浏览器引擎的组织结构?目前我所知道的是它具有用于呈现 html 和解析 javascript 的核心。我想了解更多,比如
我目前有一个 ActiveX 控件,它链接到许多 c/c++ dll。问题是我们现在需要此控件在 IE 以外的浏览器(最重要的是 Firefox)上运行。 在我看来,我有以下选择: 将控件编写为 fi
我正在尝试在 Objective-C 中重写 Java 库。我想将其重写为 API,以便需要实现某些方法。我已经开始尝试重写代码,但遇到了一些问题。 Objective-C 是否支持抽象类? 如果没有
我已经有一段时间没有接触 SQL 了,所以我需要重新学习一下。我的计算机上运行着一个 SQL 数据库,我的服务器是 localhost。我在 VB.Net 中制作了一个连接到该数据库的应用程序。一切都
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit th
运行命令时出现错误 [root@himanshi busybox-1.20.2]# make ARCH=arm CROSS_COMPILE=arm-unknown-linux-gnueabi- CON
我需要将为 iPhone 编写的现有游戏移植到 Flash。 iPhone 游戏主要是用纯 C 而不是 Objective C 编写的。 我想知道是否有任何好的工具可以将 C 代码直接转换为 Acti
我将要在 Smalltalk (Pharo) 中构建一个项目。还有一个 python 库,我打算将其用于相同的目的。现在,有 3 个选项: 那些 python 库的 Smalltalk 包装器 将 p
我必须在 GPU 上移植一个广泛使用随机数的结构。一切都可以毫无问题地移植,但随机生成器函数是唯一在该类的所有函数中被广泛调用的函数。我虽然可以简单地将它重新实现为类本身的内部设备函数。下面我放了一个
我对整个移植问题有点陌生,因为 Android SDK 提供的模拟器速度很慢,所以我解决了这个问题。 我下载了 android-x86-3.2-RC2-eeepc 和 android-x86-3.2-
我们的数据库 (PostgreSQL 9.x) 中有一些 PL/pgSQL 存储过程。 这些是严格顺序的,在某些情况下,可能会非常慢。 我们正在考虑将它们移植到 PL/Java、PL/Python 或
我有一个 Android 应用程序可以处理圆顶图像。出于性能原因,我想用 C++ 编写应用程序的某些部分,然后通过 NDK 调用这些方法。我是否需要一个特定的 C++ 编译器(例如用于嵌入式系统)或者
我正在从事一个将一大堆 OS-9(微软件)代码移植到 linux 的项目。 OS-9 中的信号处理功能允许您创建自己的信号,或者至少它是如何实现的(intercept() 函数)。我对 linux 信
目前我有这个 gtk2 代码: GList *input_devices = gdk_devices_list(); while(input_devices) { GdkDevice *devic
我正在尝试移植 Aether.Physics2D从 C# 到 Xojo 的库。这本质上是 Farseer 物理引擎的调整版本。大部分已经完成,但有一部分源代码我无法解决(可能是因为 C# 不是我的主要
我们正在开发采用 RISCV 架构的多核处理器。 我们已经为单核 RISCV 处理器移植了 Linux,它正在我们自己的基于 FPGA 的主板上使用 busybox rootfs。 我现在想为多核 R
我是一名优秀的程序员,十分优秀!