如何使C程序在接受标准输入的同时连续执行?
以下是myprogram.c的摘录:如何使C程序在接受标准输入的同时连续执行?,c,C,以下是myprogram.c的摘录: int main(int argc, char *argv[]) { UserOptions opt; DmtxEncode *enc; unsigned char codeBuffer[BUFFER_SIZE]; int codeBufferSize; opt = GetDefaultOptions(); /* Read input data into buffer */ codeBufferSize = Re
int main(int argc, char *argv[])
{
UserOptions opt;
DmtxEncode *enc;
unsigned char codeBuffer[BUFFER_SIZE];
int codeBufferSize;
opt = GetDefaultOptions();
/* Read input data into buffer */
codeBufferSize = ReadInputData(codeBuffer, &opt);
//do something with the input data
exit(0);
}
static size_t ReadInputData(unsigned char *codeBuffer, UserOptions *opt)
{
int fd;
ssize_t bytesRead;
size_t bytesReadTotal;
/* Open file or stdin for reading */
fd = (opt->inputPath == NULL) ? 0 : open(opt->inputPath, O_RDONLY);
/* Read input contents into buffer */
for(bytesReadTotal = 0;; bytesReadTotal += bytesRead) {
bytesRead = read(fd, codeBuffer + bytesReadTotal, BUFFER_SIZE);
if(bytesRead == 0)
break;
}
return bytesReadTotal;
}
这以echo 1234 | myprogram
的形式接收输入,程序生成输出并终止
我想让这个程序连续执行并接受用户输入,其中两个单独的输入由换行符(\n
)区分。比如说,我想把1234\n 5678\n 6363\n
作为输入。程序应首先获取输入1234
,为其生成输出,然后查看是否有换行符,并将5678
视为第二个输入,生成输出,依此类推
我已尝试修改ReadInputData
函数,如下所示:
static size_t ReadInputData(unsigned char *codeBuffer, UserOptions *opt) {
int fd;
ssize_t bytesRead;
size_t bytesReadTotal;
size_t startOfBlock;
unsigned char tmpBuffer[BUFFER_SIZE];
/* Open file or stdin for reading */
fd = (opt->inputPath == NULL) ? 0 : open(opt->inputPath, O_RDONLY);
for (bytesReadTotal = 0;; bytesReadTotal += bytesRead) {
startOfBlock = tmpBuffer + bytesReadTotal;
bytesRead = read(fd, startOfBlock, BUFFER_SIZE);
for (int i = startOfBlock; i < startOfBlock + bytesRead; i++) {
if (tmpBuffer[i] != '\n')
codeBuffer[i] = tmpBuffer[i];
else
break;
}
}
return bytesReadTotal;
}
static size_t
ReadInputData(unsigned char *codeBuffer, UserOptions *opt) {
int fd;
ssize_t bytesRead;
size_t bytesReadTotal;
unsigned char* startOfBlock;
unsigned char tmpBuffer[BUFFER_SIZE];
/* Open file or stdin for reading */
fd = (opt->inputPath == NULL) ? 0 : open(opt->inputPath, O_RDONLY);
for (bytesReadTotal = 0;; bytesReadTotal += bytesRead) {
startOfBlock = tmpBuffer + bytesReadTotal;
bytesRead = read(fd, startOfBlock, DMTXWRITE_BUFFER_SIZE);
if (bytesRead == 0)
break;
if (bytesRead == -1)
FatalError(EX_IOERR, _("Message read error"));
else if (bytesReadTotal > DMTXWRITE_BUFFER_SIZE)
FatalError(EX_DATAERR, _("Message to be encoded is too large"));
for (int i = 0; i < bytesRead; i++) {
if (startOfBlock[i] != '\n')
codeBuffer[i] = startOfBlock[i];
else
break;
}
}
这解决了换行符的问题,但程序在接受一个输入而不是接受连续输入后退出。main
的内容在while(1)
循环中
编辑:
main
带while循环。无退出(0)
出现在main
中
int main(int argc, char *argv[])
{
UserOptions opt;
DmtxEncode *enc;
unsigned char codeBuffer[BUFFER_SIZE];
int codeBufferSize;
opt = GetDefaultOptions();
while(1){
/* Read input data into buffer */
codeBufferSize = ReadInputData(codeBuffer, &opt);
//do something with the input data
}
}
ReadInputData
中的代码有很多问题。最大的问题是,您的输入不会在调用之间保留read
将获取所有可用数据(直到您传入的计数)。因此,如果恰好有两行可用,ReadInputData
将把这两行都放入tmpBuffer
。保存第一个,当tmpBuffer
超出范围时,将丢弃第二个
您需要一个跨调用保留的缓冲区
另一个问题是这个测试:
else if (bytesReadTotal > DMTXWRITE_BUFFER_SIZE)
如果DMTXWRITE\u BUFFER\u SIZE
非常小,以至于前两行相加大于此值,则将出现致命错误。我很确定你真的需要这样的东西:
if (bytesReadTotal == BUFFER_SIZE)
{
FatalError(EX_DATAERR, _("Message to be encoded is too large"));
}
bytesRead = read(fd, startOfBlock, min(DMTXWRITE_BUFFER_SIZE BUFFER_SIZE, BUFFER_SIZE - bytesReadTotal));
i、 e.在进行读取之前,您需要确保缓冲区中有空间。此外,阅读超出允许范围的内容是没有意义的
回到第一个问题,有两种方法可以解决这个问题
tmpBuffer
和ByteReadTotal
静态变量结构中
,并将指向该结构的指针传递到调用中文件
。如果您使用标准的库缓冲文件
API而不是原始的Unix系统调用,您的生活就会轻松得多。甚至还有一个函数(许多注释中都告诉您要使用),它读取并返回输入到下一个\n
。它被称为
刚刚发现另一个问题。您每次调用
ReadInputData
时都会打开该文件。stdin
没有问题,因为您只使用文件描述符0。但是,对于任何其他文件,您每次都只会读取第一行,直到进程用完文件描述符。在我上面的解决方案中,您必须打开该文件在main
中,将文件描述符添加到ReadBuffer
结构中。如果这样做,您肯定是在重新创建C库文件
这是一个粗略的重新实现
int main(int argc, char *argv[])
{
UserOptions opt;
DmtxEncode *enc;
unsigned char codeBuffer[BUFFER_SIZE];
ssize_t codeBufferSize;
opt = GetDefaultOptions();
FILE* input = opt->inputPath == NULL ? stdin : open(opt->inputPath, "r");
if (input == NULL)
{
// Handle the error
}
while(1)
{
/* Read input data into buffer */
codeBufferSize = fgets(codeBuffer, BUFFER_SIZE, input);
if (codeBufferSize == -1)
{
// Handfle IO error
}
else if (codeBufferSize == 0)
{
// reached end of file
}
else if (codeBuffer[codeBufferSize - 1] != '\n')
{
// Handle input truncated because line was too long
}
else
{
//do something with the input dat
}
}
if (input != NULL)
{
fclose(input);
}
}
我不确定您是否可以读取
\n
作为输入的一部分。通常它是一个输入终止符。您可以让程序循环,在每次操作后读取输入。@Paul当然可以读取“\n”;实际上这是常见的错误源。@JL2210没有fp
;-)。您必须检查read()
的返回值是否为0。为什么不简单地用fgets
逐行读取输入?fgets
可以处理二进制数据,如果它由\n
分隔(您在问题中说)。虽然用换行符分隔二进制数据有点奇怪和局限,因为数据本身无法容纳\n
字符。
int main(int argc, char *argv[])
{
UserOptions opt;
DmtxEncode *enc;
unsigned char codeBuffer[BUFFER_SIZE];
ssize_t codeBufferSize;
opt = GetDefaultOptions();
FILE* input = opt->inputPath == NULL ? stdin : open(opt->inputPath, "r");
if (input == NULL)
{
// Handle the error
}
while(1)
{
/* Read input data into buffer */
codeBufferSize = fgets(codeBuffer, BUFFER_SIZE, input);
if (codeBufferSize == -1)
{
// Handfle IO error
}
else if (codeBufferSize == 0)
{
// reached end of file
}
else if (codeBuffer[codeBufferSize - 1] != '\n')
{
// Handle input truncated because line was too long
}
else
{
//do something with the input dat
}
}
if (input != NULL)
{
fclose(input);
}
}