【问题标题】:Trimming 0 from a string从字符串中修剪 0
【发布时间】:2021-05-17 10:27:09
【问题描述】:

假设我有像“0003443”这样的字符串,我们的目标是达到“3443”。我已经使用子字符串方法找出零的数量,但我想知道在 c++ 中执行此操作的最佳方法。

【问题讨论】:

  • 但是我想知道最好的方法
  • 你会发现“最优”并没有很好的定义。你的意思是最快的?如果是这样,数据看起来如何?你运行一次吗? 1e6 次?平均有多少个零?有多少个字符串没有前导零?你的主机有什么能力?你想使用 AVX 指令吗?如果是,那是什么样的指令?另一个可选的可能是最短的代码。
  • “最佳”可能是首先不生成带有不需要的前导零的字符串。然后不需要去除前导零,在这种情况下,去除前导零的步骤是无操作的,因此效率最佳。
  • 找到零的数量,然后使用substr 对我来说是最佳选择。你能想到任何更优化的过程吗?当然,这完全取决于您所说的“最佳”是什么意思。我的感觉是,当初学者在没有定义任何这些术语的情况下问什么是最优化、最有效或最好的,这仅仅是因为他们对自己的代码缺乏信心。就好像他们认为有一些专家知道但他们不知道的秘密技巧。

标签: c++ string substring


【解决方案1】:

您可以在https://repl.it/@JomaCorpFX/TrimLeftZeros#main.cpp 中测试/运行此代码

代码

#include <iostream>
#include <regex>
#include <stdexcept>
#include <chrono>


time_t CurrentEpochMilliseconds()
{
    using namespace std::chrono;
    return duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
}

std::string TrimZeros1(const std::string& number)
{
    std::regex regex(u8"[-+]?[0-9]{1,}", std::regex_constants::ECMAScript); 
    if(!std::regex_match(number, regex)) //Validating number format +XXXXX or -XXXXX or XXXXX
    {
        throw std::invalid_argument("Invalid parameter, it is not a number.");
    }

    std::string result = number;
    size_t pos = 0;
    if(result[0] == '+') 
    {
        result.erase(0,1);
    }
    if(result[0] == '-')
    {
        pos = 1;
    }

    while (result.size()>0 && result[pos]== '0') 
    {
        result.erase(pos,1); //Erase first char. Pos = pos, Count = 1
    }
    return (pos == 1 && result.size() ==1) || result.size() == 0 ? u8"0" : result; 
}

std::string TrimZeros2(const std::string& number)
{
    std::regex regex(u8"[-+]?[0-9]{1,}", std::regex_constants::ECMAScript);
    if(!std::regex_match(number, regex))
    {
        throw std::invalid_argument("Invalid parameter, it is not a number.");
    }

    int result = std::stoi(number);
    return std::to_string(result);
}

int main()
{
    std::cout<<u8"--- TrimZeros1"<< std::endl;
    std::cout<< TrimZeros1(u8"0003443") << std::endl;
    std::cout<< TrimZeros1(u8"0000123") << std::endl;
    std::cout<< TrimZeros1(u8"0000789") << std::endl;
    std::cout<< TrimZeros1(u8"0000000") << std::endl;

    std::cout<< TrimZeros1(u8"+0003443") << std::endl;
    std::cout<< TrimZeros1(u8"+0000123") << std::endl;
    std::cout<< TrimZeros1(u8"+0000789") << std::endl;
    std::cout<< TrimZeros1(u8"+0000000") << std::endl;

    std::cout<< TrimZeros1(u8"-0003443") << std::endl;
    std::cout<< TrimZeros1(u8"-0000123") << std::endl;
    std::cout<< TrimZeros1(u8"-0000789") << std::endl;
    std::cout<< TrimZeros1(u8"-0000000") << std::endl;

    std::cout <<std::endl;

    std::cout<<u8"--- TrimZeros2"<< std::endl;
    std::cout<< TrimZeros2(u8"0003443") << std::endl;
    std::cout<< TrimZeros2(u8"0000123") << std::endl;
    std::cout<< TrimZeros2(u8"0000789") << std::endl;
    std::cout<< TrimZeros2(u8"0000000") << std::endl;

    std::cout<< TrimZeros2(u8"+0003443") << std::endl;
    std::cout<< TrimZeros2(u8"+0000123") << std::endl;
    std::cout<< TrimZeros2(u8"+0000789") << std::endl;
    std::cout<< TrimZeros2(u8"+0000000") << std::endl;

    std::cout<< TrimZeros2(u8"-0003443") << std::endl;
    std::cout<< TrimZeros2(u8"-0000123") << std::endl;
    std::cout<< TrimZeros2(u8"-0000789") << std::endl;
    std::cout<< TrimZeros2(u8"-0000000") << std::endl;

    //std::cout<< TrimZeros2(u8"") << std::endl; //Error it is not a valid number value.

    std::cout <<std::endl;
    std::cout <<std::endl;

    int iterations = 10000;
    std::cout<<u8"--- Started - TrimZeros1 - Time Test"<< std::endl;
    time_t actual = CurrentEpochMilliseconds();
    for(int i = 0; i< iterations; i++)
    {
        TrimZeros1(u8"+0000000");
        TrimZeros1(u8"-0000000");
        TrimZeros1(u8"0000000");
        TrimZeros1(u8"+1111112");
        TrimZeros1(u8"-1111112");
        TrimZeros1(u8"1111112");
    }
    actual = CurrentEpochMilliseconds() - actual;
    std::cout << ("Elapsed seconds = " + std::to_string(actual / 1000.0) + "  ---  Elapsed milliseconds = " + std::to_string(actual) + "  ---  Elapsed minutes = " + std::to_string((actual / 1000.0) / 60.0)) << std::endl;
std::cout <<std::endl;
    std::cout <<std::endl;

    
    std::cout<<u8"--- Started - TrimZeros2 - Time Test"<< std::endl;
    actual = CurrentEpochMilliseconds();
    for(int i = 0; i< iterations; i++)
    {
        TrimZeros2(u8"+0000000");
        TrimZeros2(u8"-0000000");
        TrimZeros2(u8"0000000");
        TrimZeros2(u8"+1111112");
        TrimZeros2(u8"-1111112");
        TrimZeros2(u8"1111112");
    }
    actual = CurrentEpochMilliseconds() - actual;
    std::cout << ("Elapsed seconds = " + std::to_string(actual / 1000.0) + "  ---  Elapsed milliseconds = " + std::to_string(actual) + "  ---  Elapsed minutes = " + std::to_string((actual / 1000.0) / 60.0)) << std::endl;
    std::cout <<std::endl;
    std::cout <<std::endl;

    std::cout<< u8"Press enter to continue... ";
    std::cin.get();
    return EXIT_SUCCESS;
}

输出

--- TrimZeros1
3443
123
789
0
3443
123
789
0
-3443
-123
-789
0

--- TrimZeros2
3443
123
789
0
3443
123
789
0
-3443
-123
-789
0


--- Started - TrimZeros1 - Time Test
Elapsed seconds = 106.251000  ---  Elapsed milliseconds = 106251  ---  Elapsed minutes = 1.770850


--- Started - TrimZeros2 - Time Test
Elapsed seconds = 99.248000  ---  Elapsed milliseconds = 99248  ---  Elapsed minutes = 1.654133


Press enter to continue...

clang++ - 网络/在线https://repl.it

g++ 本地机器

clang++ 本地机器

【讨论】:

  • 如果能显示时间比较就好了。顺便说一句,谢谢
  • 你的第二个修剪函数需要一个条件,即字符串在 long 范围内,这可能不是真的
  • 添加时间比较,数字验证。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-02
  • 2014-03-26
  • 1970-01-01
  • 2012-03-21
  • 2014-11-27
  • 2022-11-01
  • 1970-01-01
相关资源
最近更新 更多