如何更改字符串中的每个字符但不更改 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 ) ) ;
}
我有一个作业要创建一个程序,该程序通过在命令行中输入的一组数字来转换字符串中的每个字符。示例:如果用户在命令行输入 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 ) ) ;
}