【问题标题】:Digits in std::stringstd::string 中的数字
【发布时间】:2017-11-29 15:56:48
【问题描述】:

您能帮我在不使用 isdigit 之类的函数的情况下查找字符串中的数字吗?我只能使用 for 循环和指针。如果我有

std::string s {"A year has 365 days"}

为什么我不能这样做:

for (int i=0; i<s.size(); i++){
    while (s[i]>='0' && s[i]<='9) v[i].push_back(s[i]);
}

我知道这会将数字 3 6 和 5 存储在向量中,而不是数字 365。但我不明白为什么我的 while 循环不起作用。

【问题讨论】:

  • 它不起作用,因为你的循环条件是“它是一个数字”,所以当它是一个数字时将它添加到v[i]。如果字符串不是以数字开头怎么办?
  • 但如果它不是一个数字,它不会做任何事情吗?我不明白,因为即使我使用它也不起作用。 if (s[i]&gt;='0' &amp;&amp; s[i]&lt;='9) { while (s[i]&gt;='0' &amp;&amp; s[i]&lt;='9) v[i].push_back(s[i]); i++; },
  • 你觉得i在线while (s[i]&gt;='0' &amp;&amp; s[i]&lt;='9) v[i].push_back(s[i]);会发生什么?
  • 这段代码将永远循环,你不要在你的while循环中增加i

标签: c++ string c++11 for-loop while-loop


【解决方案1】:

为什么我不能这样做:

for (int i=0; i<s.size(); i++){
    while (s[i]>='0' && s[i]<='9') v[i].push_back(s[i]);
}

这是行不通的,因为如果条件为true,程序将永远执行while 语句。您需要使用if 而不是while

for (int i=0; i<s.size(); i++)
{
   if (s[i]>='0' && s[i]<='9')
   {
      v[i].push_back(s[i]);
   }
}

【讨论】:

    【解决方案2】:

    如果我的理解正确,您只想存储数字吗?如果是这样,那么也许您正在寻找这样的东西:

     string s = "A year has 365 days";
     vector<string> storedNums = {};
    
     for(int i = 0; i < (s.length() - 1); i++) {
        if (s[i] >= 48 && s[i] <= 57) {
            storedNums.push_back(s[i]);
        }
    }
    

    这里我使用 48 到 57 之间的 ascii 值(数字字符)来破译当前字符是否为数字。如果条件为真,使用 while 循环将使您进入无限循环。这意味着一旦您的迭代达到“3”,它将继续处于 while 循环中。因此,您的向量将永远调用 push_back,因为当前条件已满足并且没有基本情况可以跳出 while 循环。

    编辑: 这段代码有两个我最初没有发现的错误。首先,向量应该是vector&lt;char&gt; 而不是vector&lt;string&gt;。其次,我注意到条件不应该是i &lt; s.length()-1,而应该是i &lt; s.length()。我最初输入的方式会跳过循环中的最后一个索引,它适用于给定的字符串,但是如果从字符串中取出 "days",它只会打印36。以下代码已针对可读性进行了调整,并经过编译以确保其正常工作:

    // Example program
    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;
    
    int main()
    {
        string s = "A year is 365";
        vector<char> nums;
        int length = s.length();
    
        for(int i = 0; i < length; i++) {
    
            if (s[i] >= '0' && s[i] <= '9') {
                nums.push_back(s[i]);
                cout << s[i];
            }
        }
    } 
    

    【讨论】:

    • 你的循环结束条件应该是i &lt; s.length()。如果字符串为空,您当前的代码将跳过最后一个字符或执行更糟糕的操作。
    • 即使限制为 ASCII 也可以,考虑使用'0''9' 来提高代码的可读性。
    • @Bob__ 是的,我完全同意你的看法
    【解决方案3】:
    std::string str {"A year has 365 days"};   
    std::vector<char> vec;   
    for(const char c: str)   
    {
      if (c>='0' && c<='9')
      {
        vec.push_back(c);
      }   
    }
    

    【讨论】:

    • 您介意详细说明吗?即使发布的代码可以回答问题,解释也可能对其他人有益并增加其价值。
    • 首先,我们创建一个字符串对象将用作测试,然后创建一个向量来存储所有数字。然后 for 循环遍历字符串。检查字符串中的每个字符是否为数字。如果是,则将其添加到向量中。
    【解决方案4】:

    您正在循环一个序列并有条件地将元素复制到另一个容器。标准库有一个专门用于此任务的std::copy_if 算法。

    std::string s{ "A year has 365 days" };
    std::vector<char> v;
    
    std::copy_if(s.begin(), s.end(), std::back_inserter(v), ::isdigit);
    

    如果您坚持不使用isdigit,您可以提供自己的谓词(本例中为 lambda)。

    std::copy_if(s.begin(), s.end(), std::back_inserter(v),
        [](char ch) { return '0' <= ch && ch <= '9'; }
    );
    

    【讨论】:

    • 我同意,但是 OP 问题中的 "I can only use for loop and pointers" 确实与 C++11 标记冲突...
    猜你喜欢
    • 2018-11-24
    • 2010-10-28
    • 2011-05-13
    • 2017-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多