简体   繁体   English

C编程语言中的异常

[英]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. 我正在学习c语言,我碰壁了,如果您想帮助我,我会感激不尽(以下是ex:“写一个程序,将字符从标准输入读取到文件结尾。对于每个字符程序将报告是否为字母。如果为字母,则还应报告其在字母中的数字位置,否则报告为-1。” btw不是作业)。问题在于\\ ni不知道如何制作一个例外。 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 . 我知道您希望非字母字符集中的'\\n'被“排除”,也就是说,它不会产生错误值-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 . 由于您正在使用控制台来运行程序,因此将读取一个字符序列,直到按下ENTER键为止,这将生成字符\\n So, I'm not pretty sure that the while() condition you used, that compares against EOF , it's a good decision of yours. 因此,我不太确定您使用的while()条件是否与EOF相比较,这是您的明智决定。

  • I would put there directly the comparisson against '\\n' . 我直接将与'\\n'的比较。

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

  • To inform if ch is a letter or not, we could use string literals . 要知道ch是否是字母,我们可以使用字符串常量 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 ). 您假设一种编码,其中字母以连续的升序排列 (如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. 该行代码的作用是,仅当ch是小写字母时, ch才会转换为大写。 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()可以带有关该字符的所有信息:

    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 . 如果需要通过与EOF比较来结束输入,则必须将ch的类型更改为int而不是char ,因此可以确保EOF值(即int )正确保存在ch
Finally, this means that ch needs initialization now, for example to a neutral value in the program, as '\\n' . 最后,这意味着ch现在需要初始化,例如在程序中初始化为'\\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. C语言没有例外。 Exceptions were first introduced into programming in C++. 异常首先引入C ++编程中。 You can do it manually in C using setjmp() and longjmp() , but it really isn't worth it. 您可以使用setjmp()longjmp() 在C中手动进行操作 ,但这确实不值得。

The two most popular of doing error handling in C are: 在C中进行错误处理的两种最流行的方法是:

  • Invalid return value. 无效的返回值。 If you can return -1 or some other invalid value from a function to indicate 'there was an error', do it. 如果您可以从函数中返回-1或其他无效值以指示“存在错误”,请执行此操作。 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 . 这就是您要在此处执行的操作-只需返回-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). C没有提供结构化的异常处理(您可以使用setjmp / longjmpsignal / raise进行某种形式的伪造,但这很麻烦,而且很麻烦)。

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. 我很难理解您为什么还要尝试专门处理'\\n' 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 这样,程序依赖于以ASCII编码的特定方式字母

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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