简体   繁体   中英

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

I have an assignment to create a program that converts each character in a string by a set number entered at the command line. Example: if the user enters 1 at the command line then enters abc, def then the program should convert the string to bcd, efg .

I've written the program but I can't figure out how to get the program to not convert the punctuation characters.

The program currently converts abc, def and prints bcdefg . It needs to print bcd, efg and include the punctuation characters without converting them.

#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;
}

You are only outputting the characters that your are transforming (those that are in the isalnum set). You need to also output the characters not transformed. For example:

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

    printf( "%c", cipher ) ;

However the algorithm as described remains deeply flawed in several ways, but it is not clear whether it is the assignment that is flawed (in which case that is not your problem) or if your description of the assignment is inaccurate.

A more practical solution might look like:

#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 ;
}

Then your output loop would be:

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

What you're currently doing only prints the character + k if it's alpha-numeric, but not printing it otherwise. You you really want to do is only add k if it is alpha-numeric. With a little boolean logic and math, we can avoid the if-statement altogether.

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

If isalnum returns true, !! will make the resulting value 1 (it can return non-zero value if true; double-negating logically will make it either 1 if true or 0 if false). So now we add k if it's alpha-numeric, or add nothing otherwise, and print the character either way.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM