简体   繁体   中英

Exceptions in c programming language

I'm learning c language and I hit a wall, if you would like to help me I appreciate (here is the ex: "Write a program that reads characters from the standard input to end-of-file. For each character, have the program report whether it is a letter. If it is a letter, also report its numerical location in the alphabet and -1 otherwise." btw is not homework).The problem is with the \\ni don't know how to make it an exception. I'm new around here please let me know if I omitted something. Thank you for your help.

int main(void)
{
    char ch;
    int order;

    printf("Enter letters and it will tell you the location in the alphabet.\n");
    while ((ch = getchar()) != EOF)
    {
        printf("%c", ch);
        if (ch >= 'A' && ch <= 'Z')
        {
            order = ch - 'A' + 1;
            printf(" %d \n", order);
        }
        if (ch >= 'a'  && ch <= 'z')
        {
            order = ch - 'a' + 1;
            printf(" %d \n", order);
        }
        if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
        {
            if (ch == '\n');
            else if (order != (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z'))
                printf(" -1 \n");
        }
    }

    system("pause");
}

You are talking about an "exception" which can be interpreted in other ways in programming.
I understand that you want that '\\n' be "excepted" in the set of nonalphabetical characters, that is, that it doesn't generate the error value -1 .

Since you are using console to run the program, a sequence of character is going to be read till ENTER key is pressed, which generates the character \\n . So, I'm not pretty sure that the while() condition you used, that compares against EOF , it's a good decision of yours.

  • I would put there directly the comparisson against '\\n' .

    while ((ch = getchar()) != '\\n')

  • To inform if ch is a letter or not, we could use string literals . The following use of string assignment would deserve more explanation, but I will omit it. It's valid with string literals :

    char *info; if (order != -1) info = "is a letter"; else info = "is not a letter";

  • You are assuming an encoding where the letters are in contiguous increasing order (as in ASCII ).

  • By assuming that, it's enough to work with uppercase or lowercase letters, since you are only interested in the position that the letter occupy in the alphabet. So, you can choose to work with uppercase, for example, in this way:

    if (ch >= 'a' && ch <= 'z') ch = (ch - 'a' + 'A');

    The effect of that line of code is that ch is converted to uppercase, only if ch is a lowercase letter. Another kind of character is not affected.

    As a consequence, from now on, you only have uppercase letters, or nonalphabetical characters.

  • Then it's easy to code the remaining part:

    if (ch >= 'A' && ch <= 'Z') order = ch - 'A' + 1; // It brings no. position of letter in alphabet else order = -1; // This is the erroneous case

  • A printf() at the end of the loop could bring all the information about the character:

    printf(" %16s: %4d \\n", info, order);

The resulting code is shorter in more clear:

 #include <stdio.h>
 int main(void) {
   char ch;
   int order;
   char *info;

   while ((ch = getchar()) != '\n') {
      printf("%c",ch);

      if (ch >= 'a' && ch <= 'z')   /* Converting all to uppercase */
          ch = (ch - 'a' + 'A');
      if (ch >= 'A' && ch <= 'Z')
          order = ch - 'A' + 1;     /* Position of letter in alphabet */
      else
          order = -1;               /* Not in alphabet */

      if (order != -1)
         info = "is a letter";
      else
         info = "is not a letter";

      printf(" %16s: %4d \n", info, order);
   }
}

If you need to end the input by comparing against EOF , then the type of ch has to be changed to int instead of char , so you can be sure that the EOF value (that is an int ) is properly held in ch .
Finally, this means that ch needs initialization now, for example to a neutral value in the program, as '\\n' .


Finally, just for fun, I add my super-short version:

 #include <stdio.h>
 int main(void) {
   int ch, order;
   while ((ch = getchar()) != '\n') {
      order = (ch>='a' && ch<='z')? ch-'a'+1:((ch>='A' && ch<='Z')? ch-'A'+1: -1);
      printf("%c %8s a letter: %4d \n", ch, (order != -1)? "is":"is not", order);
   }
 }

The C language does not have exceptions. Exceptions were first introduced into programming in C++. You can do it manually in C using setjmp() and longjmp() , but it really isn't worth it.

The two most popular of doing error handling in C are:

  • Invalid return value. If you can return -1 or some other invalid value from a function to indicate 'there was an error', do it. This of course doesn't work for all situations. If all possible return values are valid, such as in a function which multiplies two numbers, you cannot use this method. This is what you want to do here - simply return -1 .
  • Set some global error flag, and remember to check it later. Avoid this when possible. This method ends up resulting in code that looks similar to exception code, but has some serious problems. With exceptions, you must explicitly ignore them if you don't want to handle the error (by swallowing the exception). Otherwise, your program will crash and you can figure out what is wrong. With a global error flag, however, you must remember to check for them; and if you don't, your program will do the wrong thing and you will have no idea why.

First of all, you need to define what you mean by "exception"; do you want your program to actually throw an exception when it sees a newline, or do you simply want to handle a newline as a special case? C does not provide structured exception handling (you can kind-of sort-of fake it with with setjmp / longjmp and signal / raise , but it's messy and a pain in the ass).

Secondly, you will want to read up on the following library functions:

as they will make this a lot simpler; your code basically becomes:

if ( isalpha( ch ) )
{
  // this is an alphabetic character
  int lc = tolower( ch ); // convert to lower case (no-op if ch is already lower case)
  order = lc - 'a' + 1;
}
else
{
  // this is a non-alphabetic character
  order = -1;
}

As for handling the newline, do you want to just not count it at all, or treat it like any other non-alphabetic character? If the former, just skip past it:

// non-alphabetic character
if ( ch == '\n' )
  continue; // immediately goes back to beginning of loop

order = -1;

If the latter, then you don't really have to do anything special.

If you really want to raise an honest-to-God exception when you see a newline, you can do something like the following (I honestly do not recommend it, though):

#include <setjmp.h>
...
jmp_buf try;
if ( setjmp( try ) == 0 ) // "try" block
{
  while ( (ch = getchar() ) != EOF )
  {
    ...
    if ( ch == '\n' )
      longjmp( try, 1 ); // "throw"
  }
}
else
{
  // "catch" block
}

I'm having hard time trying to understand why you even try to handle '\\n' specifically. You might be trying to implement something like this:

int main(void)
{
    char ch;
    int order;

    printf("Enter letters and it will tell you the location in the alphabet.\n");
    while ((ch = getchar()) != EOF)
    {
        printf("%c", ch);
        if (ch >= 'A' && ch <= 'Z') {
            order = ch - 'A' + 1;
            printf(" %d \n", order);
        } else if (ch >= 'a'  && ch <= 'z') {
            order = ch - 'a' + 1;
            printf(" %d \n", order);
        } else if (ch == '\n') { } else {
                printf(" -1 \n");
        }
    }
    system("pause");
}

While this is a good solution, I would recommend rewriting it in a more optimal way:

int main(void)
{
    char ch;

    printf("Enter letters and it will tell you the location in the alphabet.\n");
    while ((ch = getchar()) != EOF)
    {
        int order;
        if (ch != '\n'){
            if (ch >= 'A' && ch <= 'Z' || ch >= 'a'  && ch <= 'z') {
                order = ch & 11111B;
                printf("Letter %d\n", order);
            } else {
                order = -1;
                printf("Not letter: %d\n", order);
            }
        }
    }

    system("pause");
}

This way the program relies on specific way letters coded in ASCII

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