我正在尝试在文件上打印int array
,但它给了我一个错误。
write_error:Bad address.
我的int array
类似于:
1 2 3 4 5 6 7 8 9
我想在file
上打印如下:
1 2 3
4 5 6
7 8 9
这是我正在使用的代码:
void printToFile(int listBoard[]) {
int file_write;
char buffer[100];
char buffer2[10];
if ((file_write = open("./board.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
err_sys("error output file");
}
if (write(file_write, snprintf(buffer2, 10, "%d",listBoard[2]), 18) != 18){
err_sys("write_error");
}
if (close(file_write) != 0){
err_sys("error close write");
}
}
我也尝试了(char)
,但它将int
转换为ascii char
。
你能告诉我我错过了什么吗?
我的文件输出是:
3@\00\00펈㰙\00ጠ
编辑代码:
void printToFile(int listBoard[]){
int file_write;
char buffer[100];
int value;
int cont = 0;
char buffer2[10];
if ((file_write = open("./board.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
err_sys("error output file");
}
int len = snprintf(buffer2, 10, "%d", listBoard[2]);
if (write(file_write, buffer2, len) != len) {
err_sys("write_error");
}
if (close(file_write) != 0) {
err_sys("error close write");
}
}
输出文件:
3
这就是我现在用它来打印它作为我想要的输出
if ((file_write = open("./board.txt", O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
err_sys("error output file");
}
for (int index = 0; index < SIZE_BOARD; index++) {
if (cont == 3) {
int len = snprintf(buffer2, 1, "%d \n", ' ');
if(write(file_write, buffer2, len) != len) {
err_sys("write_error");
cont=0;
}
}
int len = snprintf(buffer2, 10, "%d ", listBoard[index]);
if (write(file_write, buffer2, len) != len) {
err_sys("write_error");
cont++;
}
}
if(close(file_write) != 0) {
err_sys("error close write");
}
但它没有正确地执行\n
。我缺少什么?
答案 0 :(得分:3)
写的定义如下:
ssize_t write(int fd, const void *buf, size_t count);
snprintf的定义如下:
int snprintf(char *str, size_t size, const char *format, ...);
现在,您正在将snprintf提供给期望void *buf
的写入位置。即数据所在的地址。
所以你必须做
snprintf(buffer2, 10, "%d", listBoard[2]);
然后
write(file_write, buffer2, 18);
修改强>
这将修复语法错误。从语义上讲,您可以看到您正在向缓冲区2写入10个字节,但您要将18写入文件。这将用垃圾填充文件。所以我建议。
int len = snprintf(buffer2, 10, "%d", listBoard[2]);
write(file_write, buffer2, len);
编辑2:
int len = snprintf(buffer2, 1, "%d \n", ' ');
首先,您的格式说明符具有 3 字节,而您只将 1 字节写入缓冲区2。第二,为什么你的论点' '
当你应该给listBoard[n]
?
答案 1 :(得分:2)
使用dprintf()
将格式化的字符串写入文件:
dprintf(file_write, "%d", listBoard[2]);
dprintf
将为您处理所有写入内容,因此这是您打开和关闭时唯一需要的调用。
dprintf
是文件描述符的fprintf
。更多信息:https://linux.die.net/man/3/dprintf
答案 2 :(得分:0)
snprintf
(and family) functions会返回整数。
在write
调用中使用此整数作为指向缓冲区的指针。这将导致未定义的行为。
单独调用snprintf
,然后将buffer2
作为第二个参数传递。并使用strlen
获取buffer2
中字符串的实际长度,而不是硬编码将导致从外部读取的幻数18
-bounds和 UB的另一个案例。
答案 3 :(得分:0)
首先,snprintf
返回一个整数,该整数是字符串未被截断时已写入的字符数(正如您可以在snprintf manual上看到的那样)
您无法在write
命令中使用它。然后您可以使用:
if ( snprintf(buffer2, 10,"%d",listBoard[2]) >= 10 ) {
/* handle truncation error*/
}
if(write(file_write,buffer2,18)!=18){
err_sys("write_error");
无论如何,因为buffer2最多10个字符,你为什么要写18个字节?
其他可能的错误:对于空终止,buffer2应该至少为10 + 1字节。
答案 4 :(得分:0)
您永远不会指定必须使用原始文件描述符,因此,让我们将您的代码上移一级到C标准库的myEq (x:xs) (y:ys) = if x == y then myEq xs ys else False
抽象。它更容易使用。
FILE
请注意,这使用循环来迭代板数组的元素,这似乎是原始代码中缺少的,也是您使用它的部分问题。
打印:
void printToFile(const int listBoard[]) {
FILE * const out = fopen("board.txt", "wt");
if (out == NULL) {
err_sys("error output file");
}
for(int j = 0; j < 3; ++j) {
for (int i = 0; i < 3; ++i)
fprintf(out, "%d ", listBoard[3 * j + i]);
fprintf(out, "\n");
}
fclose(out);
}
由于我很懒,每条线上都有一个尾随空间,但希望这很好。我也省略了一些内部错误检查。