تحويل سلسلة سداسية عشرية إلى عدد صحيح بكفاءة في C؟

StackOverflow https://stackoverflow.com/questions/10324

  •  08-06-2019
  •  | 
  •  

سؤال

في لغة C، ما هي الطريقة الأكثر فعالية لتحويل سلسلة من الأرقام السداسية إلى ثنائية unsigned int أو unsigned long?

على سبيل المثال، إذا كان لدي 0xFFFFFFFE, ، أريد int مع القيمة الأساسية 10 4294967294.

هل كانت مفيدة؟

المحلول

انت تريد strtol أو strtoul.أنظر أيضاً صفحة رجل يونكس

نصائح أخرى

يحرر: أصبح الآن متوافقًا مع برامج التحويل البرمجي MSVC وC++ والمترجمات غير التابعة لـ GNU (انظر النهاية).

كان السؤال "الطريقة الأكثر كفاءة". لا يحدد OP النظام الأساسي ، يمكن أن يقوم بتجميع رقاقة ATMEL القائمة على RISC مع 256 بايت من تخزين الفلاش لرمزه.

للعلم، ولأولئك (مثلي) الذين يقدرون الفرق بين "أسهل طريقة" و"أكثر الطرق فعالية"، والذين يستمتعون بالتعلم...

static const long hextable[] = {
   [0 ... 255] = -1, // bit aligned access into this table is considerably
   ['0'] = 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, // faster for most modern processors,
   ['A'] = 10, 11, 12, 13, 14, 15,       // for the space conscious, reduce to
   ['a'] = 10, 11, 12, 13, 14, 15        // signed char.
};

/** 
 * @brief convert a hexidecimal string to a signed long
 * will not produce or process negative numbers except 
 * to signal error.
 * 
 * @param hex without decoration, case insensitive. 
 * 
 * @return -1 on error, or result (max (sizeof(long)*8)-1 bits)
 */
long hexdec(unsigned const char *hex) {
   long ret = 0; 
   while (*hex && ret >= 0) {
      ret = (ret << 4) | hextable[*hex++];
   }
   return ret; 
}

لا يتطلب أي مكتبات خارجية، ويجب أن يكون سريعًا للغاية.يتعامل مع الأحرف الكبيرة والصغيرة والأحرف غير الصالحة والمدخلات السداسية ذات الحجم الفردي (على سبيل المثال:0xfff)، والحد الأقصى للحجم يقتصر فقط على المترجم.

بالنسبة للمترجمين أو المترجمين من خارج دول مجلس التعاون الخليجي أو C++ الذين لن يقبلوا الإعلان السداسي الرائع.

استبدل العبارة الأولى بهذا الإصدار (الأطول، ولكن الأكثر توافقًا):

static const long hextable[] = { 
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1, 0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,-1,10,11,12,13,14,15,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,10,11,12,13,14,15,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};

جرب هذا:

#include <stdio.h>
int main()
{
    char s[] = "fffffffe";
    int x;
    sscanf(s, "%x", &x);
    printf("%u\n", x);
}

إذا لم يكن لديك stdlib فعليك القيام بذلك يدويًا.

unsigned long hex2int(char *a, unsigned int len)
{
    int i;
    unsigned long val = 0;

    for(i=0;i<len;i++)
       if(a[i] <= 57)
        val += (a[i]-48)*(1<<(4*(len-1-i)));
       else
        val += (a[i]-55)*(1<<(4*(len-1-i)));

    return val;
}

ملحوظة:يفترض هذا الرمز الأحرف الكبيرة A-F.لا يعمل هذا إذا كان len يتجاوز أطول عدد صحيح 32 أو 64 بت، ولا يوجد تعويض خطأ للأحرف السداسية غير القانونية.

بالنسبة لوحدات التحكم الدقيقة AVR، كتبت الوظيفة التالية، بما في ذلك التعليقات ذات الصلة لتسهيل الفهم:

/**
 * hex2int
 * take a hex string and convert it to a 32bit number (max 8 hex digits)
 */
uint32_t hex2int(char *hex) {
    uint32_t val = 0;
    while (*hex) {
        // get current character then increment
        char byte = *hex++; 
        // transform hex character to the 4bit equivalent number, using the ascii table indexes
        if (byte >= '0' && byte <= '9') byte = byte - '0';
        else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10;
        else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10;    
        // shift 4 to make space for new digit, and add the 4 bits of the new digit 
        val = (val << 4) | (byte & 0xF);
    }
    return val;
}

مثال:

char *z ="82ABC1EF";
uint32_t x = hex2int(z);
printf("Number is [%X]\n", x);

سوف الإخراج:enter image description here

كما يحدث غالبًا، فإن سؤالك يعاني من خطأ/غموض لفظي خطير.في الكلام الشائع، لا يهم هذا الأمر عادة، ولكن في سياق هذه المشكلة المحددة يكون الأمر في غاية الأهمية.

كما ترى، لا يوجد شيء مثل "القيمة السداسية" و"القيمة العشرية" (أو "الرقم السداسي" و"الرقم العشري")."ست عشري" و"عشري" هي خصائص التوكيلات من القيم.وفي الوقت نفسه، القيم (أو الأرقام) في حد ذاتها ليس لها تمثيل، لذلك لا يمكن أن تكون "ست عشرية" أو "عشرية".على سبيل المثال، 0xF و 15 في بناء جملة C هما مختلفان التوكيلات ل نفس العدد.

أعتقد أن سؤالك، بالطريقة التي تم ذكره بها، يشير إلى أنك بحاجة إلى تحويل تمثيل ASCII السداسي لقيمة (أي.سلسلة) إلى تمثيل عشري ASCII لقيمة (سلسلة أخرى).إحدى الطرق للقيام بذلك هي استخدام تمثيل عدد صحيح كتمثيل وسيط:أولاً، قم بتحويل تمثيل ASCII السداسي إلى عدد صحيح بحجم كافٍ (باستخدام وظائف من strto... مجموعة، مثل strtol)، ثم قم بتحويل العدد الصحيح إلى التمثيل العشري ASCII (باستخدام sprintf).

إذا لم يكن هذا ما تحتاج إلى القيام به، فعليك توضيح سؤالك، لأنه من المستحيل معرفة ذلك من طريقة صياغة سؤالك.

@ اريك

لماذا يتم التصويت على حل الكود الناجح؟بالتأكيد، إنها طريقة قبيحة وقد لا تكون الطريقة الأسرع للقيام بذلك، ولكنها مفيدة أكثر من قول "strtol" أو "sscanf".إذا جربت ذلك بنفسك، فسوف تتعلم شيئًا عن كيفية حدوث الأشياء تحت الغطاء.

لا أعتقد حقًا أنه كان ينبغي التصويت على الحل الذي قدمته، ولكن أعتقد أن سبب حدوثه هو أنه أقل عملية.فكرة التصويت هي أن الإجابة "الأفضل" سوف تطفو إلى الأعلى، وبينما قد تكون إجابتك أكثر إفادة حول ما يحدث تحت الغطاء (أو الطريقة التي قد يحدث بها ذلك)، فهي بالتأكيد ليست أفضل طريقة لتحليل الأرقام السداسية. في نظام الإنتاج.

مرة أخرى، لا أعتقد أن هناك أي خطأ في إجابتك من وجهة نظر تعليمية، وأنا بالتأكيد لن أصوت عليها (ولم أصوت عليها).لا تثبط عزيمتك وتتوقف عن النشر لمجرد أن بعض الأشخاص لم يعجبهم أحد إجاباتك.يحدث ذلك.

أشك في أن إجابتي ستجعلك تشعر بالتحسن بشأن التصويت ضد إجابتك، لكنني أعلم أنه ليس من الممتع بشكل خاص عندما تسأل عن سبب التصويت ضد شيء ما و لا أحد يجيب.

بالنسبة للسلاسل السداسية الأكبر حجمًا كما في المثال الذي أحتاج إلى استخدامه com.strtoul.

سداسي عشري إلى عشري.لا تقم بتشغيله على المترجمين عبر الإنترنت، لأنه لن يعمل.

#include<stdio.h>
void main()
{
    unsigned int i;
    scanf("%x",&i);
    printf("%d",i);
}

لماذا هو حل رمز يعمل على تصويت؟بالتأكيد ، إنه قبيح ...

ربما لأنه فضلا عن كونه قبيح فهو ليس تعليميا و لا عمل.أيضًا، أظن أن معظم الأشخاص، مثلي، لا يملكون القدرة على التحرير في الوقت الحالي (وبالحكم على الرتبة المطلوبة - فلن يتمتعوا بذلك أبدًا).

يمكن أن يكون استخدام المصفوفة أمرًا جيدًا لتحقيق الكفاءة، ولكن لم يتم ذكر ذلك في هذا الكود.كما أنه لا يأخذ في الاعتبار الأحرف الكبيرة والصغيرة، لذا فهو لا يعمل مع المثال الوارد في السؤال.FFFFFFFE

@ اريك

كنت أتمنى في الواقع أن أرى معالج C ينشر شيئًا رائعًا حقًا، يشبه إلى حد ما ما فعلته ولكن أقل إسهابًا، بينما لا أزال أفعل ذلك "يدويًا".

حسنًا، أنا لست خبيرًا في لغة C، ولكن إليك ما توصلت إليه:

unsigned int parseHex(const char * str)
{
    unsigned int val = 0;
    char c;

    while(c = *str++)
    {
        val <<= 4;

        if (c >= '0' && c <= '9')
        {
            val += c & 0x0F;
            continue;
        }

        c &= 0xDF;
        if (c >= 'A' && c <= 'F')
        {
            val += (c & 0x07) + 9;
            continue;
        }

        errno = EINVAL;
        return 0;
    }

    return val;
}

لقد كان لدي في الأصل المزيد من أقنعة البت بدلاً من المقارنات، لكنني أشك بشدة في أن أقنعة البت هي أسرع من المقارنة على الأجهزة الحديثة.

جرب هذا للتحويل من عشري إلى سداسي عشري

    #include<stdio.h>
    #include<conio.h>

    int main(void)
    {
      int count=0,digit,n,i=0;
      int hex[5];
      clrscr();
      printf("enter a number   ");
      scanf("%d",&n);

      if(n<10)
      {
          printf("%d",n);
      }

      switch(n)
      {
          case 10:
              printf("A");
            break;
          case 11:
              printf("B");
            break;
          case 12:
              printf("B");
            break;
          case 13:
              printf("C");
            break;
          case 14:
              printf("D");
            break;
          case 15:
              printf("E");
            break;
          case 16:
              printf("F");
            break;
          default:;
       }

       while(n>16)
       {
          digit=n%16;
          hex[i]=digit;
          i++;
          count++;
          n=n/16;
       }

       hex[i]=n;

       for(i=count;i>=0;i--)
       {
          switch(hex[i])
          {
             case 10:
                 printf("A");
               break;
             case 11:
                 printf("B");
               break;
             case 12:
                 printf("C");
               break;
             case  13:
                 printf("D");
               break;
             case 14:
                 printf("E");
               break;
             case 15:
                 printf("F");
               break;
             default:
                 printf("%d",hex[i]);
          }
    }

    getch();

    return 0;
}
#include "math.h"
#include "stdio.h"
///////////////////////////////////////////////////////////////
//  The bits arg represents the bit say:8,16,32...                                                                                                              
/////////////////////////////////////////////////////////////
volatile long Hex_To_Int(long Hex,char bits)
{
    long Hex_2_Int;
    char byte;
    Hex_2_Int=0;

    for(byte=0;byte<bits;byte++)
    {
        if(Hex&(0x0001<<byte))
            Hex_2_Int+=1*(pow(2,byte));
        else
            Hex_2_Int+=0*(pow(2,byte));
    }

    return Hex_2_Int;
}
///////////////////////////////////////////////////////////////
//                                                                                                                  
/////////////////////////////////////////////////////////////

void main (void)
{
    int Dec;   
    char Hex=0xFA;
    Dec= Hex_To_Int(Hex,8);  //convert an 8-bis hexadecimal value to a number in base 10
    printf("the number is %d",Dec);
}

في لغة C يمكنك تحويل رقم سداسي عشري إلى رقم عشري بعدة طرق.إحدى الطرق هي تحويل الرقم السداسي العشري إلى عدد صحيح.أنا شخصياً وجدت أن هذا بسيط وصغير.

إليك نموذج تعليمة برمجية لتحويل رقم سداسي عشري إلى رقم عشري بمساعدة عملية التحويل.

#include <stdio.h>

int main(){
    unsigned char Hexadecimal = 0x6D;   //example hex number
    int Decimal = 0;    //decimal number initialized to 0


        Decimal = (int) Hexadecimal;  //conversion

    printf("The decimal number is %d\n", Decimal);  //output
    return 0;
}

يعمل هذا حاليًا فقط مع الأحرف الصغيرة ولكن من السهل جدًا جعله يعمل مع كليهما.

cout << "\nEnter a hexadecimal number: ";
cin >> hexNumber;
orighex = hexNumber;

strlength = hexNumber.length();

for (i=0;i<strlength;i++)
{
    hexa = hexNumber.substr(i,1);
    if ((hexa>="0") && (hexa<="9"))
    {
        //cout << "This is a numerical value.\n";
    }
    else
    {
        //cout << "This is a alpabetical value.\n";
        if (hexa=="a"){hexa="10";}
        else if (hexa=="b"){hexa="11";}
        else if (hexa=="c"){hexa="12";}
        else if (hexa=="d"){hexa="13";}
        else if (hexa=="e"){hexa="14";}
        else if (hexa=="f"){hexa="15";}
        else{cout << "INVALID ENTRY! ANSWER WONT BE CORRECT\n";}
    }
    //convert from string to integer

    hx = atoi(hexa.c_str());
    finalhex = finalhex + (hx*pow(16.0,strlength-i-1));
}
cout << "The hexadecimal number: " << orighex << " is " << finalhex << " in decimal.\n";
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top