2

在我的一本书中有一条关于人们将逗号输入整数并弄乱你的程序的评论,但它没有详细说明。这让我开始思考,所以我尝试编写一个小算法来获取 std::string 并删除所有非整数字符。此代码编译但跳过输出。为什么没有任何东西被分配给newstring?if(isdigit(fstring[i])) 是否将其指向的地址评估为真以保存数字?

//little algorithm to take the non-integers out of a string
//no idea on efficiency

#include <iostream>
#include <string>

int main()
{
    std::cout << "Enter a number with non-integer characters: ";

    std::string fstring; 
    getline(std::cin, fstring);

    std::string newstring;

    int i = 0, x = 0;

    while (i != fstring.length())
    {
        if (isdigit(fstring[i]))
        {
            newstring[x] = fstring[i];
            i++;
            x++;
        }
        else
        {
           i++;
        }
    }

    std::cout << std::endl;
    std::cout << newstring;
    system("PAUSE");
}

第二个问题,可能属于其他地方:如何将字符串转换为 int(或浮点数)?

4

5 回答 5

6

newstring 的长度为 0,因此 x=0 的 newstring[x] 实际上是非法的。您应该使用以下命令附加到字符串: newstring.append(1, fstring[i])

对于第二个问题,查找 atoi()、atof()、strtol(0、strtof() 函数。

于 2009-05-03T00:40:00.187 回答
5

字符串类似于数组,但字符串的默认构造函数会创建一个空字符串。为什么它应该分配比它需要的更多的内存?即使是这样,也没有说有多少,或者它是否足以容纳 fstring 的过滤副本。我印象深刻,它不会崩溃。

一个简单的修改是改变:

std::string newstring;

到:

 std::string newstring(fstring.length(), '\0')

在循环之后添加:

 newstring.resize(x);

这将确保newstring在过滤期间至少有足够的空间(可能更多),并且在完成过滤后将被修剪到适当的大小。您可能还对 中的std::remove_copy_if功能感兴趣<algorithm>

例如

struct isnotdigit { bool operator()(char c) { return !isdigit(c); } };

std::string newstring(fstring.length(), '\0');
std::string::iterator i = std::remove_copy_if(fstring.begin(), 
  fstring.end(), newstring.begin(), isnotdigit());
newstring.erase(i, newstring.end());

至于将字符串转换为整数/浮点数,除了已经提到的atoi, strtol, atof,strtof等函数之外,您还可以使用 iostream 库:

 #include <sstream>
 std::string integer("23");
 std::istringstream iss(integer);
 int result;
 iss >> result;

 std::string floatingpoint("3.14");
 std::istringstream iss2(floatingpoint);
 double result2;
 iss2 >> result2;

此外,如果您熟悉您可能感兴趣的 printf 系列函数scanfsscanf

 const char *s = "23";
 int result;
 sscanf(s, "%d", &result);
于 2009-05-03T01:22:41.597 回答
2

扩展成业的回答:

要删除非数字:

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

using namespace std;

int main() {
    string fstring;
    getline(cin, fstring);
    fstring.erase(
        remove_if(fstring.begin(), fstring.end(),
            not1(ptr_fun(static_cast<int(*)(int)>(isdigit)))
        ),
        fstring.end()
    );

    cout << fstring << "\n";
}

不过,我不确定为什么需要 static_cast。我认为如果没有它,isdigit 就有些模棱两可了。[编辑:如果你不做“使用命名空间标准”,那么你就不需要它,所以懒惰写示例代码是我的错。]

这是否比滚动你自己的循环更简单是有争议的:

#include <iostream>
#include <string>

using namespace std;

int main() {
    string fstring, ins;
    getline(cin, ins);
    for (string::iterator it = ins.begin(); it != ins.end(); ++it) {
        if (isdigit(*it)) fstring.push_back(*it);
    }
    cout << fstring << "\n";
}

而 C++0x 会有 copy_if,基本上是偶然遗漏的,实现起来也很简单:

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

int main() {
    std::string fstring, ins;
    std::getline(std::cin, ins);
    std::copy_if(ins.begin(), ins.end(), 
        std::back_inserter(fstring), isdigit);
    std::cout << fstring << "\n";
}

转换为 int(或 float):

int i = boost::lexical_cast<int>(fstring);

或者如果你没有提升:

#include <sstream>

int i = 0;
std::stringstream(fstring) >> i;

请注意,您必须初始化 i,否则如果 fstring 为空,则不会设置它。

于 2009-05-03T11:34:23.530 回答
1

要删除数字:

fstring.erase(
      std::remove_if(fstring.begin(), fstring.end(), &isdigit), 
      fstring.end());

要将字符串转换为 int/float/...:

int n1 = boost::lexical_cast<int>("123");
float n2 = boost::lexical_cast<float>("123.456");
于 2009-05-03T04:05:52.703 回答
0
  • 字符串转浮点数:

你需要#include <cstdlib>

float strtof(const char *nptr, char **endptr);

例如:

 float f = strtof("3.4",NULL);
  • 字符串转整数

你需要#include <cstdlib>

int atoi(const char *numPtr);

请注意,这些是 C 函数,而不是 C++,因此您需要在 std::string 上使用 c_str() 方法来获取 C 字符串。

const char* c_str ( ) const;
于 2009-05-03T01:13:22.133 回答