在C中将数组中的两个索引合并为一个索引

在C中将数组中的两个索引合并为一个索引,c,arrays,C,Arrays,我有一个无符号字符数组,其中包含十六进制字节,如下所示: 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'; 我想合并它们,使其成为: 我尝试过使用sprintf,但我不知道如何在其中指定索引号。任何帮助。?因此您需要一个无符号字符结果[1

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

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';
我想合并它们,使其成为:


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

因此您需要一个无符号字符结果[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个字符和一个零分隔符才能形成字符串。

我假设您将一个8位值(例如0x0F,十进制为15)与一个字符值(如ASCII格式的“F”对应于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++;
}

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

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

我的建议。在这里你必须知道数组的大小。在你的例子中是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++;
}

假设数据为ASCII格式,并且您希望将其合并为原始二进制格式,则:

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

将数字转换为数字的简单方法是从数字中减去“0”:


这仅适用于digit>='0'&&digit您希望将字符转换为十六进制值并成对组合

下面是一个简单的程序来说明如何做到这一点:

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

所以,您想将由十六进制字符组成的字符串转换为字节数组,对吗?了解您的数据

sprintf不会帮助您,因为它会生成字符串。相反,您需要提取每个六进制字符的“值”,并使用它来计算字节的值

因此,让我们创建一个helper函数,将十六进制字符转换为其整数值,如果无效,则转换为-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;
  }
}
然后把这些碎片放在一起。我假设:

您知道输入数据的长度 长度为偶数,每个字节需要两个字符 您希望将结果放入同一数组中 来了

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

如何声明数组?将您的代码…'F'->'\xF'显示为十六进制字节。'\xFF':数组[0]@Marievi它是无符号字符数组[255];您的问题没有任何意义。单个无符号字符无法容纳字符串FF。可以合并它们,使数组[0]='\xFF';数组[1]='\xE2';数组[2]='\xAA';数组[3]='\xCC';,但这不是你要求的。小心i+1,根据问题,他有255而不是256;@grek40:在最后一次运行时,循环将以i=254输入,然后i+1仍然是255;所以应该可以,对吧?数据是ASCII格式而不是十六进制。在发布答案之前,请澄清OP实际要求的内容。即使我的答案的目标是编辑之前的问题,我将把它留在这里,直到OP发现涉及十六进制值字符时他实际得到了什么。我现在看到的问题可能会再次改变。这就是为什么我们应该在发布答案之前澄清OP实际想要什么。如果不可能知道,那么问题应该关闭。@Lundin在我看来,在编辑之前很清楚,这就是我回答的原因。正如我所评论的,我不想删除答案,直到我确信OP确实理解了他修改过的问题。您的代码将字符串放在另一个名为result的数组中,而不是按照最初的请求,放在数组中。这没有道理。
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);
}
#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;
}
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;
  }
}
unsigned char hexvals2byte(int upper, int lower)
{
  return (upper * 16 + lower);
}
#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);
}