[英]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似乎更廣泛可用(是的,它可以立即使用,並且庫可用於大多數流行的系統)。
也許您需要使用現有協議來完成此工作,在這種情況下,請忽略我的回答。
您為什么不使用Google的Protocol Buffers庫來完成這項工作,而不是在這里重新發明輪子? 更簡單,更靈活且非常高效。
您所擁有的將無法以您擁有的方式工作。 例如,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.