如何更改字符串中的每个字符但不更改 C 中的标点符号?

How do I change each char in a string but not change punctuations in C?

我有一个作业要创建一个程序,该程序通过在命令行中输入的一组数字来转换字符串中的每个字符。示例:如果用户在命令行输入 1,然后输入 abc, def,则程序应将字符串转换为 bcd, efg.

我写了程序,但我不知道如何让程序不转换标点符号。

程序当前转换 abc, def 并打印 bcdefg。它需要打印 bcd, efg 并包含标点符号而不转换它们。

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

int main(int argc, string argv[]) //user enter number at cmd prompt

{
    string key = argv[1]; //store user entered number
    int k = atoi(argv[1]); //only accept consecutive digits
    if (argc != 2 || k == 0) 
    {    
        printf("Usage: ./caesar key\n"); /*show error if user enters non-consecutive digits*/
        return 1;
    }
    string original = get_string("Plaintext: "); /* prompt user for message to spin*/

    for (int i = 0, n = strlen(original); i < n; i++)  /* get string length and loop char change*/            
        if (isalnum(original[i])) /* only convert alphanumeric character*/                    
            printf("%c", original[i] + k); /* print and convert character by number entered at prompt*/

    printf("\n");
    return 0;
}

您目前正在做的只是打印字符 + k(如果它是字母数字),否则不打印。你真正想要做的只是添加 k 如果它是字母数字。通过一点布尔逻辑和数学,我们可以完全避免 if 语句。

printf("%c", original[i] + (k * !!isalnum(original[i])));

如果 isalnum return 为真,!! 将使结果值为 1(如果为真,它可以 return 非零值;逻辑上双重否定将如果为真则为 1,如果为假则为 0)。所以现在我们添加 k 如果它是字母数字,否则不添加任何内容,并以任何一种方式打印字符。

您只输出正在转换的字符(isalnum 集中的字符)。您还需要输出未转换的字符。例如:

    char cipher = original[i] ;
    if( isalnum( original[i] )
    {
        cipher += k ;
    }

    printf( "%c", cipher ) ;

然而,所描述的算法在几个方面仍然存在严重缺陷,但不清楚是作业有缺陷(在这种情况下这不是您的问题)还是您对作业的描述不准确。

更实用的解决方案可能如下所示:

#include <ctype.h>

char caesar( char x, int key )
{
    const char alphabet[] = {'a','b','c','d','e','f','g','h',
                             'i','j','k','l','m','n','o','p',
                             'q','r','s','t','u','v','w','x',
                             'y','z',
                             '0','1','2','3','4','5','6','7','8','9'};

    char cipher = x  ;

    for( int i = 0;
         cipher == x && i < sizeof( alphabet );
         i++ )
    {
        if( alphabet[i] == tolower( x ) )
        {
            cipher = alphabet[(i + key) % sizeof( alphabet )] ;
            if( isupper( x ) )
            {
                cipher = toupper( cipher ) ;
            }
        }
    }

    return cipher ;
}

那么你的输出循环将是:

for( int i = 0; original[i] != '[=12=]' ); i++)
{
    printf("%c", ceasar( original[i], k ) ) ;
}