代码之家  ›  专栏  ›  技术社区  ›  Ryon

使用C字符串和指针。删除除小写和空格外的所有字符

  •  1
  • Ryon  · 技术社区  · 7 年前

    我们被要求创建一个程序,该程序将删除给定字符串中除小写字母和空格外的所有字符(使用指针)。

    例子:

    输入字符串:嗨,北面有#20个标记点。

    输出:i有标记点

    到目前为止,我得到的是:

    #include <iostream>
    #include <cstring>
    #include <cctype>
    
    void lowerCase(char *text);
    
    int main()
    {
        char str[100];
        std::cout << "Enter a string: ";
        std::cin.getline(str, 100);
        lowerCase(str);
        std::cout << "\nOutput after lowerCase():\n";
        std::cout << str;
    
        system("pause>0");
        return 0;
    }
    
    void lowerCase(char *text)
    {
        while (*text != '\0') {
            if (((unsigned int)*text >= 97 && (unsigned int)*text <= 122) || *text == ' ') {
                text++;
            }
            else {
                for (char *i = text; *i != '\0'; i++) {
                    *i = *(i + 1);
                }
                text++;
            }
        }
    }
    

    此代码的输出为:

    输入字符串:嗨,北面有#20个标记点。

    小写()后的输出:

    i有2个标记点需要OT。

    如何在示例中获得结果?

    3 回复  |  直到 4 年前
        1
  •  2
  •   frslm    7 年前

    您的功能 lowerCase() 跳过应删除的连续字符;如果在逻辑上跟踪else块,可以看到这一点:

    else {
        for (char *i = text; *i != '\0'; i++) {
            *i = *(i + 1);
        }
        text++; // <- this always skips the next character
    }
    

    你不需要 text++ 在else块中,自 *i = *(i + 1) 已将下一个字符复制到 text .

        2
  •  1
  •   Jeffrey    7 年前

    你应该从头开始@frslm向您展示了这个问题,但正如许多其他人指出的那样,这不是称职教师的方式。

    考虑一下这一点:

    • 创建返回字符串。
    • 扫描输入字符串。
    • 对于每个角色,决定是否保留它。
    • 如果保留它,请将其附加到返回字符串中。
    • 返回返回字符串。

    而且

    • 不要硬编码97和122。使用“a”、“z”或is\u lower()或等。。。

    您的代码将更强大、更易于维护、更好。

        3
  •  1
  •   Remy Lebeau    7 年前

    当您决定从字符串中删除一个字符时,您可以将其余字符向左移动一个位置,这很好,但是您可以在移动字符开始后的位置跳过该字符,而不管其实际值是什么。这就是为什么您在输出中看到不需要的字符。只需在移位后不增加指针,例如:

    #include <iostream>
    #include <cstring>
    #include <cctype>
    
    void removeIfNotLowercaseOrWhitespace(char *text);
    
    int main()
    {
        char str[100];
    
        std::cout << "Enter a string: ";
        std::cin.getline(str, 100);
    
        removeIfNotLowercaseOrWhitespace(str);
    
        std::cout << "\nOutput after lowerCase():\n";
        std::cout << str;
    
        std::system("pause>0");
        return 0;
    }
    
    void removeIfNotLowercaseOrWhitespace(char *text)
    {
        while (*text != '\0') {
            if (std::islower(*text) || std::isspace(*text)) {
                ++text;
            }
            else {
                for (char *i = text; *i != '\0'; ++i) {
                    *i = *(i + 1);
                }
            }
        }
    }
    

    然而,尽管如此,这种方法确实是C的做事方式!因为您显然在使用C++,所以C++的方法是 std::string 具有 C++ standard library algorithms 喜欢 std::remove_if() (使用所谓的 Erase-Remove idiom ):

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <cctype>
    
    bool isNotLowercaseOrWhitespace(char c);
    
    int main()
    {
        std::string str;
    
        std::cout << "Enter a string: ";
        std::getline(std::cin, str);
    
        str.erase(
            std::remove_if(str.begin(), str.end(),
                isNotLowercaseOrWhitespace
                /* alternatively, in C++11 and later:
                [](char c){ return !(std::islower(c) || std::isspace(c)); }
                */
            )
        );
    
        std::cout << "\nOutput after lowerCase():\n";
        std::cout << str;
    
        std::cin.get();
        return 0;
    }
    
    bool isNotLowercaseOrWhitespace(char c)
    {
        return !(std::islower(c) || std::isspace(c));
    }
    

    或者,制作一个新的 标准::字符串 包含要保留的字符的副本,例如:

    #include <iostream>
    #include <string>
    #include <algorithm>
    #include <cctype>
    
    std::string removeAllNotLowercaseOrWhitespace(const std::string &s);
    
    int main()
    {
        std::string str;
    
        std::cout << "Enter a string: ";
        std::getline(std::cin, str);
    
        str = removeAllNotLowercaseOrWhitespace(str);
    
        std::cout << "\nOutput after lowerCase():\n";
        std::cout << str;
    
        std::cin.get();
        return 0;
    }
    
    std::string removeAllNotLowercaseOrWhitespace(const std::string &str)
    {
        std::string ret;
        ret.reserve(str.size());
    
        for(std::string::const_iterator iter = str.begin(); iter != str.end(); ++iter) {
            char c = *iter;
            if (std::islower(c) || std::isspace(c)) {
                ret.push_back(c);
            }
        }
        /* alternatively, in C++11 and later:
        std::copy_if(str.begin(), str.end(), std::back_inserter(ret),
            [](char c){ return (std::islower(c) || std::isspace(c)); }
        );
        */
    
        return ret;
    }