سؤال

ولدي عدد كبير المخزنة في سلسلة ومحاولة استخراج رقم واحد. ولكن ما هي الاختلافات بين تلك المكالمات؟

#include <iostream>
#include <string>

int main(){
    std::string bigNumber = "93485720394857230";
    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);
    int digit2 = atoi(&bigNumber.at(5))
    int digit3 = atoi(&bigNumber.at(12));
    std::cout << "digit: " << digit << std::endl;
    std::cout << "digit2: " << digit2 << std::endl;
    std::cout << "digit3: " << digit3 << std::endl;
}

وهذا سوف تنتج الإخراج التالي.

<اقتباس فقرة>   

وأرقام: 7

     

وdigit2: 2147483647

     

وdigit3: 57230

وأول واحد هو النتيجة المرجوة. يبدو ثانية واحدة بالنسبة لي أن يكون رقم عشوائي، وأنا لا يمكن العثور في السلسلة. والثالث هو نهاية السلسلة، ولكن ليس مجرد رقم واحد كما كنت أتوقع، ولكن ما يصل مؤشر ال12 إلى نهاية السلسلة من. يمكن للشخص شرح مختلف النواتج لي؟

وتحرير: وهذا سيكون حلا مقبولا

char tmp[2] = {bigNumber.at(5), '\0'};
int digit = atoi(tmp);
std::cout << "digit: " << digit << std::endl;
هل كانت مفيدة؟

المحلول

وكل ذلك هو أكثر أو أقل تفسيرها.

int main(){
    std::string bigNumber = "93485720394857230";

وهذا الخط نسخ حرف واحد '5' إلى المتغير الحرف. <الإضراب> atoi سيتم تحويل هذا بشكل صحيح. atoi تتوقع أن المعلمة سلسلة هي صالحة 0 سلسلة إنهاؤها. &tmp ليست سوى مؤشر إلى متغير حرف - هي غير معرفة سلوك هذه الدعوة منذ الذاكرة مباشرة بعد الحرف في الذاكرة غير معروف. على وجه الدقة، سيكون لديك لإنشاء سلسلة لاغية إنهاء وتمرير ذلك في. *

    char tmp = bigNumber.at(5);
    int digit = atoi(&tmp);

وهذا الخط يحصل مؤشر إلى حرف في موقف 5 في السلسلة. يحدث هذا مؤشر إلى سلسلة عدد كبير الأصلي فوق - حتى المعلمة سلسلة لatoi يشبه السلسلة "5720394857230". سوف atoi بوضوح oveflow يحاولون تحويل هذا إلى عدد صحيح لأنه لا عدد صحيح 32 بت سوف يعقد هذا.

    int digit2 = atoi(&bigNumber.at(5))

وهذا الخط يحصل على المؤشر إلى السلسلة في موقف 12. المعلمة إلى atoi هي السلسلة "57230". يتم تحويل هذا إلى عدد صحيح 57230 بشكل صحيح.

    int digit3 = atoi(&bigNumber.at(12));

و...     }

ومنذ كنت تستخدم C ++، هناك طرق أجمل لتحويل سلاسل الأحرف إلى أعداد صحيحة. واحدة أن أنا جزئي لهو الدافع lexical_cast المكتبة. يمكنك استخدام مثل هذا:

char tmp = bigNumber.at(5);
// convert the character to a string then to an integer
int digit = boost::lexical_cast<int>(std::string(tmp));

// this copies the whole target string at position 5 and then attempts conversion
// if the conversion fails, then a bad_lexical_cast is thrown
int digit2=boost::lexical_cast<int>(std::string(bigNumber.at(5)));

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

نصائح أخرى

وأنا أعرف لماذا يتم عرض عدد 2ND.

من الإشارة atoi.

<اقتباس فقرة>   

إذا القيمة الصحيحة هي خارج نطاق القيم للتمثيل، على INT_MAX أو يتم إرجاع INT_MIN.

و2147483647 هو INT_MAX

وbigNumber.at() لا يرجع سلسلة جديدة مع حرف واحد ولكن عنوان حرف في السلسلة. وبالتالي فإن الدعوة الثانية هي في الواقع:

atoi("720394857230")

والذي يسبب الخوارزمية الداخلية لتجاوز.

وكما أن المكالمة الأولى وهذا خطير جدا لأنه يعتمد على قيمة (عشوائي) في الذاكرة في (&tmp)+1.

لديك لتخصيص سلسلة مع اثنين من الشخصيات، تعيين حرف واحد من bigNumber.at() لأول و\0 إلى الثانية ومن ثم استدعاء atoi() مع عنوان سلسلة مؤقتة.

ويجب أن يكون حجة لatoi سلسلة إنهاء الصفر.

وظيفة at يعطي مؤشر إلى شار في السلسلة. وظيفة atoi تحويل سلسلة إلى int، ليس فقط حرف واحد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top