Home > Enterprise >  In C, How can I check an array for only ASCII defined Letters Without using tons of If Statements?
In C, How can I check an array for only ASCII defined Letters Without using tons of If Statements?

Time:12-28

I'm trying to make sure that the array entered at the command line is only letters, Capital and lowercase.

If it is numbers or anything else then I want to end the program.

Now, I know I can do this with tons of if statements to see:

if it is between this and that

else this and that

else this and that.

But I would like to try and learn a more efficient way to do this because I'm sure there is one with a for loop I just havent figured it out. I ask because I want the user to enter a key that is x amount long. And to achieve the desired / required string length I used a similar method of multiple if else statements.

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


int validate_key(int argc, string argv[]);

int main(int argc, string argv[])
{
    string input;
    int score;

    score = validate_key(argc, argv);

    if (score == 0)
    {
       // if required key is valid, next function of program here

       
    }

}

int validate_key(int argc, string argv[])
{

    //KEY VALIDATION 
    int l = 0; //initialize length variable
    string s;

    //To make sure that the string entered at command line is the required 26 characters, 
   //and that it isnt empty

    if (argc == 2) //make sure there are no spaces in the entered string
    {
        s = argv[1];     //assign key to string s
        l = strlen(s);   //check length of KEY

    }

    //check to see string isnt NULL / empty
    if (argc !=0 && l == 26) 
    {


        //make a for loop that scans the array making sure it is between two values? 
       //attempting to check argv to make sure it is a lowercase and or uppercase string 

         for (int i = 0; i < l; i  )
            {
                int charValue = argv[1][i];

                if ( ( charValue > 64 && charValue < 91 ) || ( charValue > 96 && charValue < 123 ) )
                {

                    printf("%c\n", charValue); //to show me that it made it into the if statement
                }
                else

                return 1;
            }


        return 0;

    }
    else if (l <= 25 && l >= 1) //entered key is too small
    {
        printf("Please Enter 26 Letter Key \n");
        printf("value of l: %d\n", l);

        return 1;
    }

    else //entered key is empty
    {
       //printf("value of l: %d\n", l);

        printf("missing command-line argument\n");

        return 1;

    }

}

CodePudding user response:

Use isalpha():

7.4.1.2 The isalpha function

Synopsis

      #include <ctype.h>
      int isalpha(int c);

Description

The isalpha function tests for any character for which isupper or islower is true, or any character that is one of a locale-specific set of alphabetic characters for which none of iscntrl, isdigit, ispunct, or isspace is true.200) In the "C" locale, isalpha returns true only for the characters for which isupper or islower is true.

In your code:

     for (int i = 0; i < l; i  )
        {
            // see notes below regarding the cast
            int charValue = ( unsigned char ) argv[1][i];

            if ( isalpha( charValue ) )
            {

                printf("%c\n", charValue); //to show me that it made it into the if statement
            }
            else

            return 1;
        }

Note, though, that the value passed must be representable as an unsigned char:

The header <ctype.h> declares several functions useful for classifying and mapping characters. In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

CodePudding user response:

The basic operation will always be to iterate over the characters in the input string and check whether they are that what you want them to be: uppercase or lowercase letters. There are some functions that make it more convenient for you to code.

To avoid coding the ASCII number ranges yourself, you can use the C standard function isalpha() to check a single character whether it is a letter.

You could also use the strcspn function to find the number of matching characters at the start of your string. Your matching set can be a string with all the ASCII letters. If the returned length is the length of the whole string, there were no other characters in it. If the returned length is less than the length of the string, then there is a non-letter character... This is probably less efficient for the computer because strcspn does not simply check whether the characters are in a range, but whether the characters appear in the matching string.

CodePudding user response:

The particular question was in regard of testing for non-alphabetic characters.
There are already two quality answers referring you to isalpha().

The meta- question is "how can I write less code?"

The following (using isalpha()) is offered as a teaching example that performs the same function as the OP code above. By compacting the code to fewer lines, a reader is able to scan its operation without scrolling. Unused variables such as input and s are quick to find and expunge.

#include <stdio.h>
#include <string.h>
#include <cs50.h> // Missing from OP code

// defining the function ahead of its use. Definition is its own prototype.
int unique26( string arg ) {
    int i = 0;
    // test all alpha and is exactly 26 chars long
    while( isalpha( (unsigned char) arg[i] ) i  ;
    if( i != 26 || arg[i] )
        return 0; // bad

    // test no duplications in the sample
    for( i = 0; arg[i]; i   )
        for( int j = i   1; arg[j]; j   )
            if( arg[j] == arg[i] )
                return 0; // bad

    return 1; // good
}

int main( int argc, string argv[] )
{
    if( argc != 2 || !unique26( argv[1] ) )
    {
        printf( "Usage: %s <key (26 unique alphabetic chars> \n", argv[0] );
        return 1;
    }

    // more code here

    return 0;
}

I'd be happy to answer any questions this example code.

EDIT:
To write even less code, the function unique26() could use strchr(), a tested and proven function from what is called "the C string library".

int unique26( string arg ) {
    int i = 0;
    while( isalpha( (unsigned char) arg[i] ) i  ;
    if( i != 26 || arg[i] )
        return 0; // bad

    // test no duplications in the sample
    for( i = 1; arg[i] && strchr( &arg[i], arg[i-1] ) == NULL; i   ) {}
    return arg[i] == '\0;
}

It's good to be aware of library functions, even if you may not have use for some... until you do.

  • Related