AMcoder - javascript, python, java, html, php, sql

Տասնվեցական տող դեպի բայթ զանգված C-ում

Կա՞ որևէ ստանդարտ C ֆունկցիա, որը վեցանկյուն տողից վերածվում է բայթ զանգվածի:
Ես չեմ ուզում գրել իմ սեփական ֆունկցիան:

04.08.2010

  • Նկատի ունեք տա՞ղ, որը պարունակում է վեցանկյուն թվանշաններ: 04.08.2010
  • Այո, ես ունեմ օգտվողի մուտքագրման տող, ինչպիսին է abCD12ff34 ցանկացած երկարությամբ ›= 0, և ես ուզում եմ այն ​​փոխարկել բայթերի զանգվածի, ինչպիսիք են 0xaa, 0xcd, 0x12 և այլն: 04.08.2010

Պատասխանները:


1

Որքան ես գիտեմ, դա անելու համար ստանդարտ գործառույթ չկա, բայց դա հեշտ է հասնել հետևյալ կերպ.

#include <stdio.h>

int main(int argc, char **argv) {
    const char hexstring[] = "DEadbeef10203040b00b1e50", *pos = hexstring;
    unsigned char val[12];

     /* WARNING: no sanitization or error-checking whatsoever */
    for (size_t count = 0; count < sizeof val/sizeof *val; count++) {
        sscanf(pos, "%2hhx", &val[count]);
        pos += 2;
    }

    printf("0x");
    for(size_t count = 0; count < sizeof val/sizeof *val; count++)
        printf("%02x", val[count]);
    printf("\n");

    return 0;
}

Խմբագրել

Ինչպես նշեց Ալը, տողի մեջ վեցանկյուն թվանշանների կենտ թվի դեպքում, դուք պետք է համոզվեք, որ այն նախածանց եք դնում սկզբնական 0-ով: Օրինակ, վերը նշված օրինակով "f00f5" տողը սխալմամբ կգնահատվի որպես {0xf0, 0x0f, 0x05}, փոխարենը՝ պատշաճ {0x0f, 0x00, 0xf5}.

Օրինակը մի փոքր փոփոխեց՝ հասցեագրելու @MassimoCallegari-ի մեկնաբանությանը

04.08.2010
  • Սա լավ մոտեցում է, բայց տեղյակ եղեք, որ այն սխալ արդյունք կտա, եթե վեցանկյուն տողում կա տարօրինակ թվանշաններ (նշված զրոյական նիշը նախածանցում է ոչ թե առաջինին, այլ վերջին թվանշանին, ուստի 5ab5c-ն ավելի շուտ կտպվի որպես 0x5ab50c: քան 0x05ab5c): 05.08.2010
  • Էնդիանականությունն այստեղ նշանակություն չունի՞: 25.10.2015
  • @Geremia ոչ: Endianness-ը ի հայտ է գալիս միայն այն ժամանակ, երբ դուք վերաիմաստավորում եք բայթային զանգվածները որպես ամբողջ թվերի տեսակներ կամ հակառակը: commandcenter.blogspot.com/2012/04/byte-order-fallacy: html ED. եթե դուք տարօրինակ չեք և գրեք ձեր վեցանկյունը բառացիորեն քիչ-էնդիական կարգով: Ամեն դեպքում, սա վերցնում է յուրաքանչյուր զույգ թվանշան և դրանք դարձնում մեկ բայթ; ստացված էնդիանությունը նույնն է, ինչ բնօրինակը։ 04.12.2015
  • Արդյո՞ք սա աշխատում է, եթե աղբյուրի տողը մեծատառ է: օր. ՄՌՈՒՑԻ... 30.11.2017
  • @MassimoCallegari, այո, քանի որ scanf-ի x փոխակերպման ցուցիչը աշխատում է strtoul-ի նման տողերի վրա, որն ակնկալում է մուտքագրում, ինչպես սահմանված է C11 6.4.4.1-ում: 30.11.2017
  • ստուգեք իմ մոտեցումը. իմը թույլ է տալիս բացատներ որպես բաժանարարներ և խառը տառեր՝ stackoverflow.com/a/56247335/236062 22.05.2019

  • 2

    Ես գտա այս հարցը Գուգլինգի կողմից նույն բանի համար: Ինձ դուր չի գալիս sscanf() կամ strtol() կանչելու գաղափարը, քանի որ դա չափազանցված է թվում: Ես գրել եմ արագ ֆունկցիա, որը չի հաստատում, որ տեքստը իսկապես բայթ հոսքի տասնվեցական ներկայացում է, բայց կներառի վեցանկյուն թվանշանների կենտ թիվը.

    uint8_t tallymarker_hextobin(const char * str, uint8_t * bytes, size_t blen)
    {
       uint8_t  pos;
       uint8_t  idx0;
       uint8_t  idx1;
    
       // mapping of ASCII characters to hex values
       const uint8_t hashmap[] =
       {
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, //  !"#$%&'
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ()*+,-./
         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // 01234567
         0x08, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 89:;<=>?
         0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // @ABCDEFG
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // HIJKLMNO
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // PQRSTUVW
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // XYZ[\]^_
         0x00, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00, // `abcdefg
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // hijklmno
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // pqrstuvw
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // xyz{|}~.
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00  // ........
       };
    
       bzero(bytes, blen);
       for (pos = 0; ((pos < (blen*2)) && (pos < strlen(str))); pos += 2)
       {
          idx0 = (uint8_t)str[pos+0];
          idx1 = (uint8_t)str[pos+1];
          bytes[pos/2] = (uint8_t)(hashmap[idx0] << 4) | hashmap[idx1];
       };
    
       return(0);
    }
    
    27.05.2014
  • Դուք կարող եք նվազեցնել քարտեզի չափը մինչև 32 բայթ՝ պարզապես ավելացնելով 4 տրամաբանական հրահանգներ, ինչը լավ փոխզիջում է. idx0 = (uint8_t)str[pos+0] & 0x1F ^ 0x10; և նույնը idx1-ի համար: ապա դուք կարող եք հեռացնել բոլոր բայթերը 01234567 տողից առաջ և բոլոր բայթերը HIJKLMNO տողից հետո 11.11.2015
  • @5andr0, փակցված է որպես էություն՝ gist.github.com/vi/dd3b526e0078f Չի ստուգվել, չնայած. 25.08.2017
  • sscanf-ը և strtol-ը չափազանց շատ են, բայց ոչ անհրաժեշտ 32 տողանոց վեցանկյուն աղյուսակը: 18.01.2018
  • for (pos = 0; ((pos < (blen*2)) && (pos < strlen(str))); pos += 2) այս տողը ձախողվի 255-ից ավելի երկար տողերի դեպքում, քանի որ pos-ը uint8_t է, հետևաբար հանգույցի պայմանը միշտ կգնահատվի ճշմարիտ 25.01.2018
  • Այն կարող է լինել ընդամենը 71 բայթ, եթե ստիպում եք մեծատառ գրել, իսկ եթե ցանկանում եք ներառել փոքրատառ, ապա իրականում անհրաժեշտ է ընդամենը 103 բայթ: 103 բայթ կույտ՝ հարյուրավոր միլիոնավոր անգամ օգտագործվող քարտեզ պահելու համար, ինձ համար բավականին խելամիտ է, այնուամենայնիվ, հավելյալ հրահանգներ ավելացնելը կրկնություններին, որոնք կարող են կոչվել հարյուրավոր միլիոններ՝ այդ քարտեզի չափը նվազեցնելու համար, imo , ոչ այնքան խելամիտ: 02.12.2018
  • @zibri Աշխատում է 1,000,000 կրկնություններով, իմ կոդը լրացնելու համար միջինը 0,011 վայրկյան է, ձեր կոդը՝ 0,113 վայրկյան: Չափից դուրս գալու մասին իմ մեկնաբանությունը վերաբերում էր գործարկման ժամանակի արդյունավետությանը: Հետ նայելով մեկնաբանություններին, կան մի քանի լավ առաջարկներ, թե ինչպես բարելավել իմ կոդը, ներառյալ ստուգել pos փոփոխականը շրջագծման համար: Որպես կողմնակի նշում, դուք միշտ պետք է ներառեք սահմանների ստուգումներ ելքային գործառույթները գրելիս, քանի որ ձեր գործառույթը կարող է հանգեցնել բուֆերի գերակշռման, եթե մուտքային վեցանկյունն ավելի երկար է, քան ելքային բուֆերը: 04.06.2019
  • @DavidM.Syzdek ես գիտեմ.. ուղղակի կատակում էի... Ես նաև երբեմն սիրում եմ տեսնել, թե որքան արագ կարող է լինել կոդը.. ստուգեք github.com/zibri/rand2 և տեսեք՝ կարո՞ղ եք ավելի շատ օպտիմալացնել այն... Ես ստացել եմ 8 ԳԲ/վ արագություն, բայց դա կախված է բազմաթիվ գործոններից: Հետաքրքիր է, կարող է լինել ավելի շատ օպտիմիզացված, բայց կասկածում եմ.. 29.06.2019
  • Միանշանակ ամենաարագ լուծումը խորը ներկառուցված համակարգի համար: Եվ հաշմապը ֆլեշի մեջ է, ապա RAM-ը չի վատնում 31.01.2021

  • 3

    Բացի վերը նշված գերազանց պատասխաններից, ես կգրեի C ֆունկցիա, որը չի օգտագործում գրադարաններ և պաշտպանում է վատ տողերից:

    uint8_t* datahex(char* string) {
    
        if(string == NULL) 
           return NULL;
    
        size_t slength = strlen(string);
        if((slength % 2) != 0) // must be even
           return NULL;
    
        size_t dlength = slength / 2;
    
        uint8_t* data = malloc(dlength);
        memset(data, 0, dlength);
    
        size_t index = 0;
        while (index < slength) {
            char c = string[index];
            int value = 0;
            if(c >= '0' && c <= '9')
              value = (c - '0');
            else if (c >= 'A' && c <= 'F') 
              value = (10 + (c - 'A'));
            else if (c >= 'a' && c <= 'f')
              value = (10 + (c - 'a'));
            else {
              free(data);
              return NULL;
            }
    
            data[(index/2)] += value << (((index + 1) % 2) * 4);
    
            index++;
        }
    
        return data;
    }
    

    Բացատրություն:

    ա. ինդեքս / 2 | Ամբողջ թվերի միջև բաժանումը կկլորացնի արժեքը, այնպես որ 0/2 = 0, 1/2 = 0, 2/2 = 1, 3/2 = 1, 4/2 = 2, 5/2 = 2 և այլն: յուրաքանչյուր 2 տողային նիշի համար մենք արժեք ենք ավելացնում 1 տվյալների բայթին:

    բ. (ինդեքս + 1) % 2 | Մենք ուզում ենք, որ կենտ թվերը հանգեցնեն 1-ի և նույնիսկ 0-ի, քանի որ վեցանկյուն տողի առաջին նիշը ամենակարևորն է և պետք է բազմապատկվի 16-ով: Այսպիսով, 0 => 0 + 1 % 2 = 1, ինդեքս 1 => 1 + 1 % 2 = 0 և այլն:

    ք. ‹‹ 4 | 4-ով հերթափոխը բազմապատկվում է 16-ով: Օրինակ՝ b00000001 ‹‹ 4 = b00010000

    17.02.2016
  • Այն ձախողվում է, երբ նույնիսկ: if(slength % 2 == 0)-ը պետք է լինի if(slength % 2 != 0): Հակառակ դեպքում կարծես թե ստացվում է: 24.02.2017
  • Շնորհակալություն Ուղղակի դա ուղղեց: 10.01.2018
  • Հաճելի մեկը: Գերազանց է ներկառուցվածի համար: 10.01.2018
  • @MikeM Զգույշ եղեք ձեր առօրյայում ցուցիչը դինամիկ հատկացված բուֆերին (data) վերադարձնելուց: դա c ոճ չէ, թող օգտագործողին կերակրի բուֆեր 29.04.2018
  • Կարծես հիշողության արտահոսք կա։ Եթե ​​հանդիպում է ոչ տասնվեցական նիշ, NULL-ը վերադարձվում է, բայց հատկացված տվյալների բուֆերը չի ազատվում: 11.05.2018
  • @HowardYeh Շնորհակալություն: Ուղղված է 31.07.2018

  • 4

    Կարճ տողերի դեպքում strtol, strtoll և strtoimax-ը լավ կաշխատեն (նկատի ունեցեք, որ երրորդ արգումենտը հիմքն է, որը պետք է օգտագործվի տողը մշակելիս... սահմանեք այն 16-ի): Եթե ​​ձեր մուտքագրումը number-of-bits-in-the-longest-integer-type/4-ից երկար է, ապա ձեզ անհրաժեշտ կլինի այլ պատասխաններով առաջարկվող առավել ճկուն մեթոդներից մեկը:

    24.10.2011

    5

    Մայքլ Ֆուկարաքիսի գրառման մարմնավոր տարբերակը (քանի որ ես դեռ չունեմ այդ գրառմանը մեկնաբանություն ավելացնելու «հեղինակություն»).

    #include <stdio.h>
    #include <string.h>
    
    void print(unsigned char *byte_array, int byte_array_size)
    {
        int i = 0;
        printf("0x");
        for(; i < byte_array_size; i++)
        {
            printf("%02x", byte_array[i]);
        }
        printf("\n");
    }
    
    int convert(const char *hex_str, unsigned char *byte_array, int byte_array_max)
    {
        int hex_str_len = strlen(hex_str);
        int i = 0, j = 0;
    
        // The output array size is half the hex_str length (rounded up)
        int byte_array_size = (hex_str_len+1)/2;
    
        if (byte_array_size > byte_array_max)
        {
            // Too big for the output array
            return -1;
        }
    
        if (hex_str_len % 2 == 1)
        {
            // hex_str is an odd length, so assume an implicit "0" prefix
            if (sscanf(&(hex_str[0]), "%1hhx", &(byte_array[0])) != 1)
            {
                return -1;
            }
    
            i = j = 1;
        }
    
        for (; i < hex_str_len; i+=2, j++)
        {
            if (sscanf(&(hex_str[i]), "%2hhx", &(byte_array[j])) != 1)
            {
                return -1;
            }
        }
    
        return byte_array_size;
    }
    
    void main()
    {
        char *examples[] = { "", "5", "D", "5D", "5Df", "deadbeef10203040b00b1e50", "02invalid55" };
        unsigned char byte_array[128];
        int i = 0;
    
        for (; i < sizeof(examples)/sizeof(char *); i++)
        {
            int size = convert(examples[i], byte_array, 128);
            if (size < 0)
            {
                printf("Failed to convert '%s'\n", examples[i]);
            }
            else if (size == 0)
            {
                printf("Nothing to convert for '%s'\n", examples[i]);
            }
            else
            {
                print(byte_array, size);
            }
        }
    }
    
    23.06.2015

    6

    Օգտվողի 411313 կոդով որոշ փոփոխություններով ինձ համար գործում է հետևյալը.

    #include <stdio.h>
    #include <stdint.h> 
    #include <string.h>
    
    int main ()
    {
        char *hexstring = "deadbeef10203040b00b1e50";
        int i;
        unsigned int bytearray[12];
        uint8_t str_len = strlen(hexstring);
    
        for (i = 0; i < (str_len / 2); i++) {
            sscanf(hexstring + 2*i, "%02x", &bytearray[i]);
            printf("bytearray %d: %02x\n", i, bytearray[i]);
        }
    
        return 0;
    }
    
    02.11.2012
  • Սա նաև գրում է բուֆերի վերջը: 27.11.2012
  • int i; ... uint8_t str_len երկուսն էլ պետք է լինեն size_t: 29.09.2015
  • Այս կոդը նաև թույլ է տալիս տարածություն hex բայթերի միջև, օրինակ՝ char *hexstring = "de ad be ef 10 20 30 40 b0 0b 1e 50";, այն լավ է աշխատում: Հիանալի Խմբագրել. բայց մենք պետք է կարգավորենք օղակը: 24.02.2017
  • 12-ը կարող է փոխարինվել str_len-ով, իսկ միգուցե պարզապես char զանգված՝ տարածք խնայելու համար: 01.06.2020

  • 7

    Ահա HexToBin-ը և BinToHex-ը համեմատաբար մաքուր և ընթեռնելի են: (Նկատի ունեցեք, որ սկզբում վերադարձվել են թվային սխալի կոդերը սխալների գրանցման համակարգի միջոցով, ոչ թե պարզ -1 կամ -2):

    typedef unsigned char ByteData;
    ByteData HexChar (char c)
    {
        if ('0' <= c && c <= '9') return (ByteData)(c - '0');
        if ('A' <= c && c <= 'F') return (ByteData)(c - 'A' + 10);
        if ('a' <= c && c <= 'f') return (ByteData)(c - 'a' + 10);
        return (ByteData)(-1);
    }
    
    ssize_t HexToBin (const char* s, ByteData * buff, ssize_t length)
    {
        ssize_t result = 0;
        if (!s || !buff || length <= 0) return -2;
    
        while (*s)
        {
            ByteData nib1 = HexChar(*s++);
            if ((signed)nib1 < 0) return -3;
            ByteData nib2 = HexChar(*s++);
            if ((signed)nib2 < 0) return -4;
    
            ByteData bin = (nib1 << 4) + nib2;
    
            if (length-- <= 0) return -5;
            *buff++ = bin;
            ++result;
        }
        return result;
    }
    
    void BinToHex (const ByteData * buff, ssize_t length, char * output, ssize_t outLength)
    {
        char binHex[] = "0123456789ABCDEF";
    
        if (!output || outLength < 4) return (void)(-6);
        *output = '\0';
    
        if (!buff || length <= 0 || outLength <= 2 * length)
        {
            memcpy(output, "ERR", 4);
            return (void)(-7);
        }
    
        for (; length > 0; --length, outLength -= 2)
        {
            ByteData byte = *buff++;
    
            *output++ = binHex[(byte >> 4) & 0x0F];
            *output++ = binHex[byte & 0x0F];
        }
        if (outLength-- <= 0) return (void)(-8);
        *output++ = '\0';
    }
    
    25.01.2017

    8

    hextools.h

    #ifndef HEX_TOOLS_H
    #define HEX_TOOLS_H
    
    char *bin2hex(unsigned char*, int);
    
    unsigned char *hex2bin(const char*);
    
    #endif // HEX_TOOLS_H
    

    hextools.c

    #include <stdlib.h>
    
    char *bin2hex(unsigned char *p, int len)
    {
        char *hex = malloc(((2*len) + 1));
        char *r = hex;
    
        while(len && p)
        {
            (*r) = ((*p) & 0xF0) >> 4;
            (*r) = ((*r) <= 9 ? '0' + (*r) : 'A' - 10 + (*r));
            r++;
            (*r) = ((*p) & 0x0F);
            (*r) = ((*r) <= 9 ? '0' + (*r) : 'A' - 10 + (*r));
            r++;
            p++;
            len--;
        }
        *r = '\0';
    
        return hex;
    }
    
    unsigned char *hex2bin(const char *str)
    {
        int len, h;
        unsigned char *result, *err, *p, c;
    
        err = malloc(1);
        *err = 0;
    
        if (!str)
            return err;
    
        if (!*str)
            return err;
    
        len = 0;
        p = (unsigned char*) str;
        while (*p++)
            len++;
    
        result = malloc((len/2)+1);
        h = !(len%2) * 4;
        p = result;
        *p = 0;
    
        c = *str;
        while(c)
        {
            if(('0' <= c) && (c <= '9'))
                *p += (c - '0') << h;
            else if(('A' <= c) && (c <= 'F'))
                *p += (c - 'A' + 10) << h;
            else if(('a' <= c) && (c <= 'f'))
                *p += (c - 'a' + 10) << h;
            else
                return err;
    
            str++;
            c = *str;
    
            if (h)
                h = 0;
            else
            {
                h = 4;
                p++;
                *p = 0;
            }
        }
    
        return result;
    }
    

    հիմնական.գ

    #include <stdio.h>
    #include "hextools.h"
    
    int main(void)
    {
        unsigned char s[] = { 0xa0, 0xf9, 0xc3, 0xde, 0x44 };
    
        char *hex = bin2hex(s, sizeof s);
        puts(hex);
    
        unsigned char *bin;
        bin = hex2bin(hex);
    
        puts(bin2hex(bin, 5));
    
        size_t k;
        for(k=0; k<5; k++)
            printf("%02X", bin[k]);
    
        putchar('\n');
    
        return 0;
    }
    
    01.10.2017

    9

    Հետևյալ լուծումն է, որը ես գրել եմ կատարողականի պատճառով.

    void hex2bin(const char* in, size_t len, unsigned char* out) {
    
      static const unsigned char TBL[] = {
         0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  58,  59,  60,  61,
        62,  63,  64,  10,  11,  12,  13,  14,  15,  71,  72,  73,  74,  75,
        76,  77,  78,  79,  80,  81,  82,  83,  84,  85,  86,  87,  88,  89,
        90,  91,  92,  93,  94,  95,  96,  10,  11,  12,  13,  14,  15
      };
    
      static const unsigned char *LOOKUP = TBL - 48;
    
      const char* end = in + len;
    
      while(in < end) *(out++) = LOOKUP[*(in++)] << 4 | LOOKUP[*(in++)];
    
    }
    

    Օրինակ:

    unsigned char seckey[32];
    
    hex2bin("351aaaec0070d13d350afae2bc43b68c7e590268889869dde489f2f7988f3fee", 64, seckey);
    
    /*
      seckey = {
         53,  26, 170, 236,   0, 112, 209,  61,  53,  10, 250, 226, 188,  67, 182, 140, 
        126,  89,   2, 104, 136, 152, 105, 221, 228, 137, 242, 247, 152, 143,  63, 238
      };
    */
    

    Եթե ​​ձեզ հարկավոր չէ աջակցել փոքրատառերը.

    static const unsigned char TBL[] = {
         0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  58,  59,
        60,  61,  62,  63,  64,  10,  11,  12,  13,  14,  15
    };
    
    02.12.2018
  • նախազգուշացում. «in»-ի մի քանի չհաջորդված փոփոխություններ [-Wunsequence] 23.06.2019
  • Դուք կանչում եք չսահմանված վարքագիծ՝ կրկնակի մեջ ++-ով: 13.12.2019

  • 10
    char *hexstring = "deadbeef10203040b00b1e50", *pos = hexstring;
    unsigned char val[12];
    while( *pos )
    {
      if( !((pos-hexstring)&1) )
        sscanf(pos,"%02x",&val[(pos-hexstring)>>1]);
      ++pos;
    }
    

    sizeof(val)/sizeof(val[0]) ավելորդ է:

    05.08.2010
  • Սա գրում է բուֆերի վերջից հետո: Բացի այդ, &1 ստուգման փոխարեն պարզապես p+=2: 27.11.2012
  • unsigned char val[12];...sscanf(pos,"%02x",&val[...]);-ը սխալ է, քանի որ փորձում է unsigned-ը պահել unsigned char-ում: 29.09.2015


  • 12

    Երկու կարճ ռեժիմ՝ բայթը կամ բառը վերլուծելու համար՝ օգտագործելով strchr():

    // HexConverter.h
    #ifndef HEXCONVERTER_H
    #define HEXCONVERTER_H
    unsigned int hexToByte (const char *hexString);
    unsigned int hexToWord (const char *hexString);
    #endif
    
    
    // HexConverter.c
    #include <string.h> // for strchr()
    #include <ctype.h>  // for toupper()
    
    unsigned int hexToByte (const char *hexString)
    {
        unsigned int value;
        const char *hexDigits = "0123456789ABCDEF";
    
        value = 0;
        if (hexString != NULL)
        {
            char *ptr;
    
            ptr = strchr (hexDigits, toupper(hexString[0]));
            if (ptr != NULL)
            {
                value = (ptr - hexDigits) << 4;
    
                ptr = strchr (hexDigits, toupper(hexString[1]));
                if (ptr != NULL)
                {
                    value = value | (ptr - hexDigits);
                }
            }
        }
    
        return value;
    }
    
    unsigned int hexToWord (const char *hexString)
    {
        unsigned int value;
    
        value = 0;
        if (hexString != NULL)
        {
            value = (hexToByte (&hexString[0]) << 8) |
                    (hexToByte (&hexString[2]));
        }
    
        return value;
    }
    
    
    // HexConverterTest.c
    #include <stdio.h>
    
    #include "HexConverter.h"
    
    int main (int argc, char **argv)
    {
        (void)argc; // not used
        (void)argv; // not used
    
        unsigned int value;
        char *hexString;
    
        hexString = "2a";
        value = hexToByte (hexString);
        printf ("%s == %x (%u)\n", hexString, value, value);
    
        hexString = "1234";
        value = hexToWord (hexString);
        printf ("%s == %x (%u)\n", hexString, value, value);
    
        hexString = "0102030405060708090a10ff";
        printf ("Hex String: %s\n", hexString);
        for (unsigned int idx = 0; idx < strlen(hexString); idx += 2)
        {
            value = hexToByte (&hexString[idx]);
            printf ("%c%c == %x (%u)\n", hexString[idx], hexString[idx+1],
                    value, value);
        }
    
        return EXIT_SUCCESS;
    }

    04.12.2019

    13

    Ոչ: Բայց համեմատաբար աննշան է հասնել sscanf-ի ցիկլում:

    04.08.2010
  • SO-ում տրված ոչինչ չպետք է տրիվիալ լինի պատասխանի մեջ, հակառակ դեպքում հարցը գոյության միջոցներ չի ունենա 26.11.2018
  • և Օլիվերը ակնհայտորեն չգիտի դա, հակառակ դեպքում նա կտեղադրեր չնչին օղակը պատասխանում :) 22.05.2019

  • 14

    Փորձեք հետևյալ կոդը.

    static unsigned char ascii2byte(char *val)
    {
        unsigned char temp = *val;
    
        if(temp > 0x60) temp -= 39;  // convert chars a-f
        temp -= 48;  // convert chars 0-9
        temp *= 16;
    
        temp += *(val+1);
        if(*(val+1) > 0x60) temp -= 39;  // convert chars a-f
        temp -= 48;  // convert chars 0-9   
    
        return temp;
    
    }
    
    03.03.2013

    15

    Ահա իմ տարբերակը.

    /* Convert a hex char digit to its integer value. */
    int hexDigitToInt(char digit) {
        digit = tolower(digit);
        if ('0' <= digit && digit <= '9') //if it's decimal
            return (int)(digit - '0');
        else if ('a' <= digit && digit <= 'f') //if it's abcdef
            return (int)(digit - ('a' - 10));
        else
            return -1; //value not in [0-9][a-f] range
    }
    
    /* Decode a hex string. */
    char *decodeHexString(const char *hexStr) {
        char* decoded = malloc(strlen(hexStr)/2+1);
        char* hexStrPtr = (char *)hexStr;
        char* decodedPtr = decoded;
    
        while (*hexStrPtr != '\0') { /* Step through hexStr, two chars at a time. */
            *decodedPtr = 16 * hexDigitToInt(*hexStrPtr) + hexDigitToInt(*(hexStrPtr+1));
            hexStrPtr += 2;
            decodedPtr++;
        }
    
        *decodedPtr = '\0'; /* final null char */
        return decoded;
    }
    
    30.01.2016
  • Դուք ունեք հիանալի անջատված սխալ *(decodedPtr+1) = '\0'-ում (քանի որ decodedPtr-ն արդեն ավելացել էր վերջին գրումից հետո) 14.04.2016

  • 16

    Կարո՞ղ է ավելի պարզ լինել:

    uint8_t hex(char ch) {
        uint8_t r = (ch > 57) ? (ch - 55) : (ch - 48);
        return r & 0x0F;
    }
    
    int to_byte_array(const char *in, size_t in_size, uint8_t *out) {
        int count = 0;
        if (in_size % 2) {
            while (*in && out) {
                *out = hex(*in++);
                if (!*in)
                    return count;
                *out = (*out << 4) | hex(*in++);
                *out++;
                count++;
            }
            return count;
        } else {
            while (*in && out) {
                *out++ = (hex(*in++) << 4) | hex(*in++);
                count++;
            }
            return count;
        }
    }
    
    int main() {
        char hex_in[] = "deadbeef10203040b00b1e50";
        uint8_t out[32];
        int res = to_byte_array(hex_in, sizeof(hex_in) - 1, out);
    
        for (size_t i = 0; i < res; i++)
            printf("%02x ", out[i]);
    
        printf("\n");
        system("pause");
        return 0;
    }
    
    29.04.2018

    17

    Լավագույն միջոցը, որը ես գիտեմ.

    int hex2bin_by_zibri(char *source_str, char *dest_buffer)
    {
      char *line = source_str;
      char *data = line;
      int offset;
      int read_byte;
      int data_len = 0;
    
      while (sscanf(data, " %02x%n", &read_byte, &offset) == 1) {
        dest_buffer[data_len++] = read_byte;
        data += offset;
      }
      return data_len;
    }
    

    Ֆունկցիան վերադարձնում է dest_buffer-ում պահված փոխարկված բայթերի քանակը: Մուտքային տողը կարող է պարունակել բացատներ և խառը տառեր:

    «01 02 03 04 ab Cd eF աղբ AB»

    թարգմանվում է dest_buffer, որը պարունակում է 01 02 03 04 ab cd ef

    և նաև «01020304abCdeFgarbageAB»

    թարգմանվում է ինչպես նախկինում:

    Վերլուծությունը կանգ է առնում առաջին «սխալի» վրա։

    21.05.2019

    18

    Ահա ֆայլերի հետ գործ ունենալու լուծում, որը կարող է ավելի հաճախակի օգտագործվել...

    int convert(char *infile, char *outfile) {
    
    char *source = NULL;
    FILE *fp = fopen(infile, "r");
    long bufsize;
    if (fp != NULL) {
        /* Go to the end of the file. */
        if (fseek(fp, 0L, SEEK_END) == 0) {
            /* Get the size of the file. */
            bufsize = ftell(fp);
            if (bufsize == -1) { /* Error */ }
    
            /* Allocate our buffer to that size. */
            source = malloc(sizeof(char) * (bufsize + 1));
    
            /* Go back to the start of the file. */
            if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }
    
            /* Read the entire file into memory. */
            size_t newLen = fread(source, sizeof(char), bufsize, fp);
            if ( ferror( fp ) != 0 ) {
                fputs("Error reading file", stderr);
            } else {
                source[newLen++] = '\0'; /* Just to be safe. */
            }
        }
        fclose(fp);
    }
         
    int sourceLen = bufsize - 1;
    int destLen = sourceLen/2;
    unsigned char* dest = malloc(destLen);
    short i;  
    unsigned char highByte, lowByte;  
          
    for (i = 0; i < sourceLen; i += 2)  
    {  
            highByte = toupper(source[i]);  
            lowByte  = toupper(source[i + 1]);  
      
            if (highByte > 0x39)  
                highByte -= 0x37;  
            else  
                highByte -= 0x30;  
      
            if (lowByte > 0x39)  
                lowByte -= 0x37;  
            else  
                lowByte -= 0x30;  
      
            dest[i / 2] = (highByte << 4) | lowByte;  
    }  
            
    
    FILE *fop = fopen(outfile, "w");
    if (fop == NULL) return 1;
    fwrite(dest, 1, destLen, fop);
    fclose(fop);
    free(source);
    free(dest);
    return 0;
    }  
    
    24.06.2020

    19

    դուք կարող եք օգտագործել այս գործառույթը, որը

    1. գրված է նկատի ունենալով կատարողականությունը (ներկառուցված պրոցեսորների համար), ոչ scanf, strtol կամ dynamic memory allocation
    2. ունի պաշտպանիչ ելքային բուֆերային արտահոսքից և կենտ մուտքային str len-ից
    /// in: valid chars are 0-9 + A-F + a-f
    /// out_len_max==0: convert until the end of input string, out_len_max>0 only convert this many numbers
    /// returns actual out size
    int hexStr2Arr(unsigned char* out, const char* in, size_t out_len_max = 0)
    {
        if (!out_len_max)
            out_len_max = 2147483647; // INT_MAX
    
        const int in_len = strnlen(in, out_len_max * 2);
        if (in_len % 2 != 0)
            return -1; // error, in str len should be even
    
        // calc actual out len
        const int out_len = out_len_max < (in_len / 2) ? out_len_max : (in_len / 2);
    
        for (int i = 0; i < out_len; i++) {
            char ch0 = in[2 * i];
            char ch1 = in[2 * i + 1];
            uint8_t nib0 = (ch0 & 0xF) + (ch0 >> 6) | ((ch0 >> 3) & 0x8);
            uint8_t nib1 = (ch1 & 0xF) + (ch1 >> 6) | ((ch1 >> 3) & 0x8);
            out[i] = (nib0 << 4) | nib1;
        }
        return out_len;
    }
    

    օգտագործումը:

    unsigned char result[128];
    memset(result, 0, 128); // optional
    printf("result len=%d\n", hexStr2Arr(result, "0a0B10"));  // result = [0A 0B 10 00 00 ...]
    
    memset(result, 0, 128); // optional
    // only convert single number
    printf("result len=%d\n", hexStr2Arr(result, "0a0B10", 1)); // result = [0A 00 00 00 00 ...]
    
    02.06.2021
    Նոր նյութեր

    Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
    JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

    Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
    Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

    Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
    Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

    Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
    Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

    C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
    C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

    Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
    Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..