将两个索引合并到一个数组中。

时间:2021-09-29 19:17:57

I have an unsigned char array which contains hex bytes like below:

我有一个无符号字符数组,它包含如下所示的十六进制字节:

unsigned char array[255];

array[0] = 'F';
array[1] = 'F';
array[2] = 'E';
array[3] = '2';
array[4] = 'A';
array[5] = 'A';
array[6] = 'C';
array[7] = 'C';

I want to merge them so that it becomes:

我想把它们合并起来

array[0] = "FF"
array[1] = "E2"
array[2] = "AA"
array[3] = "CC"

array[0] = '\xFF';
array[1] = '\xE2';
array[2] = '\xAA';
array[3] = '\xCC';

I have tried using sprintf but then I do not know how to specify index number in it. Any help.?

我尝试过使用sprintf,但是我不知道如何在其中指定索引号。任何帮助吗?

8 个解决方案

#1


2  

So, you want to convert your string, made of hexadecimal characters, into an array of bytes, right? Know your data.

所以,你想要把你的字符串,用十六进制字符转换成一个字节数组,对吧?知道你的数据。

sprintf() will not help you, since it produces strings. Instead, you will need to extract the 'value' of each hexa character and use it to calculate the value of your bytes.

sprintf()不会帮助您,因为它产生字符串。相反,您将需要提取每个hexa字符的“值”,并使用它来计算字节的值。

So, let's create a helper function to convert a hexadecimal character to its integer value (or -1 if it is invalid). We will use the characters' ASCII values and the fact that character ranges are contiguous in the ASCII table

因此,让我们创建一个助手函数,将十六进制字符转换为其整数值(如果无效,则为-1)。我们将使用字符的ASCII值和字符范围在ASCII表中是连续的这一事实

int char2hexa(unsigned char c)
{
  if(c >= '0' && c <= '9') {
    return (c - '0'); /* will return 0-9 */
  } else if(c >= 'A' && c <= 'F') {
    return (c - 'A') + 10; /* will return 10-15 */
  } else if(c >= 'a' && c <= 'f') {
    return (c - 'a') + 10; /* will return 10-15 */
  } else {
    return -1;
  }
}

Now a byte will be constructed from two hexa values by using one as the upper nibble (multiplied by 16 or shifted left by 4) and the other as a lower nibble, so let's have a function for that:

现在一个字节将由两个十六进制值组成,一个作为上字节(乘以16或者左移4),另一个作为下字节,我们有一个函数:

unsigned char hexvals2byte(int upper, int lower)
{
  return (upper * 16 + lower);
}

and put the pieces together. I will assume that:

把这些碎片放在一起。我将假设:

  • you know the length of your input data
  • 你知道输入数据的长度
  • the length is even (you need two characters per byte)
  • 长度为偶数(每个字节需要两个字符)
  • you want to put the result in the same array
  • 您希望将结果放在同一个数组中

Here comes.

来了。

#include <stdio.h>
#include <stdlib.h>

unsigned char array[255];
array[0] = 'F';
array[1] = 'F';
array[2] = 'E';
array[3] = '2';
array[4] = 'A';
array[5] = 'A';
array[6] = 'C';
array[7] = 'C';
unsigned length = 8;
int upper, lower;

for(int i = 0; i < length; i+=2) {
  upper = char2hexa(array[i]);
  lower = char2hexa(array[i+1]);

  if(upper < 0 || lower < 0) {
    /* handle input data format error */
    fprintf(stderr, "ERROR: Cannot decode hexa values '%c%c'\n", array[i], array[i+1]);
    exit(EXIT_FAILURE);
  }

  array[i/2] = hexvals2byte(upper, lower);
}

#2


1  

So you need a result array of unsigned char result[128][3], then assign the part results, grouping 2 source elements into one result sub-element:

因此需要一个无符号char结果的结果数组[128][3],然后分配部分结果,将两个源元素分组为一个结果子元素:

unsigned char result[128][3] = { 0 };
int i;
for (i = 0; i < 255; ++i)
{
    result[i/2][i%2] = array[i];
}

The reason for size 3 is, that you need 2 characters and one zero-delimiter to form a string.

大小为3的原因是,您需要两个字符和一个零分隔符来组成一个字符串。

#3


1  

An easy way to convert a digit to number is to subtract '0' from it:

把数字转换成数字的一个简单方法是减去“0”:

char digit = '3';
int number = digit - '0'; /* number = 3 */

This works only for digits (digit >= '0' && digit <= '9'), for hexadecimal digits ('A', 'B', etc.) you have to do a little more job:

这只适用于数字(>= '0' && digit <= '9'),对于十六进制数字('A', 'B'等),您必须多做一些工作:

unsigned char result[127];
int i;
unsigned char current;

unsigned char calc_diff(unsigned char digit) {
    if(digit >= '0' && digit <= '9')
        return '0';
    else if(digit >= 'A' && digit <= 'F')
        return 'A' - 10;
    else if(digit >= 'a' && digit <= 'f')
        return 'a' - 10;
    else
        return 0; // handle invalid digit
}

for(i = 0; i < 128; ++i) {
    current = array[2 * i];
    result[i] = (current - calc_diff(current)) << 4;

    current = array[(2 * i) + 1];
    result[i] |= current - calc_diff(current);
}

#4


1  

You want to convert characters to their hexadecimal value and combine them in pairs.

您希望将字符转换为十六进制值,并将它们成对组合。

Here is a simple program to illustrate how you can do this:

这里有一个简单的程序来说明你是如何做到这一点的:

#include <stdio.h>
#include <string.h>

static int xdigit(unsigned char c) {
    /* this method is inefficient but works for all encodings */
    static const char xdigits[] = "abcdef0123456789ABCDEF";
    const char *p = memchr(xdigits, c, 22);
    return p ? (p - xdigits + 10) & 15 : -1;
}

int main(void) {
    unsigned char array[255];

    while (scanf("%254s", array) == 1) {
        int i, j, d, d2 = 0;
        for (i = j = 0; array[i] != '\0'; i++) {
            d = xdigit(array[i]);
            if (d < 0) {
                printf("invalid hexadecimal digit: %c\n", array[i]);
                break;
            }
            d2 = (d2 << 4) | d;
            if (i & 1) {
                array[j++] = (unsigned char)d2;
                d2 = 0;
            }
        }
        array[j] = '\0';
        printf("converted array: %s\n", array);
    }
    return 0;
}

Here is a more elaborate version, with an separate conversion function and more explicit output:

这里有一个更精细的版本,有一个单独的转换函数和更明确的输出:

#include <ctype.h>
#include <stdio.h>
#include <string.h>

static int xdigit(unsigned char c) {
    switch (c) {
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
        return c - '0';
    case 'A': case 'a':
        return 10;
    case 'B': case 'b':
        return 11;
    case 'C': case 'c':
        return 12;
    case 'D': case 'd':
        return 13;
    case 'E': case 'e':
        return 14;
    case 'F': case 'f':
        return 15;
    default:
        return -1;
    }
}

int xconvert(unsigned char *dest, const unsigned char *src, int len) {
    int i, j, d, d2 = 0;
    for (i = j = 0; i < len; i++) {
        d = xdigit(src[i]);
        if (d < 0) {
            printf("invalid hexadecimal digit: %c\n", src[i]);
            return -1;
        }
        d2 = (d2 << 4) | d;
        if (i & 1) {
            dest[j++] = (unsigned char)d2;
            d2 = 0;
        }
    }
    if (i & 1) {
        printf("missing trailing digit\n");
        return -1;
    }
    return j;
}

int main(void) {
    unsigned char array[255];
    int i, len, c;

    while (scanf("%254s", array) == 1) {
        len = xconvert(array, array, strlen((char *)array));
        if (len >= 0) {
            printf("converted array: \"");
            for (i = 0; i < len; i++) {
                c = array[i];
                if (isprint(c)) {
                    putchar(c);
                } else {
                    printf("\\x%02X", c);
                }
            }
            printf("\"\n");
        }
    }
    return 0;
}

#5


0  

my stab at it. Here you have to know the size of the array. in your case 255

我尝试它。这里你必须知道数组的大小。255年你的案子

//counters and array's
int first = 0;
int second = 0;
int count = 0;
char foo[8] = {'F', 'F', 'E', '2', 'A', 'A', 'C', 'C'};
//array half the size of the first one.
char *done[4];

//loop through first array
while (first <= 7)
{
    //if its the first letter 
    if (second == 0)
    {
        //allocate enough mem to second arr
        done[count] = (char *)malloc(sizeof(char *) * 3);
        //assaign the first letter
        done[count][0] = foo[first];
        //indicate the next step for the second letter
        second = 1;
    }
    //if its the second letter
    else if (second == 1)
    {
        //assign second letter
        done[count][1] = foo[first];
        //null the string
        done[count][2] = '\0';
        //increase posistion index for the second arr
        count++;
        //indicate nexxt step is a the first letter of the next step
        second = 0;
    }
    //increment the index for the first arr
    first++;
}

#6


0  

Given that the data is in ASCII format and you want to merge it into a raw binary format, then:

如果数据是ASCII格式,您想将其合并为原始的二进制格式,则:

for(size_t i=0; i<n; i++)
{
  array[i] = to_int(array[i]);
}

where to_int() is your custom routine for converting from hexadecimal ASCII to integer. That is, if digit subtract with '0', else if upper-case letter subtract with 'A' and add 0xA.

to_int()是将十六进制ASCII转换为整数的自定义例程。也就是说,如果数字减去0,如果大写字母减去A,然后加0xA。

Then after that, merge the items:

然后合并项目:

for(size_t i=0; i<n; i+=2)
{
  array[i] = (unsigned int)array[i]<<4 | array[i+1];
}

#7


0  

I suppose you mix up an 8 bit value (e.g. 0x0F, which is 15 in decimal) with a character value like 'F' (which corresponds to 70 in ASCII format) with a string literal "FF" (which corresponds to a pointer to a sequence of the three character values {'F','F','\0'}.

我假设您将一个8位的值(比如0x0F,十进制数是15)与一个字符值(比如'F','F','\0')和一个字符串字面量"FF"(它对应一个指向三个字符值{'F','F','\0'}的指针)混合在一起。

From the context you present it seems that you mean 8 bit values, which are represented by data type unsigned char.

从您呈现的上下文来看,您的意思似乎是8位值,它由数据类型无符号字符表示。

Given that, the code could look as follows:

鉴于此,代码可以如下所示:

unsigned char array[255] = { 0xF,0xE,0x2,0xA,0xA,0xC,0xC };
int target=0;
for (int i=0; i<254; i+=2) {
  array[target] = (array[i] << 4) + array[i+1];
  target++;
}

#8


-1  

Maybe there are uncertain things but perhaps you want to do this.

也许有不确定的事情,但也许你想做这个。

#include <stdio.h>

int main(void){
    unsigned char array[255] = {//or char -> hex byte
        '\xF', '\xF', '\xE', '\x2',
        '\xA', '\xA', '\xC', '\xC',
    };
    int len = 8;
    for(int i = 0, j = 0; i < len; i += 2){
        array[j++] = (array[i] << 4) | array[i+1];
    }
    len = len / 2;
    for(int i = 0; i < len; i++){
        printf("%02hhX", array[i]);//FFE2AACC
    }
    printf("\n");
}

When the data held first is a hex character

当首先持有的数据是一个十六进制字符

#include <stdio.h>
#include <ctype.h>

int main(void){
    unsigned char array[255] = {
        'F', 'F', 'E', '2',
        'A', 'A', 'C', 'C',
    };
    int len = 8;
    for(int i = 0, j = 0; i < len; i++){
        if(isxdigit(array[i])){//maybe redundant
            if(isdigit(array[i])){
                array[i] -= '0';
            } else {
                array[i] -= isupper(array[i]) ? 'A' : 'a';
                array[i] += 10;
            }
        } else {
            fprintf(stderr, "invalid data %c\n", array[i]);
            return -1;
        }
    }

    for(int i = 0, j = 0; i < len; i += 2){
        array[j++] = (array[i] << 4) | array[i+1];
    }
    len = len / 2;
    for(int i = 0; i < len; i++){
        printf("%02hhX", array[i]);
    }
    printf("\n");
}

#1


2  

So, you want to convert your string, made of hexadecimal characters, into an array of bytes, right? Know your data.

所以,你想要把你的字符串,用十六进制字符转换成一个字节数组,对吧?知道你的数据。

sprintf() will not help you, since it produces strings. Instead, you will need to extract the 'value' of each hexa character and use it to calculate the value of your bytes.

sprintf()不会帮助您,因为它产生字符串。相反,您将需要提取每个hexa字符的“值”,并使用它来计算字节的值。

So, let's create a helper function to convert a hexadecimal character to its integer value (or -1 if it is invalid). We will use the characters' ASCII values and the fact that character ranges are contiguous in the ASCII table

因此,让我们创建一个助手函数,将十六进制字符转换为其整数值(如果无效,则为-1)。我们将使用字符的ASCII值和字符范围在ASCII表中是连续的这一事实

int char2hexa(unsigned char c)
{
  if(c >= '0' && c <= '9') {
    return (c - '0'); /* will return 0-9 */
  } else if(c >= 'A' && c <= 'F') {
    return (c - 'A') + 10; /* will return 10-15 */
  } else if(c >= 'a' && c <= 'f') {
    return (c - 'a') + 10; /* will return 10-15 */
  } else {
    return -1;
  }
}

Now a byte will be constructed from two hexa values by using one as the upper nibble (multiplied by 16 or shifted left by 4) and the other as a lower nibble, so let's have a function for that:

现在一个字节将由两个十六进制值组成,一个作为上字节(乘以16或者左移4),另一个作为下字节,我们有一个函数:

unsigned char hexvals2byte(int upper, int lower)
{
  return (upper * 16 + lower);
}

and put the pieces together. I will assume that:

把这些碎片放在一起。我将假设:

  • you know the length of your input data
  • 你知道输入数据的长度
  • the length is even (you need two characters per byte)
  • 长度为偶数(每个字节需要两个字符)
  • you want to put the result in the same array
  • 您希望将结果放在同一个数组中

Here comes.

来了。

#include <stdio.h>
#include <stdlib.h>

unsigned char array[255];
array[0] = 'F';
array[1] = 'F';
array[2] = 'E';
array[3] = '2';
array[4] = 'A';
array[5] = 'A';
array[6] = 'C';
array[7] = 'C';
unsigned length = 8;
int upper, lower;

for(int i = 0; i < length; i+=2) {
  upper = char2hexa(array[i]);
  lower = char2hexa(array[i+1]);

  if(upper < 0 || lower < 0) {
    /* handle input data format error */
    fprintf(stderr, "ERROR: Cannot decode hexa values '%c%c'\n", array[i], array[i+1]);
    exit(EXIT_FAILURE);
  }

  array[i/2] = hexvals2byte(upper, lower);
}

#2


1  

So you need a result array of unsigned char result[128][3], then assign the part results, grouping 2 source elements into one result sub-element:

因此需要一个无符号char结果的结果数组[128][3],然后分配部分结果,将两个源元素分组为一个结果子元素:

unsigned char result[128][3] = { 0 };
int i;
for (i = 0; i < 255; ++i)
{
    result[i/2][i%2] = array[i];
}

The reason for size 3 is, that you need 2 characters and one zero-delimiter to form a string.

大小为3的原因是,您需要两个字符和一个零分隔符来组成一个字符串。

#3


1  

An easy way to convert a digit to number is to subtract '0' from it:

把数字转换成数字的一个简单方法是减去“0”:

char digit = '3';
int number = digit - '0'; /* number = 3 */

This works only for digits (digit >= '0' && digit <= '9'), for hexadecimal digits ('A', 'B', etc.) you have to do a little more job:

这只适用于数字(>= '0' && digit <= '9'),对于十六进制数字('A', 'B'等),您必须多做一些工作:

unsigned char result[127];
int i;
unsigned char current;

unsigned char calc_diff(unsigned char digit) {
    if(digit >= '0' && digit <= '9')
        return '0';
    else if(digit >= 'A' && digit <= 'F')
        return 'A' - 10;
    else if(digit >= 'a' && digit <= 'f')
        return 'a' - 10;
    else
        return 0; // handle invalid digit
}

for(i = 0; i < 128; ++i) {
    current = array[2 * i];
    result[i] = (current - calc_diff(current)) << 4;

    current = array[(2 * i) + 1];
    result[i] |= current - calc_diff(current);
}

#4


1  

You want to convert characters to their hexadecimal value and combine them in pairs.

您希望将字符转换为十六进制值,并将它们成对组合。

Here is a simple program to illustrate how you can do this:

这里有一个简单的程序来说明你是如何做到这一点的:

#include <stdio.h>
#include <string.h>

static int xdigit(unsigned char c) {
    /* this method is inefficient but works for all encodings */
    static const char xdigits[] = "abcdef0123456789ABCDEF";
    const char *p = memchr(xdigits, c, 22);
    return p ? (p - xdigits + 10) & 15 : -1;
}

int main(void) {
    unsigned char array[255];

    while (scanf("%254s", array) == 1) {
        int i, j, d, d2 = 0;
        for (i = j = 0; array[i] != '\0'; i++) {
            d = xdigit(array[i]);
            if (d < 0) {
                printf("invalid hexadecimal digit: %c\n", array[i]);
                break;
            }
            d2 = (d2 << 4) | d;
            if (i & 1) {
                array[j++] = (unsigned char)d2;
                d2 = 0;
            }
        }
        array[j] = '\0';
        printf("converted array: %s\n", array);
    }
    return 0;
}

Here is a more elaborate version, with an separate conversion function and more explicit output:

这里有一个更精细的版本,有一个单独的转换函数和更明确的输出:

#include <ctype.h>
#include <stdio.h>
#include <string.h>

static int xdigit(unsigned char c) {
    switch (c) {
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
        return c - '0';
    case 'A': case 'a':
        return 10;
    case 'B': case 'b':
        return 11;
    case 'C': case 'c':
        return 12;
    case 'D': case 'd':
        return 13;
    case 'E': case 'e':
        return 14;
    case 'F': case 'f':
        return 15;
    default:
        return -1;
    }
}

int xconvert(unsigned char *dest, const unsigned char *src, int len) {
    int i, j, d, d2 = 0;
    for (i = j = 0; i < len; i++) {
        d = xdigit(src[i]);
        if (d < 0) {
            printf("invalid hexadecimal digit: %c\n", src[i]);
            return -1;
        }
        d2 = (d2 << 4) | d;
        if (i & 1) {
            dest[j++] = (unsigned char)d2;
            d2 = 0;
        }
    }
    if (i & 1) {
        printf("missing trailing digit\n");
        return -1;
    }
    return j;
}

int main(void) {
    unsigned char array[255];
    int i, len, c;

    while (scanf("%254s", array) == 1) {
        len = xconvert(array, array, strlen((char *)array));
        if (len >= 0) {
            printf("converted array: \"");
            for (i = 0; i < len; i++) {
                c = array[i];
                if (isprint(c)) {
                    putchar(c);
                } else {
                    printf("\\x%02X", c);
                }
            }
            printf("\"\n");
        }
    }
    return 0;
}

#5


0  

my stab at it. Here you have to know the size of the array. in your case 255

我尝试它。这里你必须知道数组的大小。255年你的案子

//counters and array's
int first = 0;
int second = 0;
int count = 0;
char foo[8] = {'F', 'F', 'E', '2', 'A', 'A', 'C', 'C'};
//array half the size of the first one.
char *done[4];

//loop through first array
while (first <= 7)
{
    //if its the first letter 
    if (second == 0)
    {
        //allocate enough mem to second arr
        done[count] = (char *)malloc(sizeof(char *) * 3);
        //assaign the first letter
        done[count][0] = foo[first];
        //indicate the next step for the second letter
        second = 1;
    }
    //if its the second letter
    else if (second == 1)
    {
        //assign second letter
        done[count][1] = foo[first];
        //null the string
        done[count][2] = '\0';
        //increase posistion index for the second arr
        count++;
        //indicate nexxt step is a the first letter of the next step
        second = 0;
    }
    //increment the index for the first arr
    first++;
}

#6


0  

Given that the data is in ASCII format and you want to merge it into a raw binary format, then:

如果数据是ASCII格式,您想将其合并为原始的二进制格式,则:

for(size_t i=0; i<n; i++)
{
  array[i] = to_int(array[i]);
}

where to_int() is your custom routine for converting from hexadecimal ASCII to integer. That is, if digit subtract with '0', else if upper-case letter subtract with 'A' and add 0xA.

to_int()是将十六进制ASCII转换为整数的自定义例程。也就是说,如果数字减去0,如果大写字母减去A,然后加0xA。

Then after that, merge the items:

然后合并项目:

for(size_t i=0; i<n; i+=2)
{
  array[i] = (unsigned int)array[i]<<4 | array[i+1];
}

#7


0  

I suppose you mix up an 8 bit value (e.g. 0x0F, which is 15 in decimal) with a character value like 'F' (which corresponds to 70 in ASCII format) with a string literal "FF" (which corresponds to a pointer to a sequence of the three character values {'F','F','\0'}.

我假设您将一个8位的值(比如0x0F,十进制数是15)与一个字符值(比如'F','F','\0')和一个字符串字面量"FF"(它对应一个指向三个字符值{'F','F','\0'}的指针)混合在一起。

From the context you present it seems that you mean 8 bit values, which are represented by data type unsigned char.

从您呈现的上下文来看,您的意思似乎是8位值,它由数据类型无符号字符表示。

Given that, the code could look as follows:

鉴于此,代码可以如下所示:

unsigned char array[255] = { 0xF,0xE,0x2,0xA,0xA,0xC,0xC };
int target=0;
for (int i=0; i<254; i+=2) {
  array[target] = (array[i] << 4) + array[i+1];
  target++;
}

#8


-1  

Maybe there are uncertain things but perhaps you want to do this.

也许有不确定的事情,但也许你想做这个。

#include <stdio.h>

int main(void){
    unsigned char array[255] = {//or char -> hex byte
        '\xF', '\xF', '\xE', '\x2',
        '\xA', '\xA', '\xC', '\xC',
    };
    int len = 8;
    for(int i = 0, j = 0; i < len; i += 2){
        array[j++] = (array[i] << 4) | array[i+1];
    }
    len = len / 2;
    for(int i = 0; i < len; i++){
        printf("%02hhX", array[i]);//FFE2AACC
    }
    printf("\n");
}

When the data held first is a hex character

当首先持有的数据是一个十六进制字符

#include <stdio.h>
#include <ctype.h>

int main(void){
    unsigned char array[255] = {
        'F', 'F', 'E', '2',
        'A', 'A', 'C', 'C',
    };
    int len = 8;
    for(int i = 0, j = 0; i < len; i++){
        if(isxdigit(array[i])){//maybe redundant
            if(isdigit(array[i])){
                array[i] -= '0';
            } else {
                array[i] -= isupper(array[i]) ? 'A' : 'a';
                array[i] += 10;
            }
        } else {
            fprintf(stderr, "invalid data %c\n", array[i]);
            return -1;
        }
    }

    for(int i = 0, j = 0; i < len; i += 2){
        array[j++] = (array[i] << 4) | array[i+1];
    }
    len = len / 2;
    for(int i = 0; i < len; i++){
        printf("%02hhX", array[i]);
    }
    printf("\n");
}