IT story

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

hot-time 2020. 4. 30. 07:33
반응형

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


C ++에서 다음 (Python 의사 코드)을 어떻게 구현합니까?

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

(예를 들어, argv[1]이고 --foo=98, 다음 foo_value이다 98.)

업데이트 : 나는 간단한 작은 명령 줄 도구를 아주 조금 변경하는 것을보고 있기 때문에 Boost를 주저하고 있습니다. (미성년자를 위해 Boost를 연결하고 사용하는 방법을 배우지 않아도됩니다. 변화).


이미 Boost를 사용하고 있다면 boost string algorithms + lexical cast 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
}

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

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


파라미터 rfind있는 과부하를 사용하십시오 pos. 다음 pos은 검색 주제의 일부로 간주되는 마지막 색인입니다 (따라서 문자열이 titititi인 경우 후자 titi는 선택된 것보다 늦게 시작하기 때문에 고려되지 않습니다 pos=0).

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

누가 다른 게 필요한가요? 순수한 STL!


당신은 이것을 이렇게 할 것입니다 :

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

이를 위해 Boost.ProgramOptions와 같은 라이브러리를 찾는 것도 좋습니다.


완전성을 위해 C 방법을 언급 할 것입니다.

str원래 문자열 인 경우 substr확인하려는 하위 문자열 인 경우

strncmp(str, substr, strlen(substr))

시작하면가 반환 0됩니다 . 기능 C 헤더 파일에있는strsubstrstrncmpstrlen<string.h>

(원래 Yaseen Rauf here 게시 , 마크 업 추가)

대소 문자를 구분하지 않으려면 strnicmp대신을 사용하십시오 strncmp.

C ++ 문자열의 경우 다음과 같은 기능을 사용할 수 있습니다.

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

내가 사용하는 코드 :

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를 반환하면 prefix는 '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;
  }
}

@FelixDombek의 답변C argv[1]현 모두 "--foo"C 스트링 이라는 점을 감안할 때 최상의 솔루션입니다.

그러나 다른 답변을 보면 텍스트를 이미로 사용할 수 있다면 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());

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 솔루션보다 더 우아 하다고 생각합니다 . 그리고 파이썬 인터프리터가있는 곳 어디에서나 실행하는 경우 연결에 대해 걱정할 필요가 없습니다!

#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

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

C ++ 17을 사용하면 사용할 수 있습니다 std::basic_string_view및 20 ++ C와 std::basic_string::starts_withstd::basic_string_view::starts_with.

메모리 관리와 관련 std::string_view하여 얻을 수있는 이점은 std::string"문자열"(문자열 객체의 연속 된 시퀀스)에 대한 포인터 만 보유하고 크기를 알고 있다는 것입니다. 정수 값을 얻기 위해 소스 문자열을 이동 / 복사하지 않는 예 :

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

const char * argument = "--foo=42"; // Emulating command argument.
const char * argumentPrefix = "--foo";
int inputValue = 0;

std::string_view argView = argument;
if (argView.starts_with(argumentPrefix))
{
    std::string_view prefixView = argumentPrefix; // Helper for getting the size of argumentPrefix.
    try
    {
        // The underlying data of argView is nul-terminated, therefore we can use data().
        inputValue = std::atoi(argView.substr(prefixView.size() + 1).data());
    }
    catch (std::exception& e)
    {
        std::cerr << e.what();
    }
}

내가 사용 std::string::compare아래와 같은 유틸리티 메소드에 싸여 :

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

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

당신은 또한 사용할 수 있습니다 strstr:

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

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


Ok why the complicated use of libraries and stuff? C++ String objects overload the [] operator, so you can just compare chars.. Like what I just did, because I want to list all files in a directory and ignore invisible files and the .. and . pseudofiles.

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

It's that simple..


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

Since C++11 also std::regex_search can be used, e.g. as follows (returns an empty string on failure):

#include <regex>

std::string startsWith(const std::string &str, const std::string &prefix) {
  std::smatch match;
  std::regex_search(str, match, std::regex("^" + prefix));
  return match.suffix();
}

With C++11 or higher you can use find() and find_first_of()

Example using find to find a single char:

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

Example using find to find a full string & starting from position 5:

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

Example using the find_first_of() and only the first char, to search at the start only:

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

Good luck!


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

This is completely untested. The principle is the same as the Python one. Requires Boost.StringAlgo and Boost.LexicalCast.

Check if the string starts with the other string, and then get the substring ('slice') of the first string and convert it using lexical cast.

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

반응형