c++ 初学者,string.replace,代码编译但终止 - 如何用另一个字符替换数字?

c++ beginner, string.replace, code compiles but terminates - how do you replace numbers with another character?

在我的代码中,我试图提示用户输入他们的姓名、社会保险号、用户 ID 和密码,同时以 "xxx-xx-xxx" 格式输出社会保险号,基本上将所有数字替换为 x,密码中的字符也为 x

尽管如此,我在最初的社会保障部分遇到了严重的困难,因为在我对其进行测试时,代码可以编译,但它会终止。我认为我的问题是我对循环感到困扰。我应该为这个循环创建一个函数,还是完全错误?有人可以向我解释 string::replace() 函数以及 string::insert() 函数吗?

我明白了它的要旨,但将其付诸实践是我觉得自己失败得很惨的地方!

这是我目前的情况:

#include <iostream>
#include <string>
using namespace std;

string topSecret(string);//prototype for topSecret function after main

int main()
{
    //Top Secret Input
    string name, social, userName, password;
    cout << "Enter your first name, Social Security number (digits only), userID (no spaces within ID), and password (no spaces within password) - with a space between each entry: ";
    cin >> name >> social >> userName >> password;
    cout << "Name: " << name << endl;
    cout << "SSN: " << social.replace(0,social.length(), "X");
    cout << "SSN: " << social.insert(2,"-") << endl;
    cout << "UserID: " << userName << endl;
    cout << "Password: " << topSecret(password) << endl;

    return 0;
}//end main

string topSecret (string password)//replace all characters in password to an X
{
    string::size_type length;
    string::size_type pw;
    for (pw = 0; pw < password.length(); pw++)//for the duration of the password
    {
    }//end for loop
}//end topSecret

topSecret() 函数除了迭代字符串外没有做任何事情,它没有 return 任何值 - 你应该从中得到一个编译警告。

未指定 void 作为其 return 值的函数必须 always return 某些东西,不这样做会导致未定义的行为.在这种情况下,operator<<() 尝试打印的 std::string 实例可能最终指向无效内存,从而导致崩溃。

仅供参考,任何时候你不理解 C++ 函数,你可以 google 它,你应该在 cplusplus.com 弹出窗口中找到很好的解释。我就是从那里得到我要告诉你的信息的。

编辑:正如另一个人所说,cppreference.com 也应该出现,这也是需要查看的地方。忘记加了,哈哈

string::replace 获取起始位置、长度和替换它的字符串。

您似乎想要的是一个可以接受输入值并用您想要的任何值替换它的函数。在这种情况下,您似乎想要替换任何不是“-”的数字或字符,对吗?

在这种情况下,我会创建一个函数,它接受一个字符串引用、一个“shouldReplace”函数和一个将其替换为输入的值。

你说你是初学者,为了以防万一,我解释一下什么是参考。本质上,如果您将一个变量传递给一个函数并对其进行更改,那么您实际上并不会更改该变量,您将更改该变量的副本。这称为“按值传递”。如果您改为通过引用传递,那么您所做的任何更改都会实际影响您所做的事情。

我们的函数将接受输入字符串并对其进行修改,因为这是最简单的方法,因为 string::replace 已经这样做了。

接下来要说明的是如何将函数作为参数传递。再一次,既然你说你是初学者,我假设你不知道这一点。函数可以存储在变量中并像参数一样传递。我们想创建一个函数,给定一个字符,生成一个布尔值,判断该字符是否应该被替换,然后我们想把它传递给我们的替换函数。

现在是肉和土豆;替换功能。

首先,我们将使用我提到的参数声明函数:

#include <functional>
#include <string>

void conditionalReplaceWith(
        string &str, std::function<bool(char)> test, std::string repWith) {
    ...
}

请注意,为了获取字符串引用,我们使用 &str 并获取函数,我们使用标准库的一部分 std::function 并将其声明为 return a bool 并取一个 char 作为参数。

这意味着当我们传入一个函数时,它应该是这样的:

bool testFuncToPassIn(char c) {
    ...
}

现在我们有了一个函数,让我们填写它。

我们要遍历每个字符并测试它是否是我们要替换的字符。如果是,那么我们替换它。如果不是,那么我们继续。

使用 stringstreams 有更好的方法来做到这一点,但是因为你暗示你正在尝试做 string::replace,我已经使用它来代替。

我也会使用 const 引用,但由于您是初学者,此时不值得解释。你还不需要知道。

#include <functional>
#include <string>

void conditionalReplaceWith(
        string &str, std::function<bool(char)> test, std::string repWith) {
    // Loop over every character. This will work even after modifying str
    for(int pos = 0; pos < str.length(); pos++) {
        if(test(str[pos])) { // Check if the character should be replaced
            str.replace(pos, 1, repWith); // Replace it! Increases str.length()
        }
    }
}

现在我们需要测试函数:

bool isNotDash(char c) {
    return c != '-';
}

让我们把它们放在一起:

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

void conditionalReplaceWith(
        string &str, std::function<bool(char)> test, std::string repWith) {
    // Loop over every character. This will work even after modifying str
    for(int pos = 0; pos < str.length(); pos++) {
        if(test(str[pos])) { // Check if the character should be replaced
            str.replace(pos, 1, repWith); // Replace it! Increases str.length()
        }
    }
}

bool isNotDash(char c) {
    return c != '-';
}

int main() {
    std::string name, social, userName, password;
    std::cout << "Enter your first name, Social Security number (digits only), userID (no spaces within ID), and password (no spaces within password) - with a space between each entry: ";
    std::cin >> name >> social >> userName >> password;
    
    conditionalReplaceWith(social, isNotDash, "X");
    ...
}

最后,如果你想让你的绝密函数使用 conditionalReplaceWith,你可以这样做:

std::string topSecret(std::string password) {
    conditionalReplaceWith(password, [](char c) { return true; }, "X");
    return password;
}

那个小[](char c) { return true; }是一个匿名函数。它在那里声明了一个函数。

无论如何,这不会更改密码,因为请记住,密码是按值传递的。在这里修改它就像说std::string passwordCopy(password)然后先复制它。

是的。给你。

好的 :] 所以,你们好,我以一种非常有意义的方式输出了这个,这要归功于你的贡献和我这边的一些阅读。我还去了 cppreference 站点阅读更多内容。非常感谢你的帮忙!这是我改进后的新代码。请告诉我大家的想法...

#include <iostream>
#include <string>
using namespace std;

bool isNotDash(char);//prototype for isNotDash
string xOut(string);//prototype for xOut function
string topSecret(string);//prototype for topSecret function after main

int main()
{
    //Top Secret Input
    string name, social, userName, password;
    cout << "Enter your first name, Social Security number (000-00-000 format), userID (no spaces within ID), and password (no spaces within password) - with a space between each entry: ";
    cin >> name >> social >> userName >> password;
    cout << "Let's cover some of this up, shall we..." << endl;
    cout << "Name: " << name << endl;
    cout << "SSN: " << xOut(social) << endl;//calls xOut function to use as the output
    cout << "UserID: " << userName << endl;
    cout << "Password: " << topSecret(password) << endl;//calls topSecret function to use as output

    return 0;
}//end main

bool isNotDash(char n) //checks to see if within string social, is it a dash or number
{
    return n != '-'; // return any character that is not a dash - which would be a number
}//end isNotDash

string xOut(string social) // replace with X
{
    for(int x = 0; x < social.length(); x++)//loop through string
        {
            if(isNotDash (social.at(x)))// calls isNotDash function to check to see if character, that is not a dash, should be replaced
        {
            social.replace(x, 1, "X"); // start at position x, iterate, and x it out
        }//end if
    }
    return social;
}//end xOut function



string topSecret (string password)//replace all characters in password to an X
{
    string::size_type length;
    for (int pw = 0; pw < password.length(); pw++)//declare and initialize integer pw to 0, as long as it does not exceed the length of password - loop
    {
        password.replace(pw, 1, "X");//start at pos pw, iterate, and replace with x
    }//end for loop
    return password;
}//end topSecret