【问题标题】:wraparound c++ for ASCII用于 ASCII 的环绕式 c++
【发布时间】:2019-03-18 18:40:48
【问题描述】:

我是马特,第一次发帖。我现在在学校学习 c++,我被这个问题困住了。我似乎找不到解决方案,所以我正在寻求帮助。

#include <iostream>

using namespace std;

int main()
{
    char ch;

    cin >> ch;

    if(ch <= 122){
        cout << ++ch;
        cout << ++ch;
    }else if (ch > 122){
        cout << static_cast<char>(97)++ch;
        cout << static_cast<char>(97)++ch;
    }
}

该程序非常基础。它需要做的就是输入一个小写字母,程序只需要吐出接下来的两个字符。我的问题是在'z'之后我不知道如何回到'a'。我试过 static_cast 但它说我可以'。我试过重新分配变量,它说我不能。我已经尝试了其他几个基本的东西,但似乎没有一个工作。

提前感谢您的帮助!

【问题讨论】:

  • 先用数字试试。如果我给你25,你知道如何生成26 1吗?
  • try = (char) 'a';
  • 首先,不要使用像 122 和 97 这样的幻数。使用实际的字符值。其次,只需声明一个字符串“abcdefghijklmnopqrstuvwxyz”,并索引到该字符串。这消除了对 122、97 或任何其他数字的需要。不仅如此,在处理 0、1、25 等而不是 122、97 等索引时,您可能会看到如何更轻松地解决问题。
  • @PaulMcKenzie IIRC C++ 标准保证'a'-'z' 将由连续值编码,即使它不是基于 ASCII 的编码(几乎肯定会如此)。因此,您可以安全地使用 'a' 并从中偏移。
  • static_cast&lt;char&gt;(97)++ch 不好,++ 不是中缀运算符。

标签: c++ ascii computer-science word-wrap


【解决方案1】:

这是解决问题的一种方法,既简洁又优雅。使用查找表,使用一些模运算将大写字母转换为小写字母非常易读;它还利用了现代C++ 的一些新功能,例如范围循环。

#include <iostream>
#include <ccytpe>    // needed for ::tolower

int main() {
    // ascii a-z [97,122]

    char alphabet[26] = {}; // 0 initizlize this will be a look up table
    int i = 97;
    for( auto & c : alphabet ) {
        c = static_cast<char>( i );
        i++;
    }
    // check to see if our table is correct
    for( auto & c : alphabet ) {
        std::cout << c << " ";
        std::cout << '\n';
    }
    std::cout << '\n';    
    // Alphabet Seems to be fine.

    char c = {};
    std::cout << "Please enter a lower case character: ";
    std::cin >> c;

    if( c >= 'A' && c <= 'Z' ) {
        ::tolower( c ); // make sure that it's not in caps
    } else if( c >= 'a' && c <= 'z' ) {
        // nothing to do
    } else {
        std::cout << "Error: input value\n";
        return -1;
    }

    // Now that we have the correct inputs we can show your next two characters.
    // Since we know that the ascii table has a range of [97,122] for 
    // lower case letters and that our array index starts at 0; what we can do
    // is a little bit of arithmetic to take the input character and set that
    // to the index value of the array above. Then use the array indexing to 
    // output the next 2 characters. To do this we simply just need to subtract 97 or 'a'
    c = c - 'a';

    // Now we can print the two lines using the adjusted c value with
    // a little bit of modulo arithmetic using the stride, size, or 
    // length of the alphabet.
    int stride = 26;
    std::cout << alphabet[++c % stride] << '\n';
    std::cout << alphabet[++c % stride] << '\n';

    // And we are done!

    return 0;
} 

这就是没有 cmets 和打印整个字母表的代码的代码样子:

#include <iostream>
#include <cctype>

int main() {
    char alphabet[26] = {};
    int i = 97;
    for( auto & c : alphabet ) {
        c = static_cast<char>( i );
        i++;
    }   

    char c = {};
    std::cout << "Please enter a lower case character: ";
    std::cin >> c;

    if( c >= 'A' && c <= 'Z' ) {
        ::tolower( c ); 
    } else if( c >= 'a' && c <= 'z' ) {
        // nothing to do
    } else {
        std::cout << "Error: input value\n";
        return -1;
    }

    c = c - 'a';

    int stride = 26;
    std::cout << alphabet[++c % stride] << '\n';
    std::cout << alphabet[++c % stride] << '\n';

    return 0;
}

【讨论】:

    【解决方案2】:

    (假设输入为:'a' - 'z')

    保持简单

    解决方案 1:

    #include <iostream>
    
    int main()
    {
        char ch = 0;
    
        std::cin >> ch; // "fed a lowercase letter"
    
        // "spit out the next two characters"
        if (ch < 'y')
            std::cout << ++ch << ++ch;
        else if (ch == 'y')
            std::cout << "za";
        else // (ch=='z')
            std::cout << "ab";
    }
    

    解决方案 2:

    #include <iostream>
    
    int main()
    {
        const char * lut = "abcdefghijklmnopqrstuvwxyzab";
        char ch = 0;
    
        std::cin >> ch; // "fed a lowercase letter"
        ch -= 'a'; // lowercase letter to index
    
        // "spit out the next two characters"
        std::cout << lut[++ch] << lut[++ch];
    }
    

    【讨论】:

      【解决方案3】:

      尝试使用以下代码解决您的问题。

      #include <iostream>
      using namespace std;
      
      int main()
      {
          char ch = '\0';
      
          cin >> ch; // "fed a lowercase letter"
      
          char c_next;
          c_next = (ch-'a'+1)%26+'a';
          cout <<c_next;
          c_next = (ch-'a'+2)%26+'a'; 
          cout << c_next;
      
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        首先,不要使用像 122 和 97 这样的幻数。使用实际的字符值。

        其次,只需声明一个字符串abcdefghijklmnopqrstuvwxyz,并索引到该字符串。这消除了对 122、97 或任何其他数字的需要。不仅如此,在处理 0、1、25 等而不是 122、97 等索引时,您可能会看到如何更轻松地解决问题。

        一旦你这样做了,一点点洞察力表明接下来的两个字符将在位置(如果位置从 0 开始)(index + 1) % 26(index + 2) % 26% 是取模运算符,它在除法完成后返回余数。

        例如,如果当前字符是y,则y 位于字符串的第24 位。所以

        (24 + 1) % 26 = 25 % 26 = 25(24 + 2) % 26 = 26 % 26 = 0

        所以接下来的两个字符分别位于位置 25 和位置 0,即za

        再举个例子:z:

        (25 + 1) % 26 = 26 % 26 = 0(25 + 2) % 26 = 27 % 26 = 1

        所以z 之后的下一个字符是ab

        基本上,当您得到一个数据“环绕”为 0 的赋值时,应该立即想到“余数”或“模运算”这个词。


        所以最终的程序应该是这样的:

        #include <iostream>
        int main()
        {
            char ch;
            const char * alphabet = "abcdefghijklmnopqrstuvwxyz";
            std::cin >> ch;
            int position1 = ch - 'a';  // get position of input character
            int position2 = (position1 + 1) % 26;  // get position of next character
            int position3 = (position1 + 2) % 26;  // get position of next next character
        
            // output results  
            std::cout << ch << alphabet[position2] << alphabet[position3];
        }
        

        Live Example

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-02-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多