Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使C程序在接受标准输入的同时连续执行?_C - Fatal编程技术网

如何使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

以下是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 = 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
    静态变量

  • 将它们放入
    结构中
    ,并将指向该结构的指针传递到调用中

  • 然后,您需要添加所有代码来管理缓冲区等等,但是C库中已经存在这样的东西,它被称为
    文件
    。如果您使用标准的库缓冲
    文件
    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);
       }
    }