จะตรวจสอบได้อย่างไรว่าสตริงเป็นตัวเลขที่มี C ++ หรือไม่?


136

ฉันมีปัญหาเล็กน้อยในการพยายามเขียนฟังก์ชันที่ตรวจสอบว่าสตริงเป็นตัวเลขหรือไม่ สำหรับเกมที่ฉันกำลังเขียนฉันเพียงแค่ต้องตรวจสอบว่าบรรทัดจากไฟล์ที่ฉันกำลังอ่านเป็นตัวเลขหรือไม่ (ฉันจะรู้ว่ามันเป็นพารามิเตอร์ด้วยวิธีนี้หรือไม่) ฉันเขียนฟังก์ชันด้านล่างซึ่งฉันเชื่อว่าทำงานได้อย่างราบรื่น (หรือฉันแก้ไขโดยไม่ตั้งใจเพื่อหยุดมันหรือฉันเป็นโรคจิตเภทหรือ Windows เป็นโรคจิตเภท):

bool isParam (string line)
{
    if (isdigit(atoi(line.c_str())))
        return true;

    return false;
}

184
ฉันเกลียดการเห็นif (expr) return true; return false;! return expr;เขียนเพียง
ephemient

17
@ephemient สไตล์ของฉันคือทำแบบเดียวกับคุณ แต่มันเป็นเรื่องใหญ่จริงหรือ?
Brennan Vincent

2
ต้นแบบฟังก์ชันของคุณดูเหมือนไม่เหมาะสม ทำไมไม่ใช้ bool isParam (const string & line)
MikimotoH

4
ใช่. ฉันมีนิสัยไม่ดีในการเขียนโค้ดแบบยาวเมื่อเรียนภาษาใหม่ ฉันเพิ่งเริ่มใช้ C ++ และลังเลที่จะใช้ "ทางลัด" (หรือทางลัด)
Brendan Weinstein

57
@ เบรนแนนวินเซนต์: ใช่มันเป็นเรื่องใหญ่ มันเป็นระดับเดียวกันของความผิดพลาดif (expr) return expr; else return expr;, if (expr == true), หรือ(if expr != false) if ((expr == true) == true)ทั้งหมดนี้นำเสนอความซับซ้อนที่ไม่เป็นประโยชน์ต่อผู้เขียนผู้อ่านหรือผู้รวบรวมโค้ด การขจัดความซับซ้อนที่ไม่จำเป็นไม่ใช่ทางลัด สิ่งสำคัญคือการเขียนซอฟต์แวร์ที่ดีขึ้น
MSalters

คำตอบ:


148

วิธีที่มีประสิทธิภาพมากที่สุดคือการวนซ้ำบนสตริงจนกว่าคุณจะพบอักขระที่ไม่ใช่ตัวเลข หากมีอักขระที่ไม่ใช่ตัวเลขคุณสามารถพิจารณาว่าสตริงไม่ใช่ตัวเลข

bool is_number(const std::string& s)
{
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();
}

หรือถ้าคุณต้องการทำ C ++ 11 วิธี:

bool is_number(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(), 
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

ดังที่ระบุไว้ในความคิดเห็นด้านล่างนี้ใช้ได้กับจำนวนเต็มบวกเท่านั้น หากคุณต้องการตรวจหาจำนวนเต็มลบหรือเศษส่วนคุณควรใช้โซลูชันที่ใช้ไลบรารีที่มีประสิทธิภาพมากขึ้น แม้ว่าการเพิ่มการสนับสนุนสำหรับจำนวนเต็มลบจะเป็นเรื่องเล็กน้อย


6
ยังไม่จัดการกับจำนวนลบและจำนวนที่ไม่ใช่จำนวนเต็ม เราไม่สามารถทราบได้ว่าข้อกำหนดตามคำถามคืออะไร
Brennan Vincent

76
คุณยังสามารถใช้!s.empty() && s.find_first_not_of("0123456789") == std::string::npos;สำหรับ C ++ 03 one-liner
KBjorklu

8
ยังไม่จัดการตัวเลขทศนิยมเช่น 1.23
littlecodefarmer758

3
@Remy Lebeau ใช่แล้ว มันไม่ได้แปลงสตริงเป็นintไฟล์. เป็นเพียงการระบุว่าสตริงประกอบด้วยตัวเลขหรือไม่ ไม่สำคัญว่าสตริงจะยาวแค่ไหน
Charles Salvia

5
อย่าลืมใส่<string> <algorithm>และ<cctype>เพื่อให้ C ++ 11 ตัวอย่างใช้งานได้
kR105

88

ทำไมต้องคิดค้นล้อใหม่? ไลบรารีมาตรฐาน C (มีอยู่ใน C ++ เช่นกัน) มีฟังก์ชันที่ทำสิ่งนี้:

char* p;
long converted = strtol(s, &p, 10);
if (*p) {
    // conversion failed because the input wasn't a number
}
else {
    // use converted
}

หากคุณต้องการจัดการเศษส่วนหรือสัญกรณ์ทางวิทยาศาสตร์ให้ใช้strtodแทน (คุณจะได้doubleผลลัพธ์)

หากคุณต้องการอนุญาตค่าคงที่ฐานสิบหกและฐานแปดในรูปแบบ C / C ++ ( "0xABC") ให้สร้างพารามิเตอร์สุดท้าย0แทน

จากนั้นฟังก์ชันของคุณสามารถเขียนเป็น

bool isParam(string line)
{
    char* p;
    strtol(line.c_str(), &p, 10);
    return *p == 0;
}

4
ฟังก์ชันนี้จะละทิ้งช่องว่างด้านหน้า ดังนั้นคุณต้องตรวจสอบถ่านแรกสำหรับ isdigit
chmike

1
@chmike: จากความเข้าใจของฉันเกี่ยวกับคำถามการละทิ้งช่องว่างชั้นนำเป็นพฤติกรรมที่ถูกต้อง ( atoiตามที่ใช้ในคำถามก็เช่นกัน)
Ben Voigt

1
คำถามไม่ได้ระบุอย่างชัดเจน แต่ความเข้าใจของฉันเกี่ยวกับข้อกำหนด "ตรวจสอบว่าสตริงเป็นตัวเลขหรือไม่" หมายความว่าสตริงทั้งหมดเป็นตัวเลขจึงไม่มีช่องว่าง ฉันรู้สึกว่าจำเป็นต้องชี้ให้เห็นว่าคำตอบของคุณแตกต่างกับคนอื่น ๆ ในเรื่องนี้ คำตอบของคุณอาจจะใช้ได้ถ้ามันโอเคให้สตริงมีช่องว่างข้างหน้าตัวเลข
chmike

1
@BenVoigt คุณกำลังบอกว่าpจะตั้งค่าเป็นnullptrถ้าstrtolสำเร็จใช่ไหม? นั่นไม่ใช่สิ่งที่ฉันเห็น :(
Jonathan Mee

2
@JonathanMee: ไม่pจะชี้ไปที่ NUL ที่ยุติสตริง ดังนั้นp != 0และ*p == 0.
Ben Voigt

33

ด้วยคอมไพเลอร์ C ++ 11 สำหรับจำนวนเต็มที่ไม่เป็นลบฉันจะใช้สิ่งนี้ (สังเกต::แทนstd::):

bool is_number(const std::string &s) {
  return !s.empty() && std::all_of(s.begin(), s.end(), ::isdigit);
}

http://ideone.com/OjVJWh


1
นี่คือคำตอบที่ดีที่สุด
Martin Broadhurst

หากมีอักขระ utf8 ในสตริงคุณจะได้รับข้อผิดพลาดรันไทม์
Lion King

29

คุณสามารถทำได้ด้วยวิธี C ++ ด้วย boost :: lexical_cast หากคุณยืนยันที่จะไม่ใช้บูสต์จริงๆคุณสามารถตรวจสอบว่ามันทำอะไรและทำเช่นนั้นได้ มันค่อนข้างง่าย

try 
{
  double x = boost::lexical_cast<double>(str); // double could be anything with >> operator.
}
catch(...) { oops, not a number }

21
ใช้try{} catch{}ความคิดที่ดี? เราไม่ควรหลีกเลี่ยงให้มากที่สุด?
Nawaz

32
-1 สำหรับการละเมิดลองจับ ... blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
NoSenseEtAl

14
ลองใช้ {} catch {} ที่นี่ อย่างไรก็ตามการจับ (... ) เป็นเพียงการปฏิบัติที่ไม่ดี ในกรณีนี้ให้ใช้ boost :: bad_lexical_cast สำหรับตัวจัดการข้อยกเว้นของคุณ
NuSkooler

5
ฉันรู้สึกว่านี่เป็นการพยายามอ่านจากไฟล์ ไม่ว่าคุณจะตรวจสอบไฟล์มากแค่ไหนคุณจะไม่ทราบว่าสามารถอ่านได้จนกว่าคุณจะดำเนินการดังกล่าว มันจะได้ผลหรือไม่ ซึ่งในกรณีนี้คุณจะต้องมีข้อยกเว้น ดังนั้นในกรณีนี้ฉันคิดว่านี่เป็นวิธีที่ดีอย่างสมบูรณ์
Casey

4
@EarlGray - แน่นอนว่าฉันสนใจที่จะได้ยินว่าหน้าต่างปฏิบัติการที่ขึ้นอยู่กับระบบปฏิบัติการจะใช้ มาตรฐานค่อนข้างชัดเจนเกี่ยวกับการทำงานของรหัสนี้
Edward Strange

16

ฉันแค่อยากจะโยนความคิดนี้ที่ใช้การวนซ้ำ แต่โค้ดอื่น ๆ ก็ทำซ้ำ:

#include <string.h>

bool is_number(const std::string& s)
{
    return( strspn( s.c_str(), "-.0123456789" ) == s.size() );
}

มันไม่แข็งแรงอย่างที่ควรจะเป็นเมื่อตรวจสอบจุดทศนิยมหรือเครื่องหมายลบเนื่องจากอนุญาตให้มีมากกว่าหนึ่งในแต่ละตำแหน่งและในตำแหน่งใดก็ได้ ข้อดีก็คือรหัสเป็นบรรทัดเดียวและไม่ต้องใช้ไลบรารีของบุคคลที่สาม

เอา "." ออก และ '-' ถ้าจำนวนเต็มบวกเป็นจำนวนเต็มทั้งหมดที่อนุญาต


ข้อผิดพลาด: ไม่ได้ประกาศ "strspn" ในขอบเขตนี้ฉันคิดว่านี่เป็นเพราะฉันไม่มี "#include" แต่สิ่งที่หนึ่ง
Qwertie

4
หากคุณจะใช้std::stringให้ใช้find_first_not_ofฟังก์ชันสมาชิก
Ben Voigt

5
สิ่งนี้จะล้มเหลวหากคุณส่งสตริง "12.3-4.55-" ซึ่งเห็นได้ชัดว่าไม่ใช่ตัวเลขที่ถูกต้อง
Buzzrick

Buzzrick คำตอบที่เสนอแล้วระบุว่าสิ่งนี้จะล้มเหลวกับหมายเลขที่คุณไม่ได้กล่าวถึง
David Rector

หากคุณ จำกัด ไว้ที่ "0123456789" เท่านั้นสูตรนี้เหมาะอย่างยิ่งที่จะทดสอบจำนวนเต็มที่ไม่ได้ลงชื่อ
ไม่มีใครพิเศษ

16

ฉันขอแนะนำวิธี regex regex-match เต็มรูปแบบ (ตัวอย่างเช่นการใช้boost :: regex ) กับ

-?[0-9]+([\.][0-9]+)?

จะแสดงว่าสตริงเป็นตัวเลขหรือไม่ ซึ่งรวมถึงจำนวนบวกและลบจำนวนเต็มและทศนิยม

รูปแบบอื่น ๆ :

[0-9]+([\.][0-9]+)?

(บวกเท่านั้น)

-?[0-9]+

(จำนวนเต็มเท่านั้น)

[0-9]+

(เฉพาะจำนวนเต็มบวก)


อะแฮ่มฉันลองใช้std::regexกับ gcc 4.7, gcc 4.8 - ทั้งคู่โยนstd::regex_errorเครื่องหมายใด ๆ[ใน regexp แม้กระทั่ง "[abc]" ที่ไร้เดียงสา (ฉันทำผิดหรือเปล่า) clang-3.4 ไม่ทราบ<regex>เลย อย่างไรก็ตามนี่น่าจะเป็นคำตอบที่ดีที่สุด +1
Dmytro Sirenko

3
@EarlGray: Regex พร้อมใช้งานอย่างถูกต้องจาก GCC 4.9 เท่านั้น
Lightness Races ในวงโคจร

13

นี่เป็นอีกวิธีหนึ่งในการใช้<regex>ไลบรารี:

bool is_integer(const std::string & s){
    return std::regex_match(s, std::regex("[(-|+)|][0-9]+"));
}

อาจะเป็นเช่นนั้น ฉันได้อัปเดตวิธีแก้ปัญหาที่ดีกว่าแล้ว ขอบคุณ
mpataki14

ไม่ควรเป็น "[(- | +) |] [0-9] +" (บวกแทนดาว) มิฉะนั้น regex ของคุณอาจจับคู่กับ "-" หรือ "+" เป็นตัวเลขที่ถูกต้อง
David Mulder

ดี ฉันไม่แน่ใจว่า (, | และ) กำลังทำอะไรในคลาสอักขระตัวแรกนั้น - อักขระเหล่านั้นสูญเสียความหมายพิเศษภายในคลาสอักขระเท่าที่ฉันทราบ แล้ว "^ [- +] ล่ะ [0-9] + $" ล่ะ?
U007D

มันอาจจะไม่มีประสิทธิภาพ ทุกครั้งที่เรียกสิ่งนี้จะเรียก std :: regex constructor ซึ่งรวบรวม regex
user31264

12

ด้วยวิธีนี้คุณสามารถตรวจสอบทุกอย่างตั้งแต่จำนวนลบไปจนถึงจำนวนบวกและแม้แต่ตัวเลขลอย เมื่อคุณเปลี่ยนประเภทของnumเป็นจำนวนเต็มคุณจะได้รับข้อผิดพลาดหากสตริงมีจุด

#include<iostream>
#include<sstream>
using namespace std;


int main()
{
      string s;

      cin >> s;

      stringstream ss;
      ss << s;

      float num = 0;

      ss >> num;

      if(ss.good()) {
          cerr << "No Valid Number" << endl;
      }
      else if(num == 0 && s[0] != '0') {
          cerr << "No Valid Number" << endl;
      }
      else {
          cout << num<< endl;
      }             
}

พิสูจน์: โปรแกรม C ++


10

ฉันพบว่ารหัสต่อไปนี้มีประสิทธิภาพมากที่สุด (c ++ 11) มันจับทั้งจำนวนเต็มและลอย

#include <regex>
bool isNumber( std::string token )
{
    return std::regex_match( token, std::regex( ( "((\\+|-)?[[:digit:]]+)(\\.(([[:digit:]]+)?))?" ) ) );
}

ดูเหมือนว่าเส้นusing namespace std;จะไม่จำเป็น
Xam

5

นี่คือวิธีการตรวจสอบจำนวนเต็มบวก:

bool isPositiveInteger(const std::string& s)
{
    return !s.empty() && 
           (std::count_if(s.begin(), s.end(), std::isdigit) == s.size());
}


4

เบรนแดนนี้

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

เกือบจะโอเค

สมมติว่าสตริงใด ๆ ที่ขึ้นต้นด้วย 0 เป็นตัวเลขเพียงแค่เพิ่มการตรวจสอบสำหรับกรณีนี้

bool isNumber(const string &line) 
{
 if (line[0] == '0') return true;
 return (atoi(line.c_str()));
}

ofc "123hello" จะกลับมาเป็นจริงเหมือนที่ Tony D กล่าวไว้


3

ง่ายที่สุดที่ฉันคิดได้ใน c ++

bool isNumber(string s) {
    if(s.size()==0) return false;
    for(int i=0;i<s.size();i++) {
        if((s[i]>='0' && s[i]<='9')==false) {
            return false;
        }
    }
    return true;
}

ตัวอย่างโค้ดการทำงาน: https://ideone.com/nRX51Y


3

ทางออกของฉันโดยใช้ C ++ 11 regex ( #include <regex>) ก็สามารถนำมาใช้สำหรับการตรวจสอบได้อย่างแม่นยำมากขึ้นเช่นunsigned int, doubleฯลฯ :

static const std::regex INT_TYPE("[+-]?[0-9]+");
static const std::regex UNSIGNED_INT_TYPE("[+]?[0-9]+");
static const std::regex DOUBLE_TYPE("[+-]?[0-9]+[.]?[0-9]+");
static const std::regex UNSIGNED_DOUBLE_TYPE("[+]?[0-9]+[.]?[0-9]+");

bool isIntegerType(const std::string& str_)
{
  return std::regex_match(str_, INT_TYPE);
}

bool isUnsignedIntegerType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_INT_TYPE);
}

bool isDoubleType(const std::string& str_)
{
  return std::regex_match(str_, DOUBLE_TYPE);
}

bool isUnsignedDoubleType(const std::string& str_)
{
  return std::regex_match(str_, UNSIGNED_DOUBLE_TYPE);
}

คุณสามารถค้นหารหัสนี้ได้ที่http://ideone.com/lyDtfiซึ่งสามารถแก้ไขได้อย่างง่ายดายเพื่อให้เป็นไปตามข้อกำหนด


ฉันขอให้ผู้ลงคะแนนช่วยฉันเข้าใจปัญหาฉันจะปรับปรุงคำตอบของฉัน ขอบคุณ
aniliitb10

2

วิธีแก้ปัญหาตามความคิดเห็นของ kbjorkluคือ:

bool isNumber(const std::string& s)
{
   return !s.empty() && s.find_first_not_of("-.0123456789") == std::string::npos;
}

เช่นเดียวกับคำตอบของ David Rectorมันไม่แข็งแรงสำหรับสตริงที่มีจุดหรือเครื่องหมายลบหลายจุด แต่คุณสามารถลบอักขระเหล่านั้นออกเพื่อตรวจหาจำนวนเต็ม


อย่างไรก็ตามฉันเป็นส่วนหนึ่งของโซลูชันโดยใช้วิธีแก้ปัญหาของ Ben Voigtโดยใช้strtodใน cstdlib เพื่อดูค่าทศนิยมสัญกรณ์ทางวิทยาศาสตร์ / วิศวกรรมสัญกรณ์ฐานสิบหก (C ++ 11) หรือแม้แต่ INF / INFINITY / NAN (C ++ 11) คือ:

bool isNumberC(const std::string& s)
{
    char* p;
    strtod(s.c_str(), &p);
    return *p == 0;
}



1

หลังจากดูเอกสารอีกเล็กน้อยฉันก็ได้คำตอบที่รองรับความต้องการของฉัน แต่อาจจะไม่เป็นประโยชน์สำหรับคนอื่น นี่คือ (โดยไม่มีผลตอบแทนจริงที่น่ารำคาญและส่งคืนข้อความเท็จ :-))

bool isNumber(string line) 
{
    return (atoi(line.c_str())); 
}

4
หากตัวเลขเกิดขึ้น0คุณจะได้ลบเท็จ
Charles Salvia

3
สิ่งนี้จะส่งคืนหมายเลขนำหน้าและไม่เตือนคุณถึงขยะต่อท้าย (เช่น "123hello" ==> 123) @ ชาร์ลส์: เบรนแดนกล่าวว่าเขาเพียงแค่ต้องรับรู้ ints เชิงบวกในความคิดเห็นเกี่ยวกับคำตอบอื่น
Tony Delroy

1

ฉันคิดว่านิพจน์ทั่วไปนี้ควรจัดการได้เกือบทุกกรณี

"^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"

เพื่อให้คุณสามารถลองใช้ฟังก์ชันต่อไปนี้ที่สามารถใช้งานได้กับทั้ง (Unicode และ ANSI)

bool IsNumber(CString Cs){
Cs.Trim();

#ifdef _UNICODE
std::wstring sr = (LPCWSTR)Cs.GetBuffer(Cs.GetLength());
return std::regex_match(sr, std::wregex(_T("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?")));

#else
    std::string s = (LPCSTR)Cs.GetBuffer();
return std::regex_match(s, std::regex("^(\\-|\\+)?[0-9]*(\\.[0-9]+)?"));
#endif
}

1
include <string>

สำหรับการตรวจสอบคู่ผสม:

bool validateDouble(const std::string & input) {
int decimals = std::count(input.begin(), input.end(), '.'); // The number of decimals in the string
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == decimals + negativeSigns) // Consists of only decimals and negatives or is empty
    return false;
else if (1 < decimals || 1 < negativeSigns) // More than 1 decimal or negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-.0123456789") != input.size()) // The string contains a character that isn't in "-.0123456789"
    return false;
return true;

}

สำหรับการตรวจสอบ Ints (ด้วย Negatives)

bool validateInt(const std::string & input) {
int negativeSigns = std::count(input.begin(), input.end(), '-'); // The number of negative signs in the string

if (input.size() == negativeSigns) // Consists of only negatives or is empty
    return false;
else if (1 < negativeSigns) // More than 1 negative sign
    return false;
else if (1 == negativeSigns && input[0] != '-') // The negative sign (if there is one) is not the first character
    return false;
else if (strspn(input.c_str(), "-0123456789") != input.size()) // The string contains a character that isn't in "-0123456789"
    return false;
return true;

}

สำหรับการตรวจสอบ Ints ที่ไม่ได้ลงนาม

bool validateUnsignedInt(const std::string & input) {
return (input.size() != 0 && strspn(input.c_str(), "0123456789") == input.size()); // The string is not empty and contains characters only in "0123456789"

}


1
bool isNumeric(string s){
    if ( !s.empty() && s[0] != '-' )
        s = "0" + s; //prepend 0

    string garbage;

    stringstream ss(s); 
    ss >> *(auto_ptr<double>(new double)) >> garbage;
/*
//the line above extracts the number into an anonymous variable. it could also be done like this:
double x;
ss >> x >> garbage;
*/
    //if there is no garbage return true or else return false
    return garbage.empty(); 
}

มันทำงานอย่างไร: stringstream >> overload สามารถแปลงสตริงเป็นประเภทเลขคณิตต่างๆได้โดยการอ่านอักขระตามลำดับจาก stringstream (ss ในกรณีนี้) จนกว่าอักขระจะหมดหรืออักขระถัดไปไม่ตรงตามเกณฑ์ที่จะจัดเก็บ ลงในประเภทตัวแปรปลายทาง

example1:

stringstream ss("11");
double my_number;
ss >> my_number; //my number = 11

example2:

stringstream ss("011");
double my_number;
ss >> my_number; //my number = 11

ตัวอย่างที่ 3:

stringstream ss("11ABCD");
double my_number;
ss >> my_number; //my number = 11 (even though there are letters after the 11)

คำอธิบายตัวแปร "ขยะ":

ทำไมไม่ลองตรวจสอบดูว่าการสกัดเป็นสองเท่าของฉันมีค่าที่ถูกต้องหรือไม่แล้วส่งคืนจริงถ้าเป็นเช่นนั้น

สังเกตว่า example3 ด้านบนจะยังคงอ่านหมายเลข 11 ในตัวแปร my_number ได้สำเร็จแม้ว่าสตริงอินพุตจะเป็น "11ABCD" (ซึ่งไม่ใช่ตัวเลข)

ในการจัดการกรณีนี้เราสามารถทำการแยกอีกครั้งในตัวแปรสตริง (ซึ่งฉันตั้งชื่อขยะ) ซึ่งสามารถอ่านสิ่งที่อาจเหลืออยู่ในบัฟเฟอร์สตริงหลังจากการแยกครั้งแรกในตัวแปรประเภท double หากมีสิ่งใดหลงเหลืออยู่จะถูกอ่านว่าเป็น "ขยะ" ซึ่งหมายความว่าสตริงเต็มที่ส่งเข้ามาไม่ใช่ตัวเลข (เพิ่งเริ่มต้นด้วยหนึ่ง) ในกรณีนี้เราต้องการคืนค่าเท็จ

คำอธิบาย "0" ที่นำหน้า:

การพยายามแยกอักขระเดี่ยวเป็นคู่จะล้มเหลว (คืนค่า 0 เป็นคู่ของเรา) แต่จะยังคงย้ายตำแหน่งบัฟเฟอร์สตริงไปที่หลังอักขระ ในกรณีนี้การอ่านขยะของเราจะว่างเปล่าซึ่งจะทำให้ฟังก์ชันคืนค่าจริงไม่ถูกต้อง ในการหลีกเลี่ยงสิ่งนี้ฉันใส่เครื่องหมาย 0 ไว้ข้างหน้าสตริงดังนั้นถ้าตัวอย่างเช่นสตริงที่ส่งผ่านคือ "a" มันจะเปลี่ยนเป็น "0a" เพื่อให้ 0 ถูกแยกออกเป็นคู่และ "a" จะถูกแยกออกเป็นขยะ

การเติม 0 จะไม่ส่งผลต่อค่าของตัวเลขดังนั้นตัวเลขจะยังคงถูกแยกออกเป็นตัวแปรคู่ของเราอย่างถูกต้อง


1
แม้ว่ารหัสนี้อาจตอบคำถาม แต่การให้บริบทเพิ่มเติมเกี่ยวกับสาเหตุและ / หรือวิธีที่รหัสนี้ตอบคำถามช่วยเพิ่มมูลค่าในระยะยาว
Ajean

1

เพื่อตรวจสอบว่าสตริงเป็นจำนวนเต็มหรือทศนิยมหรือดังนั้นคุณสามารถใช้:

 #include <sstream>

    bool isNumber(string str) {
    double d;
    istringstream is(str);
    is >> d;
    return !is.fail() && is.eof();
}

1
สิ่งนี้จะส่งคืน 10 สำหรับสตริงที่มีค่า "10_is_not_a_number"
KorreyD

1

อีกคำตอบหนึ่งที่ใช้stold(แม้ว่าคุณจะใช้stof/ stodหากคุณไม่ต้องการความแม่นยำ)

bool isNumeric(const std::string& string)
{
    std::size_t pos;
    long double value = 0.0;

    try
    {
        value = std::stold(string, &pos);
    }
    catch(std::invalid_argument&)
    {
        return false;
    }
    catch(std::out_of_range&)
    {
        return false;
    }

    return pos == string.size() && !std::isnan(value);
}


1

ลองสิ่งนี้:

bool checkDigit(string str)
{  
   int n=str.length();

   for(int i=0;    i   < n ;   i++)
   {
     if(str[i]<'0' || str[i]>'9')
       return false;
   }

   return true;
}

1

คุณอาจจะทดสอบว่าสตริงเป็นแปลงสภาพให้เป็นจำนวนเต็มโดยใช้เพิ่ม :: lexical_cast ถ้ามันพ่นbad_lexical_castข้อยกเว้นไม่สามารถแปลงสตริงได้มิฉะนั้นจะทำได้

ดูตัวอย่างโปรแกรมทดสอบดังกล่าวด้านล่าง:

#include <boost/lexical_cast.hpp>
#include <iostream>

int main(int, char** argv)
{
        try
        {
                int x = boost::lexical_cast<int>(argv[1]);
                std::cout << x << " YES\n";
        }
        catch (boost::bad_lexical_cast const &)
        {
                std:: cout << "NO\n";
        }
        return 0;
}

การดำเนินการตัวอย่าง:

# ./a.out 12
12 YES
# ./a.out 12/3
NO

0

ไม่กี่เดือนที่ผ่านมาฉันใช้วิธีตรวจสอบว่าสตริงใดเป็นจำนวนเต็มเลขฐานสิบหกหรือสองเท่า

enum{
        STRING_IS_INVALID_NUMBER=0,
        STRING_IS_HEXA,
        STRING_IS_INT,
        STRING_IS_DOUBLE
};

bool isDigit(char c){
    return (('0' <= c) && (c<='9'));
}

bool isHexaDigit(char c){
    return ((('0' <= c) && (c<='9')) || ((tolower(c)<='a')&&(tolower(c)<='f')));
}


char *ADVANCE_DIGITS(char *aux_p){

    while(CString::isDigit(*aux_p)) aux_p++;
    return aux_p;
}

char *ADVANCE_HEXADIGITS(char *aux_p){

    while(CString::isHexaDigit(*aux_p)) aux_p++;
    return aux_p;
}


int isNumber(const string & test_str_number){
    bool isHexa=false;
    char *str = (char *)test_str_number.c_str();

    switch(*str){
    case '-': str++; // is negative number ...
               break;
    case '0': 
              if(tolower(*str+1)=='x')  {
                  isHexa = true;
                  str+=2;
              }
              break;
    default:
            break;
    };

    char *start_str = str; // saves start position...
    if(isHexa) { // candidate to hexa ...
        str = ADVANCE_HEXADIGITS(str);
        if(str == start_str)
            return STRING_IS_INVALID_NUMBER;

        if(*str == ' ' || *str == 0) 
            return STRING_IS_HEXA;

    }else{ // test if integer or float
        str = ADVANCE_DIGITS(str);
        if(*str=='.') { // is candidate to double
            str++;
            str = ADVANCE_DIGITS(str);
            if(*str == ' ' || *str == 0)
                return STRING_IS_DOUBLE;

            return STRING_IS_INVALID_NUMBER;
        }

        if(*str == ' ' || *str == 0)
            return STRING_IS_INT;

    }

    return STRING_IS_INVALID_NUMBER;


}

จากนั้นในโปรแกรมของคุณคุณสามารถแปลงตัวเลขในฟังก์ชันประเภทได้อย่างง่ายดายหากคุณทำสิ่งต่อไปนี้

string val; // the string to check if number...

switch(isNumber(val)){
   case STRING_IS_HEXA: 
   // use strtol(val.c_str(), NULL, 16); to convert it into conventional hexadecimal
   break;
   case STRING_IS_INT: 
   // use (int)strtol(val.c_str(), NULL, 10); to convert it into conventional integer
   break;
   case STRING_IS_DOUBLE:
   // use atof(val.c_str()); to convert it into conventional float/double
   break;
}

คุณสามารถทราบได้ว่าฟังก์ชันจะคืนค่าเป็น 0 หากตรวจไม่พบตัวเลข 0 สามารถถือว่าเป็นเท็จ (เช่นบูลีน)


0

ฉันเสนอหลักการง่ายๆ:

หากการแปลงเป็น ASCII เป็น> 0 หรือเริ่มต้นด้วย 0 แสดงว่าเป็นตัวเลข มันไม่สมบูรณ์แบบ แต่รวดเร็ว

สิ่งนี้:

string token0;

if (atoi(token0.c_str())>0 || isdigit(token0.c_str()[0]) ) { //this is a value
    // do what you need to do...
}

0

ฟังก์ชั่นนี้ดูแลทุกกรณีที่เป็นไปได้:

bool AppUtilities::checkStringIsNumber(std::string s){
    //Eliminate obvious irritants that could spoil the party
    //Handle special cases here, e.g. return true for "+", "-", "" if they are acceptable as numbers to you
    if (s == "" || s == "." || s == "+" || s == "-" || s == "+." || s == "-.") return false;

    //Remove leading / trailing spaces **IF** they are acceptable to you
    while (s.size() > 0 && s[0] == ' ') s = s.substr(1, s.size() - 1);
    while (s.size() > 0 && s[s.size() - 1] == ' ') s = s.substr(0, s.size() - 1);


    //Remove any leading + or - sign
    if (s[0] == '+' || s[0] == '-')
        s = s.substr(1, s.size() - 1);

    //Remove decimal points
    long prevLength = s.size();

    size_t start_pos = 0;
    while((start_pos = s.find(".", start_pos)) != std::string::npos) 
        s.replace(start_pos, 1, "");

    //If the string had more than 2 decimal points, return false.
    if (prevLength > s.size() + 1) return false;

    //Check that you are left with numbers only!!
    //Courtesy selected answer by Charles Salvia above
    std::string::const_iterator it = s.begin();
    while (it != s.end() && std::isdigit(*it)) ++it;
    return !s.empty() && it == s.end();

    //Tada....
}

0

คุณสามารถใช้รหัสส่งคืนของ sscanf เพื่อตรวจสอบว่าเป็น int หรือไม่?

bool is_number(const std::string& s)
{
    int value;
    int result = sscanf(valueStr.c_str(), "%d", &value);
    return (result != EOF && readResult != 0);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.