我是C的新手,我想知道是否有标准库方法来读取bytes / int / long 例如:getChar(),getInt(),getLong()。
因此,例如,如果我调用getInt(),它将返回4个字节作为字符串并将char指针地址移动4.我在哪里可以找到这些方法?
答案 0 :(得分:8)
不,库不直接支持二进制(反)序列化。 read()
函数将移动流指针,但我不认为您可以绕过与平台相关的代码片段来解释字节流:
std::infile thefile("data.bin", "rb");
float f;
double d;
uint32_t i;
// the following is OK and doesn't constitute type punning
char * const pf = reinterpret_cast<char*>(&f);
char * const pd = reinterpret_cast<char*>(&d);
char * const pi = reinterpret_cast<char*>(&i);
// the following may or may not give you what you expect
// Caveat emptor, and add your own platform-specific code here.
thefile.read(pf, sizeof(float));
thefile.read(pd, sizeof(double));
thefile.read(pi, sizeof(uint32_t));
在仅读取无符号整数值的情况下,您可以执行代数提取,这在某种意义上是类型安全的,只需要您知道序列化数据格式的字节顺序:
unsigned char buf[sizeof(uint32_t)];
thefile.read(reinterpret_cast<char*>(buf), sizeof(uint32_t));
uint32_t n = buf[0] + (buf[1] << 8) + (buf[2] << 16) + (buf[3] << 24); // little-endian
以二进制形式读取浮点数据特别令人厌烦,因为您必须了解有关数据流的大量额外信息:它是否使用IEEE754? (你的平台吗?)enidanness是什么(float endianness与整数字节序无关)?或者它完全代表其他东西?良好的文件格式文档至关重要。
在C中,您将使用fread()
和C风格的演员,char * const pf = (char*)(&f)
。
答案 1 :(得分:1)
我相信你指的是Java的ByteBuffer方法。
请注意,如果您对这些函数处理的相同数据进行操作,那么 Java始终是BIG端,无论主机的本机字节顺序如何。除非您确定不是,否则您的C代码可能正在编译以在 LITTLE endian 计算机上运行。如果您不确定,可以采用一些粗略的指导原则:x86(大多数PC)都是LE。 ARM可以是,但通常是LE。 PowerPC和Itanium是BE。
此外,永远不要将char *
或void *
取消引用任何大于1字节的类型,除非您知道它已正确对齐。如果不是,它将导致总线故障或类似错误。
所以这里将是我的getInt()
impl,假设BE /网络字节顺序(例如由Java生成)缓冲区。对于简洁而道歉。
typedef struct ByteBuffer {
const char * buffer; /* Buffer base pointer */
int nextByte; /* Next byte to parse */
int size; /* Size of buffer */
} ByteBuffer_t;
/* Get int from byte buffer, store results in 'i'. Return 0 on success, -1 on error */
int getInt(ByteBuffer * bb, int * i) {
const char * b;
if( (bb->nextByte + 3) < bb->size ) {
b = &(bb->buffer[bb->nextByte]);
/* Read as big-endian value */
*i = (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[0];
bb->nextByte += 4;
return 0;
} else {
return -1;
}
}
void test(const char * buf, int bufSize) {
ByteBuffer_t bb;
int ival;
bb.buffer = buf;
bb.size = bufSize;
bb.nextByte = 0;
while(1) {
if( 0 == getInt(&bb, &ival) )
printf("%d\n", ival);
else
break;
}
}
编辑:删除了ntohl()调用....如果您的源数据真的是大端,则它不属于。如果它在那里调用那么工作,你可能需要在shift-pack上交换字节顺序,这意味着它将解析小端字节流。
答案 2 :(得分:0)
由于指针算法属于C的本质,因此这种类似Java的函数不可用。
要从某个内存缓冲区中获取int
,您可以这样做:
/* assuming that buf is of type void * */
int x = *((int *) buf);
/* advance to the position after the end of the int */
((int *) buf)++;
或更紧凑:
int x = *((int *) buf)++;
答案 3 :(得分:0)
有一个getchar()函数。
c中的标准输入法是使用
scanf("<format specifer string>",input param1, param2,...)