【问题标题】:C Programming - How to change every occurrence of character in a string with another characterC 编程 - 如何用另一个字符更改字符串中每个出现的字符
【发布时间】:2022-01-04 02:18:39
【问题描述】:

任务是让用户插入一个字符串,程序将输出一条秘密消息,该消息将该字符串中的每个字符更改为另一个字符。将插入的新字符列表由排列“qjczieaungsdfxmphybklortvw”给出,它对应于字母表的每个字母。例如,字符串“abcxyz”将返回“qjctvw”。程序会忽略符号和大写字母,所以“Abc”会变成“Ajc”。

我试图通过将字符串的每个位置与字母表中的每个字母进行比较来实现这一点。如果匹配,则字符串的该位置将被与传统字母表位置相同的秘密排列位置替换(因为它们对应)。该代码在技术上有效,但我没有得到正确的值。例如,对于每个“a”,我应该得到一个“q”,但返回的是一个“h”。如果有人能修复我的代码,将不胜感激。

下面的代码:请复制并粘贴到您喜欢的代码编辑器中,看看我返回错误值的意思。

#include <string.h>
#define MAX_STR_LEN 256
int main(void)
{
  char perm[] = "qjczieaungsdfxmphybklortvw";
  char alphabet[] = "abcdefghijklmnopqrstuvwxyz";
  int i, j;
  char msg[MAX_STR_LEN+1];

  /* read the message from the terminal using fgets. The variable msg will contain the message. */
  fgets(msg, MAX_STR_LEN, stdin);

/*compares each value of the string to the alphabet*/
  for (i = 0; i < (strlen(msg) - 1); i++) {
    for (j = 0; j < (strlen(alphabet) - 1); j++) {
       if (msg[i] == alphabet[j]) {msg[i] = perm[j];}
     }
  }
  printf("%s", msg);
}

【问题讨论】:

  • 有一种更简单的方法来进行替换。将内部循环替换为:msg[i] = perm[msg[i] - 'a'];。也就是说,将每个输入字母变基以将索引直接放入perm。处理大写字母、意外输入和其他错误情况留作练习。
  • 如果你想让你的版本正常工作,那么你需要在if 块内添加一个break。否则它将继续尝试替换已经替换的字母。

标签: c char c-strings fgets substitution


【解决方案1】:

对于拨打fgets之后的初学者

fgets(msg, MAX_STR_LEN, stdin);

您需要删除该函数可以附加到输入字符串的换行符'\n'

msg[ strcspn( msg, "\n" ) ] = '\0';

for 循环也不正确。

至少不是使用条件

j < (strlen(alphabet) - 1)

在for循环内部

 for (j = 0; j < (strlen(alphabet) - 1); j++) {
   if (msg[i] == alphabet[j]) {msg[i] = perm[j];}
 }

你需要使用条件

j < strlen(alphabet)

当在字符串alphabet 中找到一个字符时,您必须退出循环。否则已经改变的字符可以被第二次改变。

您可以使用函数strchr 代替手动编写的内部for 循环。例如

/*compares each value of the string to the alphabet*/
for ( size_t i = 0; msg[i] != '\0';  i++ ) 
{
    const char *p = strchr( alphabet, msg[i] );

    if ( p != NULL )
    {
        msg[i] = perm[p - alphabet];
    }
}

这是您的更新程序。

#include <stdio.h>
#include <string.h>

#define MAX_STR_LEN 256

int main( void )
{
    const char *perm= "qjczieaungsdfxmphybklortvw";
    const char *alphabet= "abcdefghijklmnopqrstuvwxyz";
    char msg[MAX_STR_LEN+1];
    
    /* read the message from the terminal using fgets. The variable msg will contain the message. */
    fgets( msg, MAX_STR_LEN, stdin );
    
    msg[ strcspn( msg, "\n" ) ] = '\0';
    
    /*compares each value of the string to the alphabet*/
    for ( size_t i = 0; msg[i] != '\0';  i++ ) 
    {
        const char *p = strchr( alphabet, msg[i] );

        if ( p != NULL )
        {
            msg[i] = perm[p - alphabet];
        }
    }
    
    puts( msg );
}

如果要输入字符串

abcxyz

那么程序输出是

qjctvw

【讨论】:

    【解决方案2】:

    一旦您找到问题的根源并观察到这一点,这项任务就会变得非常容易:

    1. 您的字母替换字符串只是一个简单的数组,其字母值映射到从 0 到 25 的索引。
    2. 字符本身有一些由 ASCII 标准指定的整数值,它们恰好是连续的('b'=='a'+1)

    有了这些知识,我们就可以发明一个函数,它接收一个字符并将其转换到perm 字符串中的正确位置。我们可以通过非常简单的方式做到这一点,只需从我们拥有的任何字符中减去'a''a'-'a' 将等于 0,以此类推。

    这可以实现为这样的函数:(或者您可以内联它,因为它非常简单)

    int get_char_index(char c){
        return c - 'a';
    }
    

    现在,可以访问这个函数,我们需要做的就是逐个字符地迭代一个字符串(for循环,while循环,没关系),从字符串中读取字符,将它提供给函数,然后一旦得到perm的对应索引,只需将该索引下的char的值赋回字符串即可。

    int main() {
        const char perm[] = "qjczieaungsdfxmphybklortvw";
        
        char some_string_to_convert[] = "aabbccddeeffgghhiijjkkllmmnnoopprrssttqqvvwhatever";
        for(int i=0; i<strlen(some_string_to_convert); i++){
            char c = some_string_to_convert[i];
            int perm_index = get_char_index(c);
            some_string_to_convert[i] = perm[perm_index];
        }
    
        printf("%s", some_string_to_convert);
    }
    
    

    以下代码输出: qqjjcczziieeaauunnggssddffxxmmppyybbkkhhooruqkioiy

    希望我的回答能帮助你解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 2020-03-13
      • 1970-01-01
      • 2010-11-16
      相关资源
      最近更新 更多