كيف يمكنني معرفة ما إذا كانت الدالة c atoi قد فشلت أم أنها كانت سلسلة من الأصفار؟
سؤال
عند استخدام الوظيفة atoi
(أو strtol
أو وظائف مشابهة في هذا الشأن)، كيف يمكنك معرفة ما إذا كان تحويل الأعداد الصحيحة قد فشل أو إذا كانت السلسلة C التي تم تحويلها عبارة عن 0
?
بسبب ما أفعله، 0
هي قيمة مقبولة وقد تحتوي السلسلة C التي يتم تحويلها على أي عدد من 0
س.وقد تحتوي أيضًا على مسافة بيضاء بادئة.
المحلول
بالنسبة لـ C++ 11 والإصدارات الأحدث:
وظيفة go-to لتحويل السلسلة إلى عدد صحيح هي الآن stoi
, ، والذي يستغرق أ string
ويعيد ا int
, ، أو يلقي استثناءً على الخطأ.
لا داعي للإسهاب istringstream
hack المذكورة في الإجابة المقبولة بعد الآن.
(هناك ايضا stol
/stoll
/stof
/stod
/stold
ل long
/long long
/float
/double
/long double
التحويلات على التوالي.)
نصائح أخرى
وظيفة مناسبة (طالما كنت تصر على استخدام وظائف على غرار C) هو strtol
ويتبع شفرة التحويل قد تبدو ك
const char *number = "10"; /* for example */
char *end;
long value = strtol(number, &end, 10);
if (end == number || *end != '\0' || errno == ERANGE)
/* ERROR, abort */;
/* Success */
/* Add whatever range checks you want to have on the value of `value` */
وبعض الملاحظات:
وstrtol
يسمح (بمعنى: يتخطى بهدوء) بيضاء أمام العدد الفعلي. إذا كنت ما لعلاج مثل هذه المسافات الكبرى، وخطأ، لديك للتحقق من ذلك بنفسك.
والاختيار ل*end != '\0'
يتأكد أن لا يوجد شيء بعد أرقام. إذا كنت ترغب في السماح الشخصيات الأخرى بعد العدد الفعلي (بيضاء؟)، وهذا الاختيار لابد من تعديلها وفقا لذلك.
وP.S. وأضفت في وقت لاحق الاختيار end == number
للقبض على تسلسل المدخلات فارغة. "كل المسافات" و "أي رقم على الإطلاق" قد تم القبض المدخلات عن طريق شيك *end != '\0'
وحدها. قد يكون من المنطقي للقبض على مدخلات فارغة مسبقا بالرغم من ذلك. في هذا الاختيار حالة end == number
سوف / قد تصبح غير ضرورية.
وبما أن الموسومة هذا ج ++ أ >:
template< typename T >
inline T convert(const std::string& str)
{
std::istringstream iss(str);
T obj;
iss >> std::ws >> obj >> std::ws;
if(!iss.eof())
throw "dammit!";
return obj;
}
ومن صفحة رجل لstrtol ():
<اقتباس فقرة> إذا endptr ليس NULL، strtol () يخزن عنوان غير صالح الأول
حرف في * endptr. إذا لم تكن هناك أرقام على الإطلاق، ومع ذلك، strtol ()
يخزن القيمة الأصلية nptr في * endptr. (وهكذا، إذا * nptr ليس
'\0'
لكن ** endptr هو '\0'
في المقابل، كانت السلسلة بأكملها صالحة).
وبديل لstrtol
هو sscanf
، على الرغم من انها قليلا الثقيلة الوزن:
const char *numStr = "12345"; // input string
int value;
if(sscanf(numStr, "%d", &value) == 1)
; // parsing succeeded, use value
else
; // error
ولكن، وهذا يسمح الرائدة بيضاء في سلسلة الخاص بك (التي قد تكون أو لا يكون مرغوبا فيه)، وأنه يسمح بأي شيء لدرب عدد، وذلك "123abc" لن يقبل العودة و123. إذا كنت تريد أن يكون تشديد الرقابة، الذهاب مع strtol()
، و<لأ href = "https://stackoverflow.com/questions/1640720/how-do-i-tell-if-the-c-function-atoi-failed-or-if-it-was- على بعد سلسلة من الأصفار-/ 1640804 # 1640804 "> AndreyT يدل .
ولقد كانت فترة من الوقت منذ أن كنت قد فعلت وC / C ++، ولكن يبدو لي أن (أكثر من اللازم) الحل بسيط سيكون للتحقق مجرد سلسلة ل "0".
int value = atoi(string_number.c_str());
if ( !value && string_number != "0" ) {
// error
} else {
// great success!
}