如何从 c++ 中的字符串中删除所有非字母数字字符?

发布于 2024-11-14 22:44:24 字数 126 浏览 4 评论 0 原文

我正在编写一个软件,它要求我使用 libcurl 处理从网页获取的数据。当我获取数据时,由于某种原因,其中有额外的换行符。我需要找到一种只允许字母、数字和空格的方法。并删除其他所有内容,包括换行符。有什么简单的方法可以做到这一点吗?谢谢。

I am writing a piece of software, and It require me to handle data I get from a webpage with libcurl. When I get the data, for some reason it has extra line breaks in it. I need to figure out a way to only allow letters, numbers, and spaces. And remove everything else, including line breaks. Is there any easy way to do this? Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

梦途 2024-11-21 22:44:24

编写一个接受 char 的函数,如果要删除该字符,则返回 true;如果要保留该字符,则返回 false

bool my_predicate(char c);

然后使用std::remove_if 算法从字符串中删除不需要的字符:

std::string s = "my data";
s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());

根据您的要求,您可以使用标准库谓词之一,例如 std::isalnum,而不是写你自己的谓词(你说你需要匹配字母数字字符和空格,所以这可能不完全符合您的需要)。

如果您想使用标准库 std::isalnum 函数,则需要进行强制转换来消除 C 标准库头文件中的 std::isalnum 函数之间的歧义 (这是您要使用的)和 C++ 标准库标头 中的 std::isalnum (哪个不是您想要使用的容器,除非您想要执行特定于区域设置的字符串处理):

s.erase(std::remove_if(s.begin(), s.end(), (int(*)(int))std::isalnum), s.end());

这对于任何序列容器(包括 std::stringstd: :vector 和 std::deque )。该习惯用法通常称为“擦除/删除”习惯用法。 std::remove_if 算法也适用于普通数组。 std::remove_if 仅对序列进行一次传递,因此它具有线性时间复杂度。

Write a function that takes a char and returns true if you want to remove that character or false if you want to keep it:

bool my_predicate(char c);

Then use the std::remove_if algorithm to remove the unwanted characters from the string:

std::string s = "my data";
s.erase(std::remove_if(s.begin(), s.end(), my_predicate), s.end());

Depending on your requirements, you may be able to use one of the Standard Library predicates, like std::isalnum, instead of writing your own predicate (you said you needed to match alphanumeric characters and spaces, so perhaps this doesn't exactly fit what you need).

If you want to use the Standard Library std::isalnum function, you will need a cast to disambiguate between the std::isalnum function in the C Standard Library header <cctype> (which is the one you want to use) and the std::isalnum in the C++ Standard Library header <locale> (which is not the one you want to use, unless you want to perform locale-specific string processing):

s.erase(std::remove_if(s.begin(), s.end(), (int(*)(int))std::isalnum), s.end());

This works equally well with any of the sequence containers (including std::string, std::vector and std::deque). This idiom is commonly referred to as the "erase/remove" idiom. The std::remove_if algorithm will also work with ordinary arrays. The std::remove_if makes only a single pass over the sequence, so it has linear time complexity.

So要识趣 2024-11-21 22:44:24

以前使用 std::isalnum 时,如果不传递 unary 参数,则无法使用 std::ptr_fun 进行编译,因此此解决方案带有lambda 函数应该封装正确的答案:

s.erase(std::remove_if(s.begin(), s.end(), 
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());

Previous uses of std::isalnum won't compile with std::ptr_fun without passing the unary argument is requires, hence this solution with a lambda function should encapsulate the correct answer:

s.erase(std::remove_if(s.begin(), s.end(), 
[]( auto const& c ) -> bool { return !std::isalnum(c); } ), s.end());
南七夏 2024-11-21 22:44:24

如果您使用字符串,您始终可以循环遍历并擦除所有非字母数字字符。

#include <cctype>

size_t i = 0;
size_t len = str.length();
while(i < len){
    if (!isalnum(str[i]) || str[i] == ' '){
        str.erase(i,1);
        len--;
    }else
        i++;
}

更好地使用标准库的人可能可以在没有循环的情况下完成此操作。

如果您仅使用 char 缓冲区,则可以循环遍历,如果字符不是字母数字,则将其后面的所有字符向后移动一位(以覆盖有问题的字符):

#include <cctype>

size_t buflen = something;
for (size_t i = 0; i < buflen; ++i)
    if (!isalnum(buf[i]) || buf[i] != ' ')
        memcpy(buf[i], buf[i + 1], --buflen - i);

You could always loop through and just erase all non alphanumeric characters if you're using string.

#include <cctype>

size_t i = 0;
size_t len = str.length();
while(i < len){
    if (!isalnum(str[i]) || str[i] == ' '){
        str.erase(i,1);
        len--;
    }else
        i++;
}

Someone better with the Standard Lib can probably do this without a loop.

If you're using just a char buffer, you can loop through and if a character is not alphanumeric, shift all the characters after it backwards one (to overwrite the offending character):

#include <cctype>

size_t buflen = something;
for (size_t i = 0; i < buflen; ++i)
    if (!isalnum(buf[i]) || buf[i] != ' ')
        memcpy(buf[i], buf[i + 1], --buflen - i);
与风相奔跑 2024-11-21 22:44:24

只是稍微扩展了 James McNellis 的代码。他的功能是删除alnum字符而不是非alnum字符。

从字符串中删除非数字字符。 (alnum = 字母或数字)

  • 声明一个函数(如果传递的 char 不是 alnum,isalnum 返回 0)

    bool isNotAlnum(char c) {
        返回 isalnum(c) == 0;
    }
    
  • 然后写这个

    s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end());
    

,那么你的字符串就只有 alnum 字符。

Just extending James McNellis's code a little bit more. His function is deleting alnum characters instead of non-alnum ones.

To delete non-alnum characters from a string. (alnum = alphabetical or numeric)

  • Declare a function (isalnum returns 0 if passed char is not alnum)

    bool isNotAlnum(char c) {
        return isalnum(c) == 0;
    }
    
  • And then write this

    s.erase(remove_if(s.begin(), s.end(), isNotAlnum), s.end());
    

then your string is only with alnum characters.

梦中的蝴蝶 2024-11-21 22:44:24

对不同方法进行基准测试。

如果你正在寻找一个基准,我做了一个。

(115830 cycles) 115.8ms -> using stringstream
( 40434 cycles)  40.4ms -> s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !isalnum(c); }), s.end());
( 40389 cycles)  40.4ms -> s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return ispunct(c); }), s.end());
( 42386 cycles)  42.4ms -> s.erase(remove_if(s.begin(), s.end(), not1(ptr_fun( (int(*)(int))isalnum ))), s.end());
( 42969 cycles)  43.0ms -> s.erase(remove_if(s.begin(), s.end(), []( auto const& c ) -> bool { return !isalnum(c); } ), s.end());
( 44829 cycles)  44.8ms -> alnum_from_libc(s) see below
( 24505 cycles)  24.5ms -> Puzzled? My method, see below
(  9717 cycles)   9.7ms -> using mask and bitwise operators

Original length: 8286208, current len with alnum only: 5822471

  • Stringstream 给出了可怕的结果(但我们都知道)
  • 已经给出的不同答案给出了大约相同的运行时间
  • 以 C 方式执行它始终提供更好的运行时间(几乎快两倍!),这绝对值得考虑,最重要的是兼容C语言。
  • 我的按位方法(也与 C 兼容)速度快了 400% 以上。

NB 必须修改所选答案,因为它只保留特殊字符

NB2:测试文件是一个(几乎)8192 kb 的文本文件,大约有 62 个数字和 12 个特殊字符,随机而且写得均匀。


Benchmark源码

#include <ctime>

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>

#include <locale> // ispunct
#include <cctype>

#include <fstream> // read file
#include <streambuf>

#include <sys/stat.h> // check if file exist
#include <cstring>

using namespace std;

bool exist(const char *name)
{
  struct stat   buffer;
  return !stat(name, &buffer);
}

constexpr int SIZE = 8092 * 1024;

void keep_alnum(string &s) {
    stringstream ss;
    int i = 0;
    for (i = 0; i < SIZE; i++)
        if (isalnum(s[i]))
            ss << s[i];
    s = ss.str();
}

/* my method, best runtime */
void old_school(char *s) {
    int n = 0;
    for (int i = 0; i < SIZE; i++) {
        unsigned char c = s[i] - 0x30; // '0'
        if (c < 10 || (c -= 0x11) < 26 || (c -= 0x20) < 26) // 0x30 + 0x11 = 'A' + 0x20 = 'a'
            s[n++] = s[i];
    }
    s[n] = '\0';
}

void alnum_from_libc(char *s) {
    int n = 0;
    for (int i = 0; i < SIZE; i++) {
        if (isalnum(s[i]))
            s[n++] = s[i];
    }
    s[n] = '\0';
}

#define benchmark(x) printf("\033[30m(%6.0lf cycles) \033[32m%5.1lfms\n\033[0m", x, x / (CLOCKS_PER_SEC / 1000))

int main(int ac, char **av) {
    if (ac < 2) {
        cout << "usage: ./a.out \"{your string} or ./a.out FILE \"{your file}\n";
        return 1;
    }
    string s;
    s.reserve(SIZE+1);
    string s1;
    s1.reserve(SIZE+1);
    char s4[SIZE + 1], s5[SIZE + 1];
    if (ac == 3) { 
        if (!exist(av[2])) {
            for (size_t i = 0; i < SIZE; i++)
              s4[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnoporstuvwxyz!@#$%^&*()__+:\"<>?,./'"[rand() % 74];
          s4[SIZE] = '\0';
          ofstream ofs(av[2]);
          if (ofs)
            ofs << s4;
        }
        ifstream ifs(av[2]);
        if (ifs) {
          ifs.rdbuf()->pubsetbuf(s4, SIZE);
          copy(istreambuf_iterator<char>(ifs), {}, s.begin());
        }
        else
          cout << "error\n";

        ifs.seekg(0, ios::beg);
        s.assign((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());
    }
    else
        s = av[1];

    double elapsedTime;
    clock_t start;
    bool is_different = false;

    s1 = s;
    start = clock();
    keep_alnum(s1);
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    string tmp = s1;

    s1 = s;
    start = clock();
    s1.erase(std::remove_if(s1.begin(), s1.end(), [](char c) { return !isalnum(c); }), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    s1 = s;
    start = clock();
    s1.erase(std::remove_if(s1.begin(), s1.end(), [](char c) { return ispunct(c); }), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    s1 = s;
    start = clock();
    s1.erase(remove_if(s1.begin(), s1.end(), not1(ptr_fun( (int(*)(int))isalnum ))), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    s1 = s;
    start = clock();
    s1.erase(remove_if(s1.begin(), s1.end(), []( auto const& c ) -> bool { return !isalnum(c); } ), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    memcpy(s4, s.c_str(), SIZE);
    start = clock();
    alnum_from_libc(s4);
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s4);

    memcpy(s4, s.c_str(), SIZE);
    start = clock();
    old_school(s4);
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s4);

    cout << "Original length: " << s.size() << ", current len with alnum only: " << strlen(s4) << endl;
    // make sure that strings are equivalent
    printf("\033[3%cm%s\n", ('3' + !is_different), !is_different ? "OK" : "KO");

    return 0;
}

我的解决方案

按位法可以直接在我的github,基本上我避免了分支指令(如果)感谢掩码。我避免使用 C++ 标签发布按位运算,我对此非常讨厌。

对于 C 风格,我迭代字符串并有两个索引:n 用于我们保留的字符,i 用于遍历字符串,我们在其中一个接一个地进行测试如果是数字,则为大写或小写。

添加此功能:

void strip_special_chars(char *s) {
    int n = 0;
    for (int i = 0; i < SIZE; i++) {
        unsigned char c = s[i] - 0x30;
        if (c < 10 || (c -= 0x11) < 26 || (c -= 0x20) < 26) // 0x30 + 0x11 = 'A' + 0x20 = 'a'
            s[n++] = s[i];
    }
    s[n] = '\0';
}

并用作:

char s1[s.size() + 1]
memcpy(s1, s.c_str(), s.size());
strip_special_chars(s1);

Benchmarking the different methods.

If you are looking for a benchmark I made one.

(115830 cycles) 115.8ms -> using stringstream
( 40434 cycles)  40.4ms -> s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !isalnum(c); }), s.end());
( 40389 cycles)  40.4ms -> s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return ispunct(c); }), s.end());
( 42386 cycles)  42.4ms -> s.erase(remove_if(s.begin(), s.end(), not1(ptr_fun( (int(*)(int))isalnum ))), s.end());
( 42969 cycles)  43.0ms -> s.erase(remove_if(s.begin(), s.end(), []( auto const& c ) -> bool { return !isalnum(c); } ), s.end());
( 44829 cycles)  44.8ms -> alnum_from_libc(s) see below
( 24505 cycles)  24.5ms -> Puzzled? My method, see below
(  9717 cycles)   9.7ms -> using mask and bitwise operators

Original length: 8286208, current len with alnum only: 5822471

  • Stringstream gives terrible results (but we all know that)
  • The different answers already given gives about the same runtime
  • Doing it the C way consistently give better runtime (almost twice faster!), it is definitely worth considering, and on top of that it is compatible with C language.
  • My bitwise method (also C compatible) is more than 400% faster.

NB the selected answer had to be modified as it was keeping only the special characters

NB2: The test file is a (almost) 8192 kb text file with roughly 62 alnum and 12 special characters, randomly and evenly written.


Benchmark source code

#include <ctime>

#include <iostream>
#include <sstream>
#include <string>
#include <algorithm>

#include <locale> // ispunct
#include <cctype>

#include <fstream> // read file
#include <streambuf>

#include <sys/stat.h> // check if file exist
#include <cstring>

using namespace std;

bool exist(const char *name)
{
  struct stat   buffer;
  return !stat(name, &buffer);
}

constexpr int SIZE = 8092 * 1024;

void keep_alnum(string &s) {
    stringstream ss;
    int i = 0;
    for (i = 0; i < SIZE; i++)
        if (isalnum(s[i]))
            ss << s[i];
    s = ss.str();
}

/* my method, best runtime */
void old_school(char *s) {
    int n = 0;
    for (int i = 0; i < SIZE; i++) {
        unsigned char c = s[i] - 0x30; // '0'
        if (c < 10 || (c -= 0x11) < 26 || (c -= 0x20) < 26) // 0x30 + 0x11 = 'A' + 0x20 = 'a'
            s[n++] = s[i];
    }
    s[n] = '\0';
}

void alnum_from_libc(char *s) {
    int n = 0;
    for (int i = 0; i < SIZE; i++) {
        if (isalnum(s[i]))
            s[n++] = s[i];
    }
    s[n] = '\0';
}

#define benchmark(x) printf("\033[30m(%6.0lf cycles) \033[32m%5.1lfms\n\033[0m", x, x / (CLOCKS_PER_SEC / 1000))

int main(int ac, char **av) {
    if (ac < 2) {
        cout << "usage: ./a.out \"{your string} or ./a.out FILE \"{your file}\n";
        return 1;
    }
    string s;
    s.reserve(SIZE+1);
    string s1;
    s1.reserve(SIZE+1);
    char s4[SIZE + 1], s5[SIZE + 1];
    if (ac == 3) { 
        if (!exist(av[2])) {
            for (size_t i = 0; i < SIZE; i++)
              s4[i] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnoporstuvwxyz!@#$%^&*()__+:\"<>?,./'"[rand() % 74];
          s4[SIZE] = '\0';
          ofstream ofs(av[2]);
          if (ofs)
            ofs << s4;
        }
        ifstream ifs(av[2]);
        if (ifs) {
          ifs.rdbuf()->pubsetbuf(s4, SIZE);
          copy(istreambuf_iterator<char>(ifs), {}, s.begin());
        }
        else
          cout << "error\n";

        ifs.seekg(0, ios::beg);
        s.assign((istreambuf_iterator<char>(ifs)), istreambuf_iterator<char>());
    }
    else
        s = av[1];

    double elapsedTime;
    clock_t start;
    bool is_different = false;

    s1 = s;
    start = clock();
    keep_alnum(s1);
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    string tmp = s1;

    s1 = s;
    start = clock();
    s1.erase(std::remove_if(s1.begin(), s1.end(), [](char c) { return !isalnum(c); }), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    s1 = s;
    start = clock();
    s1.erase(std::remove_if(s1.begin(), s1.end(), [](char c) { return ispunct(c); }), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    s1 = s;
    start = clock();
    s1.erase(remove_if(s1.begin(), s1.end(), not1(ptr_fun( (int(*)(int))isalnum ))), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    s1 = s;
    start = clock();
    s1.erase(remove_if(s1.begin(), s1.end(), []( auto const& c ) -> bool { return !isalnum(c); } ), s1.end());
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s1.c_str());

    memcpy(s4, s.c_str(), SIZE);
    start = clock();
    alnum_from_libc(s4);
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s4);

    memcpy(s4, s.c_str(), SIZE);
    start = clock();
    old_school(s4);
    elapsedTime = (clock() - start);
    benchmark(elapsedTime);
    is_different |= !!strcmp(tmp.c_str(), s4);

    cout << "Original length: " << s.size() << ", current len with alnum only: " << strlen(s4) << endl;
    // make sure that strings are equivalent
    printf("\033[3%cm%s\n", ('3' + !is_different), !is_different ? "OK" : "KO");

    return 0;
}

My solution

For the bitwise method you can check it directly on my github, basically I avoid branching instructions (if) thanks to the mask. I avoid posting bitwise operations with C++ tag, I get a lot of hate for it.

For the C style one, I iterate over the string and have two index: n for the characters we keep and i to go through the string, where we test one after another if it is a digit, a uppercase or a lowercase.

Add this function:

void strip_special_chars(char *s) {
    int n = 0;
    for (int i = 0; i < SIZE; i++) {
        unsigned char c = s[i] - 0x30;
        if (c < 10 || (c -= 0x11) < 26 || (c -= 0x20) < 26) // 0x30 + 0x11 = 'A' + 0x20 = 'a'
            s[n++] = s[i];
    }
    s[n] = '\0';
}

and use as:

char s1[s.size() + 1]
memcpy(s1, s.c_str(), s.size());
strip_special_chars(s1);
暖心男生 2024-11-21 22:44:24

remove_copy_if 标准算法非常适合您的情况。

The remove_copy_if standard algorithm would be very appropriate for your case.

最近可好 2024-11-21 22:44:24
#include <cctype>
#include <string>
#include <functional>

std::string s = "Hello World!";
s.erase(std::remove_if(s.begin(), s.end(),
    std::not1(std::ptr_fun(std::isalnum)), s.end()), s.end());
std::cout << s << std::endl;

结果:

"HelloWorld"

您使用 isalnum 来确定每个字符是否是字母数字,然后使用 ptr_fun 将函数传递给 NOT1返回值,只留下你想要的字母数字内容。

#include <cctype>
#include <string>
#include <functional>

std::string s = "Hello World!";
s.erase(std::remove_if(s.begin(), s.end(),
    std::not1(std::ptr_fun(std::isalnum)), s.end()), s.end());
std::cout << s << std::endl;

Results in:

"HelloWorld"

You use isalnum to determine whether or not each character is alpha numeric, then use ptr_fun to pass the function to not1 which NOTs the returned value, leaving you with only the alphanumeric stuff you want.

蹲在坟头点根烟 2024-11-21 22:44:24

您可以这样使用删除擦除算法 -

// Removes all punctuation       
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());

You can use the remove-erase algorithm this way -

// Removes all punctuation       
s.erase( std::remove_if(s.begin(), s.end(), &ispunct), s.end());
绝對不後悔。 2024-11-21 22:44:24

下面的代码对于给定的字符串 s 应该可以正常工作。它利用 库。

std::string s("He!!llo  Wo,@rld! 12 453");
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalnum(c); }), s.end());

Below code should work just fine for given string s. It's utilizing <algorithm> and <locale> libraries.

std::string s("He!!llo  Wo,@rld! 12 453");
s.erase(std::remove_if(s.begin(), s.end(), [](char c) { return !std::isalnum(c); }), s.end());
暗地喜欢 2024-11-21 22:44:24

提到的解决方案

s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());

非常好,但不幸的是在 Visual Studio(调试模式)中不适用于像“Ñ”这样的字符,因为这一行:

_ASSERTE((unsigned)(c + 1) <= 256)

在 isctype.c

所以,我会推荐这样的东西:

inline int my_ispunct( int ch )
{
    return std::ispunct(unsigned char(ch));
}
...
s.erase( std::remove_if(s.begin(), s.end(), &my_ispunct), s.end());

The mentioned solution

s.erase( std::remove_if(s.begin(), s.end(), &std::ispunct), s.end());

is very nice, but unfortunately doesn't work with characters like 'Ñ' in Visual Studio (debug mode), because of this line:

_ASSERTE((unsigned)(c + 1) <= 256)

in isctype.c

So, I would recommend something like this:

inline int my_ispunct( int ch )
{
    return std::ispunct(unsigned char(ch));
}
...
s.erase( std::remove_if(s.begin(), s.end(), &my_ispunct), s.end());
九公里浅绿 2024-11-21 22:44:24

以下内容对我有用。

str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end());
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end());

The following works for me.

str.erase(std::remove_if(str.begin(), str.end(), &ispunct), str.end());
str.erase(std::remove_if(str.begin(), str.end(), &isspace), str.end());
小巷里的女流氓 2024-11-21 22:44:24
void remove_spaces(string data)
{ int i=0,j=0;
    while(i<data.length())
    {
        if (isalpha(data[i]))
        {
        data[i]=data[i];
        i++;
        }
        else
            {
            data.erase(i,1);}
    }
    cout<<data;
}
void remove_spaces(string data)
{ int i=0,j=0;
    while(i<data.length())
    {
        if (isalpha(data[i]))
        {
        data[i]=data[i];
        i++;
        }
        else
            {
            data.erase(i,1);}
    }
    cout<<data;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文