当前位置:   article > 正文

C++程序常见错误总结_c++ 多次 排序 为啥报错

c++ 多次 排序 为啥报错

在 C++ 程序设计中,有以下 3 类错误:

  1. 语法错误;
  2. 运行错误;
  3. 语义错误;

我们结合具体案例,来讨论这三种错误。

1. 语法错误

语法错误又分为两类: 编译错误 (Compile error),连接错误 (link error).

前者是编译过程中发生的错误,导致无法生成目标文件,

可能的原因有:分号遗漏或多余,括号不匹配,标识符未定义,访问类的 private 成员等。

后者是生成目标文件后,连接过程中发生错误,是针对有多个源文件的情况,

可能的原因有:全局变量重复定义,函数名冲突等。

根据报错的信息,我们修改代码,再次编译和连接,直到没有语法错误为止。

例如,我们有如下代码段:

  1. #include <stdio.h>
  2. class Cat {
  3. // ...
  4. }
  5. int main() {
  6. cat* pCat = new cat;
  7. delete pCat;
  8. return scanf("%*s");
  9. }

编译会提示,未定义标识符 cat,因为,C++ 严格区分大小写,cat 应该写成 Cat。

另一个案例:

  1. #include <stdio.h>
  2. int main() {
  3. int a = 3;
  4. double b = 2:
  5. printf("%d\n", a % b);
  6. return scanf("%*s");
  7. }

取模运算,只适用于整型数据,而我们对浮点数 b 取摸,因此会报错。

有时候,我们遇到的只是 Warning ,可以生成目标文件,但为了保险,我们还是应该修改代码,尽量达到 0 error, 0 warning。

2. 运行错误 (Runtime error)

运行过程中,程序可能出现错误。这些错误属于运行错误,不会在编译过程中显现。

例如,我们有以下代码:

  1. #include <stdio.h>
  2. int main() {
  3. int a = 1;
  4. int b = 1;
  5. scanf("%d %d", &a, &b);
  6. printf("%d\n", a / b);
  7. return scanf("%*s");
  8. }

如果在运行过程中,输入的第 2 个数为0,则会引发除数为0的异常。

我们可以在做除法前,判断除数是否为 0,从而避免这种异常。

或者使用 try-catch 语句,来处理可能发生的异常。

  1. #include <stdio.h>
  2. int main() {
  3. int a = 1;
  4. int b = 1;
  5. scanf("%d %d", &a, &b);
  6. try {
  7. printf("%d\n", a / b);
  8. }
  9. catch (...) {
  10. printf("Runtime error!\n");
  11. scanf("%*s");
  12. return 1;
  13. }
  14. return scanf("%*s");
  15. }

引发运行错误的原因,不仅有除数为0,还有下标越界,栈溢出等。

下面这段代码, 大家不要轻易运行!

  1. #include <stdio.h>
  2. int main() {
  3. int* p = NULL;
  4. while (true) {
  5. p = new int[1024];
  6. }
  7. return scanf("%*s");
  8. }

它可以通过编译,但运行时会无限开辟内存,导致内存耗尽,发生严重错误。

我在 x64 Win10 系统中运行,约 80s 后出现黑屏,系统无响应的情况。

如果增加 try-catch 机制,则可以及时结束这种局面:

  1. #include <stdio.h>
  2. int main(int argc, char** argv) {
  3. int* p = 0;
  4. try {
  5. while (true) {
  6. p = new int[1024];
  7. }
  8. }
  9. catch (...) {
  10. printf("Runtime error!\n");
  11. scanf("%*s");
  12. return 1;
  13. }
  14. return scanf("%*s");
  15. }

3. 语义错误

这种情况,编译没有报错,运行也没有抛出异常,但是输出的结果不正确。

我们看这个案例:

  1. #include <stdio.h>
  2. #define LEN 8
  3. int main() {
  4. int i = 0;
  5. int* ar = new int[LEN];
  6. for (i = 0; i > LEN; ++i) {
  7. if (1 > scanf("%d", ar + i)) {
  8. scanf("%*s");
  9. }
  10. }
  11. while (--i >= 0) {
  12. printf("%d,", ar[i]);
  13. }
  14. delete[] ar;
  15. return scanf("%*s");
  16. }

第 7 行的 i > LEN 应改为 i < LEN,否则程序不会进入循环,不输出任何内容。

我们再看另一个案例:

  1. #include <stdio.h>
  2. class Date {
  3. private:
  4. int year;
  5. int month;
  6. int day;
  7. public:
  8. Date(int y, int m, int d) {
  9. year = y;
  10. m = month;
  11. day = d;
  12. }
  13. // Other functions...
  14. }
  15. int main() {
  16. Date* date = new Date(2001, 6, 10);
  17. // ...
  18. delete date;
  19. return scanf("%*s");
  20. }

在 Date 的构造函数里,m = month 应改为 month = m;

否则将导致 month 成员没有被初始化,运行结果错误。

如果用严格检查的编译软件,例如 VS 2019,它会在编译时给出 warning,说 month未初始化,从而提示我们,这里可能有错误。

不过,有些语义错误,并不引发 warning ,只在运行过程中表现,很难被察觉。

想要避免这些语义错误,我们就必须认真分析代码。

之后我会总结更多案例。^_^

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/714956
推荐阅读
相关标签
  

闽ICP备14008679号