Làm cách nào để kiểm tra xem chuỗi C ++ std :: có bắt đầu bằng một chuỗi nhất định không và chuyển đổi một chuỗi con thành int?


241

Làm cách nào để triển khai các mã sau (mã giả Python) trong C ++?

if argv[1].startswith('--foo='):
    foo_value = int(argv[1][len('--foo='):])

(Ví dụ: nếu argv[1]--foo=98, thì foo_value98.)

Cập nhật: Tôi ngần ngại tìm hiểu về Boost, vì tôi chỉ xem xét thực hiện một thay đổi rất nhỏ đối với một công cụ dòng lệnh nhỏ đơn giản (tôi không phải học cách liên kết và sử dụng Boost cho trẻ vị thành niên thay đổi).


Điều này cũng thú vị.
manlio

Câu trả lời:


446

Sử dụng quá tải trong rfindđó có postham số:

std::string s = "tititoto";
if (s.rfind("titi", 0) == 0) {
  // s starts with prefix
}

Ai cần gì nữa? STL thuần túy!

Nhiều người đã đọc sai điều này có nghĩa là "tìm kiếm ngược qua toàn bộ chuỗi tìm kiếm tiền tố". Điều đó sẽ cho kết quả sai (ví dụ string("tititito").rfind("titi")trả về 2 vì vậy khi so sánh == 0sẽ trả về sai) và nó sẽ không hiệu quả (nhìn qua toàn bộ chuỗi thay vì chỉ bắt đầu). Nhưng nó không làm điều đó bởi vì nó vượt qua postham số là 0, điều này giới hạn tìm kiếm chỉ khớp ở vị trí đó hoặc sớm hơn . Ví dụ:

std::string test = "0123123";
size_t match1 = test.rfind("123");    // returns 4 (rightmost match)
size_t match2 = test.rfind("123", 2); // returns 1 (skipped over later match)
size_t match3 = test.rfind("123", 0); // returns std::string::npos (i.e. not found)

32
câu trả lời này nên được bình chọn nhiều nhất chứ không phải là câu trả lời: D tại sao nên sử dụng thư viện khác khi bạn đã mắc STL.
Iuliu Atudosiei

@ sweisgerber.dev, tôi bối rối về sự tranh chấp đầu tiên của bạn. Giá trị trả về từ findsẽ chỉ bằng 0 nếu titiđầu chuỗi. Nếu nó được tìm thấy ở một nơi khác, bạn sẽ nhận được giá trị trả về khác không và nếu không tìm thấy, bạn sẽ nhận được giá trị nposkhác không. Giả sử tôi đúng, tôi thích câu trả lời này vì tôi không phải mang theo bất kỳ thứ gì không chuẩn (vâng, tôi biết Boost ở khắp mọi nơi, tôi chỉ thích các lib C ++ cốt lõi cho những thứ đơn giản như thế này).
paxdiablo

@paxdiablo: bạn đã đúng, nó thực sự kiểm tra xem nó có bắt đầu không titi, nhưng phần chuyển đổi bị thiếu.
sweisgerber.dev

2
Chúng ta có bất cứ bằng chứng nào cho thấy điều này được tối ưu hóa trong hầu hết các trình biên dịch không? Tôi không tìm thấy nơi nào khác đề cập đến tối ưu hóa "tìm" hoặc "rfind" là cách làm phổ biến dựa trên giá trị trả về mà nó đang kiểm tra.
Superziyi

2
@alcoforado "rfind sẽ bắt đầu từ phía sau chuỗi ..." Không, điều đó chỉ áp dụng cho tình trạng quá tải của rfind()điều đó không có postham số. Nếu bạn sử dụng quá tải có postham số thì nó sẽ không tìm kiếm toàn bộ chuỗi, chỉ vị trí đó và trước đó. (Giống như thông thường find()với postham số chỉ nhìn ở vị trí đó hoặc sau đó.) Vì vậy, nếu bạn vượt qua pos == 0, như thể hiện trong câu trả lời này, thì nó sẽ chỉ xem xét cho các trận đấu ở một vị trí đó. Điều đó đã được giải thích trong cả câu trả lời và bình luận.
Arthur Tacca

188

Bạn sẽ làm nó như thế này:

std::string prefix("--foo=");
if (!arg.compare(0, prefix.size(), prefix))
    foo_value = atoi(arg.substr(prefix.size()).c_str());

Tìm kiếm một lib như Boost.ProgramOptions thực hiện điều này cho bạn cũng là một ý tưởng tốt.


7
Vấn đề lớn nhất với điều này là atoi("123xyz")trả về 123, trong khi Python int("123xyz")ném ngoại lệ.
Tom

Cách giải quyết, chúng ta có thể làm, là một sscanf () và so sánh kết quả và bản gốc, để quyết định nên tiến hành hay ném ngoại lệ.
Roopesh Majeti

1
Hoặc chỉ cần thay thế atoibằng strtolhoặc strtoll, cho phép chúng tôi phát hiện các điều kiện lỗi trong giá trị đầu vào.
Tom

1
Đây là giải pháp tốt hơn giải pháp rfindphụ thuộc vào tối ưu hóa để hoạt động.
Calmarius

143

Để hoàn thiện, tôi sẽ đề cập đến cách C để làm điều đó:

Nếu strlà chuỗi ban đầu của bạn, substrlà chuỗi con bạn muốn kiểm tra, thì

strncmp(str, substr, strlen(substr))

sẽ trở lại 0nếu str bắt đầu với substr. Các chức năng strncmpstrlencó trong tệp tiêu đề C<string.h>

(ban đầu được đăng bởi Yaseen Rauf tại đây , đã thêm đánh dấu)

Đối với một so sánh không phân biệt chữ hoa chữ thường, sử dụng strnicmpthay vì strncmp.

Đây là cách C để làm điều đó, đối với các chuỗi C ++, bạn có thể sử dụng chức năng tương tự như sau:

strncmp(str.c_str(), substr.c_str(), substr.size())

9
thật vậy, mọi người dường như chỉ đi "sử dụng boost" và tôi cảm ơn vì một phiên bản thư viện stl hoặc OS
Force Gaia

Đúng. Tuy nhiên, nó giả sử chuỗi không có ký tự null trong đó. Nếu không phải như vậy - người ta nên sử dụngmemcmp()
Avishai Y

Tại sao mọi người sẽ sử dụng bất cứ điều gì khác ngoài giải pháp đẹp đơn giản này?
Adam Zahran

88

Nếu bạn đã sử dụng Boost, bạn có thể làm điều đó với thuật toán chuỗi tăng cường + tăng tốc từ vựng:

#include <boost/algorithm/string/predicate.hpp>
#include <boost/lexical_cast.hpp>

try {    
    if (boost::starts_with(argv[1], "--foo="))
        foo_value = boost::lexical_cast<int>(argv[1]+6);
} catch (boost::bad_lexical_cast) {
    // bad parameter
}

Cách tiếp cận này, giống như nhiều câu trả lời khác được cung cấp ở đây là ổn đối với các tác vụ rất đơn giản, nhưng về lâu dài, bạn thường sử dụng một thư viện phân tích cú pháp dòng lệnh tốt hơn. Boost có một ( Boost.Program_options ), có thể có ý nghĩa nếu bạn tình cờ sử dụng Boost.

Nếu không, việc tìm kiếm "trình phân tích cú pháp dòng lệnh c ++" sẽ mang lại một số tùy chọn.


107
Kéo theo sự phụ thuộc rất lớn để kiểm tra tiền tố chuỗi cũng giống như bắn chim bằng pháo.
Tobi

150
"Sử dụng Boost" luôn là câu trả lời sai khi ai đó hỏi cách thực hiện thao tác chuỗi đơn giản trong C ++.
Glenn Maynard

90
trừ 1 cho đề xuất Boost
uglycoyote

37
Sử dụng boost ở đây là đúng, nếu bạn đã sử dụng boost trong dự án của mình.
Alex Che

17
Câu trả lời có tiền tố là "Nếu bạn đang sử dụng Boost ...". Rõ ràng đây là câu trả lời đúng "... nếu bạn đang sử dụng Boost". Nếu không, hãy xem gợi ý của @Thomas
NuSkooler

82

Mã tôi sử dụng cho mình:

std::string prefix = "-param=";
std::string argument = argv[1];
if(argument.substr(0, prefix.size()) == prefix) {
    std::string argumentValue = argument.substr(prefix.size());
}

2
ngắn gọn nhất và chỉ phụ thuộc vào chuỗi std ::, ngoại trừ loại bỏ đối số tùy chọn và sai lệch.size () ở cuối đế cuối cùng.
Ben Bryant

@ ben-bryant: Cảm ơn vì đã ngẩng cao đầu. Không biết nó là tùy chọn.
Hüseyin Yağlı

16
Sử dụng substrdẫn đến sao chép không cần thiết. Các str.compare(start, count, substr)phương pháp được sử dụng trong Thomas' Câu trả lời là hiệu quả hơn. Câu trả lời của razvanco13 có một phương pháp khác tránh sao chép bằng cách sử dụng std::equal.
Felix Dombek

4
@ HüseyinYağlı Thomas uses atoi which is only for windowsHả? atoiđã là một chức năng thư viện tiêu chuẩn C kể từ ... bao giờ. Trên thực tế, điều atoinày rất tệ - không phải vì nó dành riêng cho Windows - mà bởi vì nó (1) C, không phải C ++ và (2) không được chấp nhận ngay cả trong C (bạn nên sử dụng strtolhoặc một trong các chức năng liên quan khác. Bởi vì atoicó không xử lý lỗi. Nhưng, một lần nữa, đó chỉ là trong C, dù sao).
Parthian Shot

50

Không ai sử dụng thuật toán STL / hàm không khớp . Nếu điều này trả về true, tiền tố là tiền tố của 'toCheck':

std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()

Ví dụ đầy đủ prog:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char** argv) {
    if (argc != 3) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "Will print true if 'prefix' is a prefix of string" << std::endl;
        return -1;
    }
    std::string prefix(argv[1]);
    std::string toCheck(argv[2]);
    if (prefix.length() > toCheck.length()) {
        std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
                  << "'prefix' is longer than 'string'" <<  std::endl;
        return 2;
    }
    if (std::mismatch(prefix.begin(), prefix.end(), toCheck.begin()).first == prefix.end()) {
        std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck << '"' << std::endl;
        return 0;
    } else {
        std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"' << toCheck << '"' << std::endl;
        return 1;
    }
}

Biên tập:

Như @James T. Huggett gợi ý, std :: bằng là phù hợp hơn cho câu hỏi: A có phải là tiền tố của B không? và là mã ngắn hơn một chút:

std::equal(prefix.begin(), prefix.end(), toCheck.begin())

Ví dụ đầy đủ prog:

#include <algorithm>
#include <string>
#include <iostream>

int main(int argc, char **argv) {
  if (argc != 3) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "Will print true if 'prefix' is a prefix of string"
              << std::endl;
    return -1;
  }
  std::string prefix(argv[1]);
  std::string toCheck(argv[2]);
  if (prefix.length() > toCheck.length()) {
    std::cerr << "Usage: " << argv[0] << " prefix string" << std::endl
              << "'prefix' is longer than 'string'" << std::endl;
    return 2;
  }
  if (std::equal(prefix.begin(), prefix.end(), toCheck.begin())) {
    std::cout << '"' << prefix << '"' << " is a prefix of " << '"' << toCheck
              << '"' << std::endl;
    return 0;
  } else {
    std::cout << '"' << prefix << '"' << " is NOT a prefix of " << '"'
              << toCheck << '"' << std::endl;
    return 1;
  }
}

2
Tại sao không sử dụng std :: bằng nhau?
Brice M. Dempsey

Nghe có vẻ tốt với tôi. Nó sẽ là mã ngắn hơn quá. Tôi thất bại, tôi sẽ phải chỉnh sửa câu trả lời ngay bây giờ: p
matiu

2
Việc sử dụng std::equalcho các chuỗi có nhược điểm là nó không phát hiện được kết thúc chuỗi, vì vậy bạn cần kiểm tra thủ công xem tiền tố có ngắn hơn toàn bộ chuỗi không. (Như được thực hiện chính xác trong ví dụ prog, nhưng được bỏ qua trong phần lót ở trên.)
Felix Dombek

Vì vậy, không có lợi ích hơn rfind?
Андрей Вахрушев

26

Cho rằng cả hai chuỗi - argv[1]"--foo"- là các chuỗi C, câu trả lời của @ FelixDombek là giải pháp tốt nhất.

Tuy nhiên, nhìn thấy các câu trả lời khác, tôi nghĩ rằng đáng chú ý rằng, nếu văn bản của bạn đã có sẵn dưới dạng std::string, thì một giải pháp đơn giản, không sao chép, hiệu quả tối đa tồn tại đã được đề cập cho đến nay:

const char * foo = "--foo";
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(strlen(foo));

Và nếu foo đã là một chuỗi:

std::string foo("--foo");
if (text.rfind(foo, 0) == 0)
    foo_value = text.substr(foo.length());

6
rfind(x, 0) == 0nên thực sự được định nghĩa trong tiêu chuẩn nhưstarts_with
porges

1
Không, bởi vì rfind()(thay cho startswith()) rất không hiệu quả - nó tiếp tục tìm kiếm cho đến hết chuỗi.
ankostis

4
@ankostis rfind (x) tìm kiếm từ cuối cho đến khi bắt đầu cho đến khi tìm thấy x, thực sự. Nhưng rfind (x, 0) bắt đầu tìm kiếm từ đầu (vị trí = 0) cho đến khi bắt đầu; vì vậy nó chỉ tìm kiếm ở nơi cần tìm kiếm; không tìm kiếm từ / cho đến cuối.
Kẻ hèn nhát vô danh

18

Với C ++ 17, bạn có thể sử dụng std::basic_string_view& với C ++ 20 std::basic_string::starts_withhoặc std::basic_string_view::starts_with.

Lợi ích của std::string_viewviệc so sánh với std::string- liên quan đến quản lý bộ nhớ - là nó chỉ giữ một con trỏ tới một "chuỗi" (chuỗi các đối tượng giống như char) và biết kích thước của nó. Ví dụ mà không di chuyển / sao chép chuỗi nguồn chỉ để lấy giá trị nguyên:

#include <exception>
#include <iostream>
#include <string>
#include <string_view>

int main()
{
    constexpr auto argument = "--foo=42"; // Emulating command argument.
    constexpr auto prefix = "--foo=";
    auto inputValue = 0;

    constexpr auto argumentView = std::string_view(argument);
    if (argumentView.starts_with(prefix))
    {
        constexpr auto prefixSize = std::string_view(prefix).size();
        try
        {
            // The underlying data of argumentView is nul-terminated, therefore we can use data().
            inputValue = std::stoi(argumentView.substr(prefixSize).data());
        }
        catch (std::exception & e)
        {
            std::cerr << e.what();
        }
    }
    std::cout << inputValue; // 42
}

1
@RolandIllig Không, std::atoihoàn toàn ổn. Nó ném ngoại lệ vào đầu vào xấu (được xử lý trong mã này). Bạn đã có một cái gì khác trong tâm trí?
Roi Danton

Bạn đang nói về atoitừ <cstdlib>? Các tài liệu nói rằng "nó không bao giờ ném ngoại lệ".
Roland Illig

@RolandIllig Tôi đang đề cập đến bình luận đầu tiên của bạn. Có vẻ như, bạn đang nói nhầm atoithay vì std::atoi. Đầu tiên là không an toàn để sử dụng, trong khi sau đó là tốt. Tôi đang sử dụng cái sau trong mã ở đây.
Roi Danton

Vui lòng chứng minh với tôi rằng std::atoithực sự ném một ngoại lệ, bằng cách trích dẫn một tài liệu tham khảo phù hợp. Cho đến khi bạn làm điều đó, tôi không tin bạn vì sẽ rất khó hiểu khi có cả hai ::atoistd::atoihành động theo một cách hoàn toàn khác.
Roland Illig

4
@RolandIllig Cảm ơn bạn đã kiên trì! Bạn nói đúng, đó là một sự giám sát std::atoiđã được sử dụng thay vì std::stoi. Tôi đã sửa nó.
Roi Danton

12
text.substr(0, start.length()) == start

3
@GregorDoroschenko nó trả lời phần "kiểm tra xem chuỗi có bắt đầu bằng phần khác không".
etarion

1
Hiệu quả và thanh lịch bằng cách sử dụng std :: string. Tôi đã học được nhiều nhất từ ​​điều này.
Michael B

1
thêm điểm để trở thành một lớp lót phù hợp để sử dụng vớiif (one-liner)
Adam.at.Epsilon

@Roland Illig Tại sao bạn tin rằng hành vi trong trường hợp đó là không xác định? Biểu thức sẽ trả về false vì chất nền trả về một chuỗi có cùng độ dài với văn bản theo en.cppreference.com/w/cpp/opes/basic_opes/substr
Macsinus

11

Sử dụng STL, điều này có thể trông giống như:

std::string prefix = "--foo=";
std::string arg = argv[1];
if (prefix.size()<=arg.size() && std::equal(prefix.begin(), prefix.end(), arg.begin())) {
  std::istringstream iss(arg.substr(prefix.size()));
  iss >> foo_value;
}

2
Điều đó nên được if (prefix.size()<=arg.size() && std::equal(...)).
Jared Grubb

10

Có nguy cơ bị đốt cháy khi sử dụng các cấu trúc C, tôi nghĩ rằng sscanfví dụ này thanh lịch hơn hầu hết các giải pháp Boost. Và bạn không phải lo lắng về liên kết nếu bạn đang chạy bất cứ nơi nào có trình thông dịch Python!

#include <stdio.h>
#include <string.h>

int main(int argc, char **argv)
{
    for (int i = 1; i != argc; ++i) {
        int number = 0;
        int size = 0;
        sscanf(argv[i], "--foo=%d%n", &number, &size);
        if (size == strlen(argv[i])) {
            printf("number: %d\n", number);
        }
        else {
            printf("not-a-number\n");
        }
    }
    return 0;
}

Dưới đây là một số ví dụ đầu ra chứng minh giải pháp xử lý rác hàng đầu / theo dõi chính xác như mã Python tương đương và chính xác hơn bất kỳ thứ gì đang sử dụng atoi(sẽ bỏ qua một hậu tố không phải là số).

$ ./scan --foo=2 --foo=2d --foo='2 ' ' --foo=2'
number: 2
not-a-number
not-a-number
not-a-number

7
Nếu argv[i]"--foo=9999999999999999999999999", hành vi không được xác định (mặc dù hầu hết hoặc tất cả các triển khai nên hành xử hoàn toàn). Tôi đang giả sử 9999999999999999999999999 > INT_MAX.
Keith Thompson

10

Tôi sử dụng std::string::comparegói trong phương thức tiện ích như dưới đây:

static bool startsWith(const string& s, const string& prefix) {
    return s.size() >= prefix.size() && s.compare(0, prefix.size(), prefix) == 0;
}

5

Tại sao không sử dụng gnu getopts? Đây là một ví dụ cơ bản (không có kiểm tra an toàn):

#include <getopt.h>
#include <stdio.h>

int main(int argc, char** argv)
{
  option long_options[] = {
    {"foo", required_argument, 0, 0},
    {0,0,0,0}
  };

  getopt_long(argc, argv, "f:", long_options, 0);

  printf("%s\n", optarg);
}

Đối với lệnh sau:

$ ./a.out --foo=33

Bạn sẽ nhận được

33

5

Trong trường hợp bạn cần khả năng tương thích C ++ 11 và không thể sử dụng boost, đây là phần bổ trợ tương thích boost với một ví dụ về cách sử dụng:

#include <iostream>
#include <string>

static bool starts_with(const std::string str, const std::string prefix)
{
    return ((prefix.size() <= str.size()) && std::equal(prefix.begin(), prefix.end(), str.begin()));
}

int main(int argc, char* argv[])
{
    bool usage = false;
    unsigned int foos = 0; // default number of foos if no parameter was supplied

    if (argc > 1)
    {
        const std::string fParamPrefix = "-f="; // shorthand for foo
        const std::string fooParamPrefix = "--foo=";

        for (unsigned int i = 1; i < argc; ++i)
        {
            const std::string arg = argv[i];

            try
            {
                if ((arg == "-h") || (arg == "--help"))
                {
                    usage = true;
                } else if (starts_with(arg, fParamPrefix)) {
                    foos = std::stoul(arg.substr(fParamPrefix.size()));
                } else if (starts_with(arg, fooParamPrefix)) {
                    foos = std::stoul(arg.substr(fooParamPrefix.size()));
                }
            } catch (std::exception& e) {
                std::cerr << "Invalid parameter: " << argv[i] << std::endl << std::endl;
                usage = true;
            }
        }
    }

    if (usage)
    {
        std::cerr << "Usage: " << argv[0] << " [OPTION]..." << std::endl;
        std::cerr << "Example program for parameter parsing." << std::endl << std::endl;
        std::cerr << "  -f, --foo=N   use N foos (optional)" << std::endl;
        return 1;
    }

    std::cerr << "number of foos given: " << foos << std::endl;
}

2

Bạn cũng có thể sử dụng strstr:

if (strstr(str, substr) == substr) {
    // 'str' starts with 'substr'
}

nhưng tôi nghĩ nó chỉ tốt cho các chuỗi ngắn vì nó phải lặp qua toàn bộ chuỗi khi chuỗi không thực sự bắt đầu bằng 'chất nền'.


2

Ok tại sao việc sử dụng phức tạp của các thư viện và công cụ? Các đối tượng Chuỗi C ++ làm quá tải toán tử [], vì vậy bạn chỉ có thể so sánh các ký tự .. Giống như những gì tôi vừa làm, vì tôi muốn liệt kê tất cả các tệp trong một thư mục và bỏ qua các tệp vô hình và .. và. giả hành.

while ((ep = readdir(dp)))
{
    string s(ep->d_name);
    if (!(s[0] == '.')) // Omit invisible files and .. or .
        files.push_back(s);
}

Nó đơn giản mà..



2
@robertwb Google+ không còn khả dụng
Static_assert

0
std::string text = "--foo=98";
std::string start = "--foo=";

if (text.find(start) == 0)
{
    int n = stoi(text.substr(start.length()));
    std::cout << n << std::endl;
}

3
Sẽ thật tuyệt, nếu bạn tránh dán mã mà không giải thích mã. Cảm ơn bạn.
Tái sinh

1
Mã không hiệu quả, sẽ tiếp tục tìm kiếm trong quá trình bắt đầu chuỗi.
ankostis

0

Với C ++ 11 trở lên, bạn có thể sử dụng find()find_first_of()

Ví dụ sử dụng find để tìm một char duy nhất:

#include <string>
std::string name = "Aaah";
size_t found_index = name.find('a');
if (found_index != std::string::npos) {
    // Found string containing 'a'
}

Ví dụ sử dụng find để tìm một chuỗi đầy đủ & bắt đầu từ vị trí 5:

std::string name = "Aaah";
size_t found_index = name.find('h', 3);
if (found_index != std::string::npos) {
    // Found string containing 'h'
}

Ví dụ sử dụng find_first_of()char và chỉ char đầu tiên, để chỉ tìm kiếm khi bắt đầu:

std::string name = ".hidden._di.r";
size_t found_index = name.find_first_of('.');
if (found_index == 0) {
    // Found '.' at first position in string
}

Chúc may mắn!


Tại sao không phải là rfind? rfind (str, 0) sẽ không cần quét toàn bộ chuỗi để thực hiện lựa chọn vì nó không thể tiến lên. Xem người khác.
dùng2864740

0

Vì C ++ 11 std::regex_searchcũng có thể được sử dụng để cung cấp các biểu thức khớp phức tạp hơn nữa. Ví dụ sau xử lý các số trôi nổi thorugh std::stofvà một lần đúc tiếp theo int.

Tuy nhiên, parseIntphương pháp hiển thị bên dưới có thể đưa ra một std::invalid_argumentngoại lệ nếu tiền tố không khớp; điều này có thể dễ dàng điều chỉnh tùy thuộc vào ứng dụng đã cho:

#include <iostream>
#include <regex>

int parseInt(const std::string &str, const std::string &prefix) {
  std::smatch match;
  std::regex_search(str, match, std::regex("^" + prefix + "([+-]?(?=\\.?\\d)\\d*(?:\\.\\d*)?(?:[Ee][+-]?\\d+)?)$"));
  return std::stof(match[1]);
}

int main() {
    std::cout << parseInt("foo=13.3", "foo=") << std::endl;
    std::cout << parseInt("foo=-.9", "foo=") << std::endl;
    std::cout << parseInt("foo=+13.3", "foo=") << std::endl;
    std::cout << parseInt("foo=-0.133", "foo=") << std::endl;
    std::cout << parseInt("foo=+00123456", "foo=") << std::endl;
    std::cout << parseInt("foo=-06.12e+3", "foo=") << std::endl;

//    throw std::invalid_argument
//    std::cout << parseInt("foo=1", "bar=") << std::endl;

    return 0;
}

Các loại phép thuật của mô hình regex được chi tiết tốt trong câu trả lời sau đây .

EDIT: câu trả lời trước không thực hiện chuyển đổi thành số nguyên.


0

Bắt đầu với C ++ 20, bạn có thể sử dụng starts_withphương thức này.

std::string s = "abcd";
if (s.starts_with("abc")) {
    ...
}

-3
if(boost::starts_with(string_to_search, string_to_look_for))
    intval = boost::lexical_cast<int>(string_to_search.substr(string_to_look_for.length()));

Điều này là hoàn toàn chưa được kiểm tra. Nguyên tắc giống như Python. Yêu cầu Boost.StringAlgo và Boost.LexicalCast.

Kiểm tra xem chuỗi có bắt đầu bằng chuỗi khác không, sau đó lấy chuỗi con ('lát') của chuỗi đầu tiên và chuyển đổi chuỗi đó bằng cách sử dụng từ vựng.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.