طريقة التحويل من عشري إلى عدد صحيح في C ، لا يمكن الحصول على صغيرة!

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

  •  06-07-2019
  •  | 
  •  

سؤال

يا الجميع, سريعة فقط شيء لدي عشري إلى عدد صحيح العامل ، ولكن أنا بحاجة للحصول على أرقام صغيرة.هذا ما لدي أي أفكار للحصول على للحصول على الظهور و قضية حساسة ؟

int htoi(char f[]) {
    int  z, n;
    n = 0;

    for (z = 0; f[z] >= '0' && f[z] <= 'F'; ++z) 
        if (f[z] >= 'A' && f[z] <= 'F')
            n = 10 + 16 * n + (f[z] - 'A');
        else
            n = 16 * n + (f[z] - '0');
}

ربما مجرد شيء صغير ، ولكن أود أن تشمل a-f و A-F.شكرا على مساعدتكم!

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

المحلول

إذا كنت تفعل هذا لمعرفة كيفية القيام بذلك، تجاهل هذا المنصب. إذا كنت تستخدم هذه الوظيفة لأنك بحاجة لتحويل سلسلة من الأرقام عرافة إلى int، يجب أن تأخذ نزهة في مكتبة القياسية. وظيفة القياسية strtol() تحويل سلسلة إلى long، والتي يمكن أن ننزل إلى int (أو unsigned int بينما كانت في ذلك). الحجة الثالثة هي قاعدة لتحويل ل- في هذه الحالة، هل تريد قاعدة 16 للعشري. أيضا، إذا ما أتيحت قاعدة 0، فإنه سيتولى عرافة إذا بدأت السلسلة مع 0x، ثماني اذا كان يبدأ مع 0، وعشري خلاف ذلك. انها وظيفة مفيدة جدا.


وتحرير: فقط لاحظت هذا، ولكن بينما نحن هنا، ومن الجدير بالذكر أنه يجب عليك عموما لا تستخدم int صفائف مؤشر. يحدد مستوى C نوع، ودعا size_t، الذي تم تصميمه لتخزين مؤشرات مجموعة. ومن المسلم به عموما على unsigned int أو unsigned long أو شيء من هذا، ولكن يتم ضمان أن تكون كبيرة بما يكفي لتخزين أي مجموعة أو مؤشر تعويض يمكنك استخدامها.

والمشكلة مع استخدام مجرد int هي أنه، من الناحية النظرية، ربما، يوما ما، أي شخص يمكن تمرير سلسلة أطول من INT_MAX، ثم int الخاص بك وسوف تفيض، وربما التفاف حولها، والبدء في قراءة الذاكرة التي ربما لا ينبغي لأنه باستخدام مؤشر سلبي. هذا من المستبعد جدا، خاصة بالنسبة لوظيفة من هذا القبيل، لأن قيمة int عودتك سوف تفيض قبل فترة طويلة امتدت مكافحة int الخاص بك، ولكن هو الشيء المهم أن نأخذ في الاعتبار.

ليكون صحيحا من الناحية الفنية، يجب عليك استخدام فقط نوع size_t المتغيرات صفائف المؤشر، أو على الأقل فقط استخدام أنواع unsigned، إلا إذا كنت تريد حقا أن محاولة الوصول إلى العناصر السلبية (التي عادة ما تكون فكرة سيئة إلا إذا كنت تعرف ما لك " إعادة به). ومع ذلك، انها ليست مشكلة كبيرة هنا.

نصائح أخرى

إنشاء وظيفة أخرى الأمر الذي يجعل رقما عشري إلى عدد صحيح:

int hex_digit_to_integer(char digit) {
    if (digit >= 'A' && digit <= 'F') {
        return digit - 'A' + 10;
    } else if (digit >= 'a' && digit <= 'f') {
        return digit - 'a' + 10;
    } else if (digit >= '0' && digit <= '9') {
        return digit - '0';
    }

    return -1; // Bad input.
}

لاحظ كيف يتعامل مع أربع حالات:  * digit هو خطاب A..F العليا الحالة،  * digit يبعد الحالة الأدنى حرف a..f،  * digit هو عشري أرقام 0..9، و  * digit لا شيء مما سبق.

والآن استخدام وظيفة جديدة في وظيفة الأصلي:

int htoi(char f[]) {
    int z, n;
    n = 0;

    /* Loop until we get something which isn't a digit (hex_digit_to_integer returns something < 0). */
    for (z=0; hex_digit_to_integer(f[z]) >= 0; ++z) {
        n = 16 * n + hex_digit_to_integer(f[z]);
    }
}

لاحظ كيف أنظف بكثير تبدو وظيفة جديدة؟

إذا كنت المغامرة، يمكنك استخدام هذه الوظيفة السحر (والذي لا يعالج المدخلات سيئة، لذلك كنت بحاجة للتأكد من أن مسبقا):

int hex_digit_to_integer(char digit) {
    return digit - (digit & 64 ? 55 : 48) & 15;
}

واستبدال كافة F [ض] مع متغير مخصص. تعيين هذا المتغير مع toupper (و [ض])

وهنا بعض رمز من حزمة NPS NSRL بلوم:

static int *hexcharvals = 0;

/** Initialization function is used solely for hex output
 */
static void nsrl_bloom_init()
{
    if(hexcharvals==0){
        /* Need to initialize this */
        int i;
        hexcharvals = calloc(sizeof(int),256);
        for(i=0;i<10;i++){
            hexcharvals['0'+i] = i;
        }
        for(i=10;i<16;i++){
            hexcharvals['A'+i-10] = i;
            hexcharvals['a'+i-10] = i;
        }
    }
}

/**
 * Convert a hex representation to binary, and return
 * the number of bits converted.
 * @param binbuf output buffer
 * @param binbuf_size size of output buffer in bytes.
 * @param hex    input buffer (in hex)
 */
int nsrl_hex2bin(unsigned char *binbuf,size_t binbuf_size,const char *hex)
{
    int bits = 0;
    if(hexcharvals==0) nsrl_bloom_init();
    while(hex[0] && hex[1] && binbuf_size>0){
        *binbuf++ = ((hexcharvals[(unsigned char)hex[0]]<<4) |
                     hexcharvals[(unsigned char)hex[1]]);
        hex  += 2;
        bits += 8;
        binbuf_size -= 1;
    }
    return bits;
}

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

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

هل يمكن أن تحاول sscanf بدلا من ذلك:

#include <stdio.h>

...

//NOTE: buffer overflow if f is not terminated with \0 !!
int htoi(char f[]){
  int intval = -1;
  if (EOF == sscanf(f, "%x", &intval))
    return -1; //error
  return intval;
}

وخياران:

تحويل إلى الحالة العلوي قبل أن تفعل المسح الضوئي.

واضافة ثانية واذا كان في حلقة الأربعة التي يعالج الحالة الأدنى.

جرب هذا بدلا من ذلك:

int htoi (char f[]) {
    int  z, n;
    n = 0;
    for (z = 0; f[z] != '\0'; ++z) { 
        if (f[z] >= '0' && f[z] <= '9') {
            n = n * 16 + f[z] - '0';
        } else {
            if (f[z] >= 'A' && f[z] <= 'F') {
                n = n * 16 + f[z] - 'A' + 10;
            } else {
                if (f[z] >= 'a' && f[z] <= 'f') {
                    n = n * 16 + f[z] - 'a' + 10;
                } else {
                    break;
                }
            }
        }
    }
    return n;
}

فإنه لا يزال يعامل الإدخال بنفس الطريقة لك (كنت تميل إلى استخدام مؤشرات لكنها في بعض الأحيان من الصعب أن نفهم قبل المبتدئين) ولكن يدخل ثلاث قضايا منفصلة, 0-9, A-F و a-f, علاج بعضها بشكل مناسب.

الأصلي الخاص بك رمز شأنها أن تسمح في الواقع خاطئة الشخصيات (الستة بين '9' و 'A') تنتج نتائج غير صحيحة على أساس منها.

لاحظ أن هذه التعليمات البرمجية الجديدة فقط عادة تنتهي حلقة في نهاية السلسلة.إيجاد صالح عرافة الطابع الخروج من الحلقة ، وظيفيا متطابقة إلى إنهاء حالة.

استخدم strtol () من فضلك. هذه هي وظيفة C90 القياسية وأكثر من ذلك بكثير قوية من معظم تطبيقات ساذجة. كما أنها تدعم تحويل السلس من ديسمبر (بدون اختصار)، عرافة (0X) وأكتوبر (بدءا 0).

وتنفيذ تستخدم تناوب التحول بدلا من الضرب.

int HexToDec(char *Number)
{

    unsigned int val = 0;

    int i , nibble;
    for(i = strlen( Number ) - 1; i >= 0; --i, nibble += 4)
    {
        const char hex = Number[i];
        if (hex >= '0' && hex <= '9')
            val += (hex - '0')<<nibble;
        else if (hex >= 'A' && hex <= 'F')
            val += (hex - 'A' + 10)<<nibble;
        else if (hex >= 'a' && hex <= 'f')
            val += (hex - 'a' + 10)<<nibble;
        else
            return -1;
    }
    return val;
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top