以下是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;
}
并将其工作封装main
在一个while(1)
循环中,但这只会产生单个输入的输出并终止程序。
有人可以帮我弄清楚我在做什么错吗?
编辑:根据建议,我修改了ReadInputData
如下功能:
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循环。不exit(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_BUFFER_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));
也就是说,在读取之前,您需要确保缓冲区中有空间。另外,阅读没有意义,没有超出您的允许范围。
回到第一个问题,有两种方法可以解决此问题。
品牌tmpBuffer
和bytesReadTotal
静态变量
将它们放在a中struct
,并将指向它的指针传递给通话
struct ReadBuffer
{
char tmpBuffer[BUFFER_SIZE];
size_t bytesReadTotal;
}
int main(int argc, char *argv[])
{
struct ReadBuffer buffer;
buffer.bytesReadTotal = 0;
// stuff
codeBufferSize = ReadInputData(codeBuffer, &opt, &buffer);
// stuff
}
static size_t ReadInputData(unsigned char *codeBuffer, UserOptions *opt, struct ReadBuffer *buffer)
{
// stuff
startOfBlock = buffer.tmpBuffer + buffer.bytesReadTotal;
// and so on
}
然后,您需要添加所有代码来管理缓冲区,依此类推,但是C库中已经存在这种东西,称为a FILE
。如果您使用标准库缓冲的FILE
API而不是原始的Unix系统调用,那么您的生活会容易得多。甚至还有一个功能(很多注释都在告诉您使用该功能,该功能读取并返回下一个输入\n
。这称为fgets()。
刚刚发现了另一个问题。每次调用时都打开文件ReadInputData
。这不是问题,stdin
因为您只使用了文件描述符0。但是,对于任何其他文件,您每次都会读取第一行,直到您的进程用完文件描述符为止。在上面的解决方案中,您必须打开文件,main
然后将文件描述符添加到ReadBuffer
struct中。如果这样做,则肯定是在重新发明C库FILE
。
这是一个粗略的重新实现
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);
}
}
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句