我从只读FIFO读取几行时遇到问题。特别是,我必须阅读两行 - 一个数字n
,然后是\n
和一个字符串str
- 我的C程序应该写一个str
只有n
次的FIFO。这是我的尝试。
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
char *readline(int fd);
int main(int argc, char** argv) {
int in = open(argv[1], O_RDONLY);
mkfifo(argv[2], 0666);
int out = open(argv[2] ,O_WRONLY);
char *line = (char *) malloc(50);
int n;
while (1) {
sscanf(readline(in), "%d", &n);
strcpy(line, readline(in));
int i;
for (i = 0; i < n; i++) {
write(out, line, strlen(line));
write(out, "\n", 1);
}
}
close(in);
close(out);
return 0;
}
char *readline(int fd) {
char *c = (char *) malloc(1);
char line[50];
while (read(fd, c, 1) != 0) {
if (strcmp(c, "\n") == 0) {
break;
}
strcat(line, c);
}
return line;
}
代码工作正常,但在最后一次重复字符串后,它会随机放置一些新行。此外,此数字在每次执行时都会更改。
有人可以帮我一下吗?
答案 0 :(得分:1)
除了明智地阅读字符并使用“字符串”比较比较两个字符的事实之外,两者都远没有效率,readline()
返回指向readline()
本地声明的内存的指针,即{ {1}}只要line[50]
返回就会释放内存,因此之后访问它会调用undefine行为。
解决这个问题的一种可能性是声明缓冲区将行读入外部readline()
并将引用传递给它,如下所示:
readline()
然后像这样称呼它:
char * readline(int fd, char * line, size_t size)
{
if ((NULL != line) && (0 < size))
{
char c = 0;
size_t i = 0;
while (read(fd, &c, 1) >0)
{
if ('\n' == c) or (size < i) {
break;
}
line[i] = c;
++i;
}
line [i] = 0;
}
return line;
}
答案 1 :(得分:0)
我没有尝试运行您的代码,但在readline
函数中,您没有使用null(line
)字符终止'\0'
。一旦你点击'\n'
字符,你就会打破while
循环并返回字符串line
。在从函数'\0'
返回之前尝试添加readline
字符。
点击here了解详情。
答案 2 :(得分:-1)
你的代码在我的机器上不起作用,我说你很幸运能得到任何有意义的结果。
以下是一些需要考虑的问题:
readline
返回一个本地定义的静态字符缓冲区(line
),当函数结束时它将被销毁,它曾经占用的内存可以被其他操作覆盖。line
在分配时未设置为空字节,strcat
会将其垃圾值视为字符,并可能在其结束后尝试写入。c
)只是因为你需要read
中的char *。这是不必要的(参见下面的代码)。更糟糕的是,你不会在readline
退出之前解除分配,所以它会泄漏内存。while(1)
循环将重新读取文件并将其重新打印到输出fifo,直到时间结束。strcat
和记忆分配 - 这里有更简单的方法。以下是我修改代码的方法。请注意,如果第二行超过50个字符,则此代码也可能表现不佳。缓冲区限制有一些技术,但我在这个例子中没有使用任何技术:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
char *readline(int fd, char * buffer);
int main(int argc, char** argv) {
int in = open(argv[1], O_RDONLY);
int out;
int n;
int i;
char line[50];
memset(line, 0, 50);
mkfifo(argv[2], 0666);
out = open(argv[2] ,O_WRONLY);
sscanf(readline(in, line), "%d", &n);
strcpy(line, readline(in, line));
for (i = 0; i < n; i++) {
write(out, line, strlen(line));
write(out, "\n", 1);
}
close(in);
close(out);
return 0;
}
char *readline(int fd, char * buffer) {
char c;
int counter = 0;
while (read(fd, &c, 1) != 0) {
if (c == '\n') {
break;
}
buffer[counter++] = c;
}
return buffer;
}
如您所述,这可以在我的盒子上使用。用GCC 4.8.2编译。