繁体   English   中英

编码,将整数解码为char数组

[英]Encoding, decoding an integer to a char array

请注意,这不是家庭作业,我在开始此新线程之前进行过搜索。 将int存储在char数组中?

我在寻找答案,但是在上述线程中没有得到满意的答案。

这是我的要求:我想将我的数据(例如整数)编码为字节数组,然后通过网络传输,然后在另一端解码并处理它。

这是编码部分:

const int MAX=5;
uint32_t a = 0xff00ffaa;
char byte_array[1024]; // this is the array to be transferred over the network
char buff[MAX]="";
sprintf(buff,"%4d",a);
memcpy(byte_array,buff,4);
// fill remaining stuff in the byte array and send it over the network

这是解码部分:

const int MAX=5;
char buff[MAX]="";
strncat(buff,byte_array,4)

int i=atoi(buff);
// Work with i

这是我的问题:

1)上面的代码可移植吗? 我想是(请纠正我)

2)现在,我希望将字节数组编码为3个字节(但整数大小为4),即说整数存储0x00ffaabb,而我只希望字节数组在第1个索引中具有ff int 0th个索引aa,在第一个索引中具有bb第二索引。 怎么做?

snprinf似乎不起作用,或者可能是我缺少了一些东西。

实施任何网络协议的人都可以轻松帮助我。 我猜解码逻辑仍然可以工作。 strncat(buff,byte_array,3)后跟atoi函数调用)。

协议说明如下:

--------+--------+--------+--------+------------------------------
    |Version|   3       byte    length |  Remaining stuff
    --------+--------+--------+--------+------------------------------

版本为1字节,后跟消息的3字节长度。

我希望我可以澄清我的问题

您将以ASCII格式存储,应该在其中存储字节本身。

编码应类似于:

uint32_t a = 0xff00ffaa;
unsigned char byte_array[1024];

注意我如何使目标数组无符号,以表明它是“原始字节”,而不是字符。

byte_array[0] = a >> 24;
byte_array[1] = a >> 16;
byte_array[2] = a >> 8;
byte_array[3] = a >> 0;

这使用大端字节顺序将变量a序列化为byte_array的前四个字节,这是许多网络协议的默认设置。

您可能还想在这里看到我的答案: 问题1577161

1)这是一种工作,因为您使用字符数组进行运输,所以我个人会使用二进制协议。 如果您可以使用变量的4个字节,那么我来看看htonl / ntohl函数(自w2k以来,它们实际上在每个unix和Windows上),否则请参见下文

2)使用二进制协议,编码将是

uint32_t a = 0xff00ffaa;
char byte_array[1024]; // this is the array to be transferred over the network

// leave byte_array[0] for version byte
// leave the high order byte in a since you want only the 3 lowest
byte_array[1] = (char)((a & 0x00FF0000)>>16);
byte_array[2] = (char)((a & 0x0000FF00)>>8);
byte_array[3] = (char)(a & 0x000000FF);

和解码将是

uint32_t a = 0;
a |= byte_array[1]<<16;
a |= byte_array[2]<<8;
a |= byte_array[3];

您正在做的事情将完成一些工作。 您不是在传输数据的字节,而是在传输数据的数值。 因此,对于要发送的数据,大小为5的缓冲区太小了(0xFF00FFAA的数值为4278255530-10个字节)。

要传输字节,您需要执行以下操作(假设使用小字节序):

编码:

char array[1024]; // outgoing network data
int next = 0;

array[next++] = value & 0xFF;
array[next++] = (value >> 8) & 0xFF;
array[next++] = (value >> 16) & 0xFF;
array[next++] = (value >> 24) & 0xFF;

这些语句剥离值的字节,并将其分配给数组中的后续值。

解码:

char array[1024]; // incoming network data
int next = 0;

value = 0;
value |= (int)*((unsigned char*)array)[next++];
value |= (int)*((unsigned char*)array)[next++] << 8;
value |= (int)*((unsigned char*)array)[next++] << 16;
value |= (int)*((unsigned char*)array)[next++] << 24;

这些语句将字节从数组中拉出,然后将其推回值中。

如果要尝试优化网络格式而不传输字节,则可以消除一些数据。 但是请记住,您的发送方和接收方需要彼此了解期望的内容-因此需要进行某种通信,以传递要传递的数据元素的类型或长度。

至少为了便于移植,您应该考虑编码上可能的不同字节顺序。

您是否真的需要实现新的网络消息传递协议? NASA IPC或Sun RPC不适合您吗? 它们都足够稳定,NASA更易于启动,RPC似乎更广泛可用(是的,它可以立即使用,并且库可用于大多数流行的系统)。

  • 对于RPC,请尝试使用“ man rpc”
  • 对于NASA IPC,请点击此处

也许您需要使用现有协议来完成此工作,在这种情况下,请忽略我的回答。

您为什么不使用Google的Protocol Buffers库来完成这项工作,而不是在这里重新发明轮子? 更简单,更灵活且非常高效。

使用XDRRFC 4506 )。

您所拥有的将无法以您拥有的方式工作。 例如,a是32位,而在您的示例中您设置了高位,这意味着它不能与您的printf语句一起容纳4位数字。 (0xff00ffaa = 4278255530,大于4位)我相信它将使缓冲区溢出。 我相信printf会转换它并溢出该字段,但这取决于您的编译器/ C在缓冲区空间不足时如何实现printf函数。

对于您拥有的printf语句,您可以传入的最大值为4个字符的9999。 同样,在使用3个字节的长度字段传输数据的示例中,最大长度为999。理论上,如果您将长度加1,则长度可以为1000,但是声明的缓冲区为1024您需要的最大缓冲区长度为1004个字节。

使用ASCII字符确实使消息/数据可在整个系统中移植,但是这是以使用更多带宽/空间以及编程时间和精力来从ASCII来回转换以传输数据为代价的。

看来您有个好主意,但仍然需要一些工作。

最好使用一些现有工具。 如果不能-您是否关心字节顺序(即,这是跨平台协议吗?)

否则,您可以简单地做类似...

unsigned char msg[1024];
int writeIndex = 0;
[...]
int mynum  = 12345;
memcpy(msg + writeIndex , &mynum, sizeof mynum);
writeIndex += sizeof mynum;

并解码

//[...] also declare readIndex;
memcopy(&mynum, msg + readIndex, sizeof mynum);
readIndex += sizeof mynum;

(您可以用无符号的char指针替换msg + index的概念,尽管这不太重要)。

像这样使用memcpy可能会比较慢,但也更具可读性。 如有必要,您可以在#define或内联函数中实现memcopy克隆-毕竟,这只是一小段分配。

仅当您希望解码的字符串是由您自己的代码构建且仅在上面的两行之内完成时,才可以使用atoi函数。 即,它仅在类似草图的代码中可用。

否则,特别是在您的情况下,当数据从网络到达时,无法有效地使用atoi函数执行解码,因为它没有提供可用的错误处理机制并且绝对没有针对溢出的保护(溢出时未定义的行为)。 可用于字符串到整数转换的唯一函数是strto...组中的strtol在您的情况下为strtol

我已经浏览了此页面一百万次,非常感谢其他所有帮助我的答案。 这是我正在使用的存根,与其他答案不同,因为它可以在for循环中使用:

void encode_int_as_char(int num, char *buf, int length){
    int i;
    for (i = 0; i < length; i++){
        buf[i] = (char)(num >> ((8 * (length - i - 1)) & 0xFF));
    }
}

int decode_int_from_char(char *enc, int length){
    int i, num, cur;

    num = 0;
    for (i = 0; i < length; i++){
        cur = (unsigned char) enc[i] << (8 * (length - i - 1));
        num += (int) cur;
    }

    return num;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM