在C

时间:2017-05-09 06:21:01

标签: c arrays

我有一个unsigned char数组,其中包含如下所示的十六进制字节:

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';

我想合并它们以便它变成:

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

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

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

8 个答案:

答案 0 :(得分:2)

因此,您希望将由十六进制字符组成的字符串转换为字节数组,对吗?了解您的数据。

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; } } 无法帮助您,因为它会生成字符串。相反,您需要提取每个hexa字符的“值”,并使用它来计算字节值。

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

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

现在一个字节将由两个hexa值构成,使用一个作为高半字节(乘以16或向左移动4),另一个作为低半字节,所以让我们有一个函数:

#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);
}

将各个部分放在一起。我会假设:

  • 您知道输入数据的长度
  • 长度均匀(每个字节需要两个字符)
  • 您想将结果放在同一个数组中

来了。

{{1}}

答案 1 :(得分:1)

所以你需要一个unsigned char result[128][3]的结果数组,然后分配部分结果,将2个源元素分组到一个结果子元素中:

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

大小3的原因是,你需要2个字符和一个零分隔符来形成一个字符串。

答案 2 :(得分:1)

将数字转换为数字的简便方法是从中减去'0'

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

这仅适用于数字(digit >= '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);
}

答案 3 :(得分:1)

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

这是一个简单的程序,用于说明如何执行此操作:

#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;
}

这是一个更复杂的版本,具有单独的转换功能和更明确的输出:

#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;
}

答案 4 :(得分:0)

我想你混淆了一个8位值(例如0x0F,十进制为15),字符值如'F'(对应于ASCII格式的70)字符串文字"FF"(对应于指向三个字符值{'F','F','\0'}的序列的指针。

从您提供的上下文中,您似乎意味着8位值,它们由数据类型unsigned char表示。

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

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++;
}

答案 5 :(得分:0)

我刺伤了它。在这里你必须知道数组的大小。在你的情况下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)

鉴于数据是ASCII格式,并且您想将其合并为原始二进制格式,那么:

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

其中to_int()是从十六进制ASCII转换为整数的自定义例程。也就是说,如果数字用'0'减去,否则如果用大写字母减去'A'并添加0xA。

然后,合并项目:

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

答案 7 :(得分:-1)

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

#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");
}

首先保存的数据是十六进制字符

#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");
}