如何从当前位置偏移 fseek
How to offset in fseek from current position
我无法从 SEEK_CUR
偏移:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE * fp = fopen("txt", "w+b");
if(!fp)
return 1;
fprintf(fp, "20");
fseek(fp, 1, SEEK_CUR);
fprintf(fp, "19");
long size = ftell(fp) + 1;
rewind(fp);
char * buf = malloc(size+1);
buf = memset(buf, 0, size+1); //should I really do this? becuase, after the "20" there will be [=10=] so I won't see the rest (` 19`)
fread(buf, sizeof(char), size, fp);
printf("%s\n",buf);
}
输出:
20
但应该是 20 19
,我不能从该文件 fread()
,为什么?
问题是您的 buf
不是 null-terminated。该数组的大小正好可以容纳文本文件的内容,没有任何空终止符。
尝试
char buf[size+1] = ""; /* initialize buf to all zeros, with room for null terminator */
字符串文字对象已经是 null-terminated,所以对于大多数用途来说,这是多余的:
char *str = "abc[=11=]";
字符串现在由两个空值终止,这在某些特殊情况下可能很有用。 Microsoft 提出了一种数据格式,用于 Windows 注册表,用于存储字符串列表。列表中的每个字符串都是 null-terminated,然后又一个空字节明确地终止了整个列表。我们可以在 C 中声明这样的东西:
char *windows_reg_style_list = "how[=12=]now[=12=]brown\cow[=12=]";
对于C语言中的普通字符串处理,"abc[=15=]"
看起来和"abc"
一样:都是长度为3的字符串,同样上面的数据看起来像字符串"how"
。
我认为,只有一种情况 C 源代码中的 "..."
表示法不会产生空终止字符串。那就是当它用作数组的初始值设定项时,该数组的大小恰好适合该字符数:
char no_null_term[4] = "abcd";
如果我们使它成为 [5]
,它将以 null 终止,并且 [3]
将是错误的,因为数组太小无法容纳 abcd
。 [4]
允许作为一种特殊情况用于初始化不像 null-terminated 字符串那样表现的数组。
另请注意,要使用 ftell
,流必须是二进制的:fopen(..., "w+b")
。所以也就是说,ftell
不需要return一个对应于写入文本流的字符数的值。
因此,您将“20”写入文件,然后跳过文件中前面的一个 byte/character,然后将“19”写入文件。跳过的字符需要写成某个值...那个值是 [=12=]
.
因此,您从文件中将“209”读取到一个由 memset
调用初始化为七个 [=12=]
字节的 buf 中。 buf
现在包含 "209[=16=][=16=]"
.
printf("%s\n", buf)
将 buf
打印为 NUL 终止字符串,即直到出现第一个 NUL 字节。 NUL 字节紧跟在“20”之后,因此它只打印“20”。
如果你要用hexdump函数对缓冲区进行hexdump(写成练习)
hexdump(buf, size);
它会打印类似
的内容
0000 32 30 00 31 39 00 - 20.19.
我无法从 SEEK_CUR
偏移:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE * fp = fopen("txt", "w+b");
if(!fp)
return 1;
fprintf(fp, "20");
fseek(fp, 1, SEEK_CUR);
fprintf(fp, "19");
long size = ftell(fp) + 1;
rewind(fp);
char * buf = malloc(size+1);
buf = memset(buf, 0, size+1); //should I really do this? becuase, after the "20" there will be [=10=] so I won't see the rest (` 19`)
fread(buf, sizeof(char), size, fp);
printf("%s\n",buf);
}
输出:
20
但应该是 20 19
,我不能从该文件 fread()
,为什么?
问题是您的 buf
不是 null-terminated。该数组的大小正好可以容纳文本文件的内容,没有任何空终止符。
尝试
char buf[size+1] = ""; /* initialize buf to all zeros, with room for null terminator */
字符串文字对象已经是 null-terminated,所以对于大多数用途来说,这是多余的:
char *str = "abc[=11=]";
字符串现在由两个空值终止,这在某些特殊情况下可能很有用。 Microsoft 提出了一种数据格式,用于 Windows 注册表,用于存储字符串列表。列表中的每个字符串都是 null-terminated,然后又一个空字节明确地终止了整个列表。我们可以在 C 中声明这样的东西:
char *windows_reg_style_list = "how[=12=]now[=12=]brown\cow[=12=]";
对于C语言中的普通字符串处理,"abc[=15=]"
看起来和"abc"
一样:都是长度为3的字符串,同样上面的数据看起来像字符串"how"
。
我认为,只有一种情况 C 源代码中的 "..."
表示法不会产生空终止字符串。那就是当它用作数组的初始值设定项时,该数组的大小恰好适合该字符数:
char no_null_term[4] = "abcd";
如果我们使它成为 [5]
,它将以 null 终止,并且 [3]
将是错误的,因为数组太小无法容纳 abcd
。 [4]
允许作为一种特殊情况用于初始化不像 null-terminated 字符串那样表现的数组。
另请注意,要使用 ftell
,流必须是二进制的:fopen(..., "w+b")
。所以也就是说,ftell
不需要return一个对应于写入文本流的字符数的值。
因此,您将“20”写入文件,然后跳过文件中前面的一个 byte/character,然后将“19”写入文件。跳过的字符需要写成某个值...那个值是 [=12=]
.
因此,您从文件中将“209”读取到一个由 memset
调用初始化为七个 [=12=]
字节的 buf 中。 buf
现在包含 "209[=16=][=16=]"
.
printf("%s\n", buf)
将 buf
打印为 NUL 终止字符串,即直到出现第一个 NUL 字节。 NUL 字节紧跟在“20”之后,因此它只打印“20”。
如果你要用hexdump函数对缓冲区进行hexdump(写成练习)
hexdump(buf, size);
它会打印类似
的内容0000 32 30 00 31 39 00 - 20.19.