programing

C++ std:: 문자열이 특정 문자열로 시작하는지 확인하고 하위 문자열을 int로 변환하려면 어떻게 해야 합니까?

abcjava 2023. 5. 6. 14:00
반응형

C++ std:: 문자열이 특정 문자열로 시작하는지 확인하고 하위 문자열을 int로 변환하려면 어떻게 해야 합니까?

C++에서 다음 (파이썬 유사 코드)를 어떻게 구현합니까?

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

를 들어, if (예를들어만약, 약만▁()argv[1]이라--foo=98,그리고나서foo_value이라98.)

업데이트: Boost에 대해 알아보려 하지 않습니다. 단순한 명령줄 도구를 아주 조금 변경하려고 하기 때문입니다(작은 변경 사항에 대해 Boost를 연결하고 사용하는 방법을 배울 필요가 없습니다).

검색 위치를 차지하는 오버로드 사용pos매개 변수 및 0을 전달합니다.

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

더 필요한 사람?순수 STL!

많은 사람들이 이것을 "접두사를 찾는 전체 문자열을 뒤로 검색"하는 의미로 잘못 읽었습니다.결과가 그면잘결나예니납다타가과된못러예(:다니).string("tititito").rfind("titi")했을 때 를 반환합니다.== 0false를 반환합니다. 그러면 비효율적입니다(시작만 보는 대신 전체 문자열을 살펴봅니다).하지만 그것은 그것이 통과하기 때문에 그렇게 하지 않습니다.pos를 로의파라터미로 합니다.0검색을 해당 위치 또는 이전 위치에서만 일치하도록 제한합니다.예:

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)

이 작업은 다음과 같이 수행됩니다.

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

Boost와 같은 lib를 찾고 있습니다.이를 수행하는 프로그램 옵션도 좋은 방법입니다.

완성도를 높이기 위해 C 방법을 언급하겠습니다.

한다면str문자열인 의당원끈입다니래신▁your입니다.substr이고, 그 다음에 "는 " " " 입니다.

strncmp(str, substr, strlen(substr))

돌아올 것입니다0한다면str 합니다.substr »strncmp그리고.strlen는 C 파일 C에 .<string.h>

(원래 야신 라우프가 여기에 게시했으며, 마크업 추가됨)

하지 않는 대문자를구않비경우의교는지분,strnicmpstrncmp.

이것이 C 방법입니다. C++ 문자열에 대해 다음과 같은 동일한 기능을 사용할 수 있습니다.

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

Boost를 이미 사용 중인 경우 부스트 문자열 알고리즘 + 부스트 어휘 캐스트를 사용할 수 있습니다.

#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
}

여기에 제공된 다른 많은 답변과 마찬가지로 이러한 종류의 접근 방식은 매우 간단한 작업에는 괜찮지만, 장기적으로 볼 때 일반적으로 명령줄 구문 분석 라이브러리를 사용하는 것이 좋습니다.부스트에는 (부스트)가 있습니다.Program_options)는 이미 Boost를 사용하고 있다면 의미가 있을 수 있습니다.

그렇지 않으면 "c++ 명령줄 파서"를 검색하면 여러 가지 옵션이 생성됩니다.

내가 직접 사용하는 코드:

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

아직 아무도 STL 알고리즘/불일치 기능을 사용하지 않았습니다.true를 반환하는 경우 접두사는 'ToCheck' 접두사입니다.

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

전체 예제 프로그램:

#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;
    }
}

편집:

@James T처럼.Huggett은 다음 질문에 더 적합하다고 제안합니다. std:: equal:A는 B의 접두사이며 코드가 약간 짧습니다.

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

전체 예제 프로그램:

#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;
  }
}

C++17을 사용하면 & with C++20 또는 를 사용할 수 있습니다.

std::string_view와비하여와 std::string메모리 관리와 관련하여 - "문자열"(문자열과 유사한 개체의 연속적인 시퀀스)에 대한 포인터만 가지고 있으며 크기를 알고 있습니다.정수 값을 얻기 위해 소스 문자열을 이동/복사하지 않는 예:

#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
}

- 두 문 열 모 할 때 려 고 를 -을 고려하면,argv[1]그리고."--foo"C 문자열입니다. @FelixDombek의 대답은 실제 최고의 솔루션입니다.

하지만 다른 답변을 보니, 만약 당신의 텍스트가 이미 사용 가능하다면 주목할 가치가 있다고 생각했습니다.std::string이제까지 언급되지 않았던 단순하고 복사 없이 효율적인 솔루션이 존재합니다.

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

foo가 이미 문자열인 경우:

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

부터는 C++20을 할 수 .starts_with방법.

std::string s = "abcd";
if (s.starts_with("abc")) {
    ...
}
text.substr(0, start.length()) == start

STL을 사용하면 다음과 같이 보일 수 있습니다.

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;
}

C 컨스트럭츠를 사용한 것에 대해 비난을 받을 위험을 무릅쓰고, 저는 이것을 생각합니다.sscanf예제는 대부분의 Boost 솔루션보다 더 우아합니다.그리고 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;
}

이 선행하고 다은추적솔동 Python 코드행/처를고리하비다지가음다를 보다 더 하게 처리하는 몇 가지 입니다.atoi접미사가 아닌 접미사를 잘못 무시합니다.

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

사용합니다std::string::compare아래와 같은 유틸리티 방법으로 포장:

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

C++20 업데이트:

  • 사용하다std::string::starts_with

https://en.cppreference.com/w/cpp/string/basic_string/starts_with

std::string str_value = /* smthg */;
const auto starts_with_foo = str_value.starts_with(std::string_view{"foo"});

C++20에는 이제 다음이 있습니다.starts_with 기로가능의 멤버 으로 사용 std::string다음으로 정의됨:

constexpr bool starts_with(string_view sv) const noexcept;

constexpr bool starts_with(CharT c) const noexcept;

constexpr bool starts_with(const CharT* s) const;

따라서 코드는 다음과 같습니다.

std::string s{argv[1]};

if (s.starts_with("--foo="))

C++11 호환성이 필요하고 부스트를 사용할 수 없는 경우 사용 예를 들어 다음과 같은 부스트 호환 드롭인이 있습니다.

#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;
}

왜 gnu getopts를 사용하지 않습니까?다음은 기본적인 예입니다(안전 점검 없음).

#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);
}

다음 명령의 경우:

$ ./a.out --foo=33

얻게 될 것입니다.

33

좋아요, 왜 도서관이나 그런 것들의 복잡한 사용인가요?C++ 문자열 개체는 [] 연산자를 오버로드하므로 문자를 비교하기만 하면 됩니다.방금 한 것처럼 디렉터리에 있는 모든 파일을 나열하고 보이지 않는 파일과 ... 및 . 의사 파일을 무시하고 싶기 때문입니다.

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

그 정도로 간단한..

사용할 수도 있습니다.strstr:

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

하지만 문자열이 실제로 'substr'로 시작하지 않을 때는 전체 문자열을 반복해야 하기 때문에 짧은 문자열에만 적합하다고 생각합니다.

C++11 이상 사용 가능find()그리고.find_first_of()

찾기를 사용한 단일 문자 찾기 예제:

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

찾기를 사용하여 전체 문자열을 찾고 위치 5부터 시작하는 예:

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

사용 예find_first_of()첫 번째 문자만 검색할 수 있습니다.

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

행운을 빕니다.

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;
}

C++11은 더 복잡한 표현을 일치시키는 데도 사용될 수 있기 때문입니다.다음 예제에서는 또한 전체를 통해 부동 숫자를 처리하고 다음으로 캐스트합니다.int.

하만지그, 그▁however.parseInt아래에 표시된 방법은 접두사가 일치하지 않을 경우 예외를 발생시킬 수 있습니다. 이는 주어진 응용 프로그램에 따라 쉽게 조정될 수 있습니다.

#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;
}

정규식 패턴의 마법의 종류는 다음 답변에서 잘 설명되어 있습니다.

편집: 이전 응답이 정수로 변환되지 않았습니다.

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()));

이것은 완전히 검증되지 않았습니다.원리는 파이썬과 동일합니다.부스트가 필요합니다.StringAlgo 및 Boost.어휘 캐스트.

문자열이 다른 문자열로 시작하는지 확인한 다음 첫 번째 문자열의 하위 문자열('슬라이스')을 가져와 어휘 캐스트를 사용하여 변환합니다.

언급URL : https://stackoverflow.com/questions/1878001/how-do-i-check-if-a-c-stdstring-starts-with-a-certain-string-and-convert-a

반응형