# Error handling

## What is Error handling?

&#x20;    Error handing คือ การจัดการข้อผิดพลาด ซึ่งเป็นความผิดพลาดที่โดยทั่วไปแล้วไม่สามารถจัดการภายในโปรแกรม เมื่อเกิด Error ขึ้นอาจส่งผลให้การทำงานของโปรแกรมล้มเหลว เช่น หน่วยความจำไม่พอ เวอร์ชันการทำงานของ library ไม่ถูกรองรับ การเปิดไฟล์ที่ไม่มีอยู่จริง เป็นต้น จึงต้องมีการเขียน Error handling เพื่อแสดงสาเหตุของข้อผิดพลาดนั้นและทำให้โปรแกรมสามารถทำงานต่อไปได้

## **Different methods of Error handling**

&#x20;    การเขียนโปรแกรมภาษา C ไม่ได้มีการสนับสนุนการจัดการข้อผิดพลาด (Error handling) โดยตรง ผู้ออกแบบโปรแกรมต้องทำการเขียนขึ้นมาเอง โดยการใช้คำสั่ง return ส่งคืนค่า -1 หรือ NULL ในกรณีที่เกิดข้อผิดพลาด และสามารถเขียน Error handling ด้วยการใช้ 'คำสั่ง if' ดังตัวอย่าง การหารด้วย 0 (Divide by Zero Errors) ดังต่อไปนี้

{% hint style="info" %}
&#x20;    สำหรับภาษา C++ จะมีตัวสนับสนุนการจัดการข้อผิดพลาด เรียกว่า Exceptions handling ถึงแม้ว่าจะมีตัวสนับสนุนจัดการข้อผิดพลาด แต่ก็สามารถเขียน Error handling ได้เหมือนภาษา c&#x20;
{% endhint %}

{% tabs %}
{% tab title="Example code C" %}

```c
// err_p1_1.c
#include <stdio.h> 

int solution(int a,int b)
{
    if (b > 0) { 
    
        return a / b; 
    } 

    return -1;
}   

int main() {
    printf("%d\n",solution(102,0));
    printf("%d\n",solution(955,5));
    printf("%d\n",solution(1650,2));     
    return 0;
}
```

{% endtab %}

{% tab title="Example code C++" %}

```cpp
// err_p1_2.cpp
#include <iostream>
using namespace std;

int myFunction(int a,int b) {
    if (b == 0) {
	    return -1;
    }    

    return a/b;
}

int main() {
  cout << myFunction(102,0) << endl;
  cout << myFunction(955,5) << endl;
  cout << myFunction(1650,2) << endl;
  return 0;
} 
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```
-1
191
825
```

{% endtab %}
{% endtabs %}

&#x20;    อย่างที่รู้กันว่าโปรแกรมคอมพิวเตอร์จะไม่สามารถคำนวณค่าที่เกิดจากการหารด้วย 0 เนื่องจากจะส่งผลให้เกิดข้อผิดพลาดในการทำงานและไม่สามารถทำงานต่อไปได้ แต่จากตัวอย่างจะเห็นได้ว่าโปรแกรมสามารถทำงานต่อไปได้ด้วยการเขียน Error handling return ค่า -1&#x20;

&#x20;    ข้อเสียของการส่งค่า return คือ จะทำให้คนอื่นนอกจากผู้ออกแบบโปรแกรมไม่ทราบว่าค่า -1 ที่ถูก return กลับมานั้นเกิดจากสาเหตุอะไร จึงได้มี**การตั้งค่ารหัสตัวแปรส่วนกลาง (Global Variable)** เพื่อระบุว่ารหัสตัวแปรที่ปรากฏเกิดจากสาเหตุอะไร ซึ่งสามารถค้นหารหัสตัวแปรข้อผิดพลาดต่าง ๆ ที่กำหนดไว้จาก <**errno.h**> ที่เป็น header file เรียกวิธีนี้ว่า **Global Variable errno**

### **Global Variable errno**

&#x20;     Global Variable errno ถูกตั้งค่าเป็นตัวแปรส่วนกลางและระบุว่ามีข้อผิดพลาดอะไรที่เกิดขึ้นระหว่างการเรียกใช้ฟังก์ชันใด ๆ ซึ่งสามารถค้นหารหัสตัวแปรข้อผิดพลาดที่กำหนดไว้จาก \<errno.h> **(ภาษา** **C++ สามารถเรียกใช้ได้ทั้งแบบ \<errno.h> และแบบ \<cerrno>)** ดังนั้นโปรแกรมเมอร์สามารถตรวจสอบค่าที่ส่งคืนและสามารถดำเนินการที่เหมาะสมโดยขึ้นอยู่กับค่าที่ส่งคืน ดังตารางต่อไปนี้

![](/files/-MTAxYa9U0ek93CizeGI)

{% hint style="warning" %}
errno value จะไม่มีเลข 0 เนื่องจากเลข 0 หมายถึงไม่มีข้อผิดพลาดในโปรแกรม
{% endhint %}

{% tabs %}
{% tab title="Example code C" %}

```c
// err_p1_3.c
#include <stdio.h> 
#include <errno.h> 
  
int main() 
{ 
    // If a file is opened which does not exist, 
    // then it will be an error and corresponding 
    // errno value will be set 
    FILE * fp; 
  
    // opening a file which does 
    // not exist. 
    fp = fopen("text.txt", "r"); 
  
    printf(" Value of errno: %d\n ", errno); 
  
    return 0; 
} 
```

{% endtab %}

{% tab title="Example code C++" %}

```cpp
// err_p1_4.cpp
#include <iostream>
#include <cerrno>
using namespace std;

int main()
{
    cout << "Attempting file access..." << endl;
    FILE *f = fopen("text.txt","r");
    if (f == NULL)   
    {       
        cout << "Something went wrong! errno : " << errno << endl;
    }
    return 0;
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```
Value of errno: 2
```

{% endtab %}
{% endtabs %}

&#x20;    จากตัวอย่างจะเห็นว่าค่าตัวแปร errno ที่ถูกส่งออกมา คือ 2 หมายความว่า โปรแกรมไม่สามารถเปิดไฟล์ที่ต้องการ เนื่องจากไม่มีไฟล์หรือไดเร็กทอรีดังกล่าว

&#x20;   ข้อเสียของการให้ส่งค่าตัวแปรแสดงข้อผิดพลาดเพียงอย่างเดียว คือจะทำให้เกิดความยุ่งยากในการหาคำอธิบายข้อผิดพลาด ดังนั้นจึงได้มีฟังก์ชัน perror() และ strerror() เข้ามาช่วยในการแสดงข้อผิดพลาด

{% hint style="success" %}
**คำถาม** คำสั่ง FILE \*fp และ fopen คืออะไร

**คำตอบ** เป็นรูปแบบการประกาศแฟ้มข้อมูลและเปิดแฟ้มข้อมูล

ข้อมูลอ่านเพิ่มเติม :: [**พื้นฐานการทำงานของไฟล์** ](http://c-by-step.weebly.com/3614363936573609360036343609358536343619360736353591363436093585363336103652361536213660.html#:~:text=FILE%20*fp%3B,%E0%B8%81%E0%B8%B2%E0%B8%A3%E0%B8%AD%E0%B9%88%E0%B8%B2%E0%B8%99%E0%B8%82%E0%B9%89%E0%B8%AD%E0%B8%A1%E0%B8%B9%E0%B8%A5%E0%B8%88%E0%B8%B2%E0%B8%81%E0%B9%81%E0%B8%9F%E0%B9%89%E0%B8%A1)
{% endhint %}

### perror() and strerror()

* &#x20;perror() ย่อมาจาก print error เป็นฟังก์ชันที่ใช้ในการแสดงข้อความของค่า errno ปัจจุบัน โดยที่สามารถแสดงข้อความที่กำหนดไว้ ก่อนการแสดงข้อผิดพลาด

{% tabs %}
{% tab title="Syntax" %}

```cpp
void perror (char*msg);
  msg คือ ข้อความแบบกำหนดเองก่อนการแสดงข้อผิดพลาด
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Example code C" %}

```c
// err_p1_5.c
// C program to illustrate the 
// use of perror() 
#include <errno.h> 
#include <stdio.h> 
#include <stdlib.h> 
  
// Driver Code 
int main() 
{ 
    FILE* fp; 
  
    // Now try to open same file 
    fp = fopen("file.txt", "r"); 
  
    if (fp == NULL) { 
  
        perror("Error: "); 
        return (-1); 
    } 
  
    // Close the file pointer 
    fclose(fp); 
  
    return (0); 
}
```

{% endtab %}

{% tab title="Example code C++" %}

```cpp
// err_p1_6.cpp
// C++ program to illustrate the 
// use of perror() 
#include <iostream>
#include <errno.h> 
  
// Driver Code 
int main() 
{ 
    FILE* fp; 

    fp = fopen("file.txt", "r"); 
  
    if (fp == NULL) { 
  
        perror("Error: "); 
        return (-1); 
    } 
  
    // Close the file pointer 
    fclose(fp); 
  
    return (0); 
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="output" %}

```cpp
Error: : No such file or directory
```

{% endtab %}
{% endtabs %}

* strerror() คือ ฟังก์ชันที่ใช้รับค่าตัวแปรของ errno เพื่อ return ข้อมูลประเภท string มาแสดงผลข้อผิดพลาด

{% tabs %}
{% tab title="Example code C" %}

```c
// err_p1_7.c
// C program to illustrate the 
// use of strerror() 
#include <errno.h> 
#include <stdio.h> 
#include <string.h> 
  
// Driver Code 
int main() 
{ 
    FILE* fp; 
  
    fp = fopen("file.txt", "r"); 
  
    if (fp == NULL) { 
  
        printf("Value of errno: %d\n ", errno); 
        printf("The error message is : %s\n",strerror(errno)); 
        return (-1); 
    } 
  
    // Close the file pointer 
    fclose(fp); 
  
    return (0); 
}

```

{% endtab %}

{% tab title="Example code C++" %}

```cpp
// err_p1_8.cpp
// C++ program to illustrate the 
// use of strerror() 
#include <iostream>
#include <cerrno>
#include <string.h>
using namespace std; 
  
// Driver Code 
int main() 
{ 
    FILE* fp; 
  
    // Now try to open same file 
    fp = fopen("file.txt", "r"); 
  
    if (fp == NULL) { 
  
        cout <<"Value of errno: " << errno << endl; 
        cout << "The error message is : " << strerror(errno) << endl;
        return (-1); 
    } 
  
    // Close the file pointer 
    fclose(fp); 
  
    return (0); 
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```
Value of errno: 2
The error message is : No such file or directory
```

{% endtab %}
{% endtabs %}

{% hint style="info" %}
&#x20; นอกจากนี้ยังมีฟังก์ชัน ferror() และ clearerr() ที่ใช้ในการตรวจจับข้อผิดพลาดในการ stream   &#x20;

ศึกษาเพิ่มเติม :: [Error handling during file operations in C/C++](https://www.geeksforgeeks.org/error-handling-during-file-operations-in-c-c/?ref=rp)
{% endhint %}

### Exit Status

&#x20;    Exit Status จะต่างจาก errno, perror() และ strerror() ที่เป็นการแสดงผลข้อผิดพลาด เพื่อให้โปรแกรมสามารถทำงานต่อไปได้ แต่ Exit Status เป็นคำสั่งที่ใช้ในการออกจากโปรแกรม แบ่งออกเป็น 2 ประเภท คือ Exit Success และ Exit Failure ซึ่งต้องทำการ include  ก่อน จึงจะสามารถใช้คำสั่ง exit()

&#x20;    1\. Exit Success คือ การออกจากโปแกรมที่ไม่เกิดข้อผิดพลาด สามารถเลือกใช้ได้ 2 แบบ ดังต่อไปนี้

{% tabs %}
{% tab title="Syntax" %}

```
exit(EXIT_SUCCESS)
exit(0)
```

{% endtab %}
{% endtabs %}

{% hint style="danger" %}
สร้างไฟล์ file.txt ก่อน run code ดังต่อไปนี้
{% endhint %}

{% tabs %}
{% tab title="Example code C" %}

```c
// err_p2_1.c
#include <stdio.h> 
#include <stdio.h> 
  
int main() 
{ 
    FILE* file; 
  
    // opening the file in read-only mode 
    file = fopen("file.txt", "r"); 
  
    printf("File opening successful!"); 
  
    // EXIT_SUCCESS 
    exit(0); 
}
```

{% endtab %}

{% tab title="Example code C++" %}

```cpp
// err_p2_2.cpp
#include <iostream>
#include <stdlib.h>
using namespace std;
  
int main() 
{ 
    FILE* file; 
  
    // opening the file in read-only mode 
    file = fopen("myFile.txt", "r"); 
  
    cout << "File opening successful!" << endl; 
  
    // EXIT_SUCCESS 
    exit(0); 
}
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Output" %}

```
File opening successful!
```

{% endtab %}
{% endtabs %}

&#x20;    2\. Exit Failure คือ การออกจากโปรแกรมที่เกิดข้อผิดพลาด สามารถเลือกใช้ได้ 2 แบบ ดังต่อไปนี้

{% tabs %}
{% tab title="Syntax" %}

```
exit(EXIT_FAILURE)
exit(1)
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Example code C" %}

```c
// err_p2_3.c
#include <stdio.h> 
#include <stdlib.h>
  
int main() 
{ 
    FILE* file; 
  
    // open the file in read-only mode 
    file = fopen("myFile.txt", "r"); 
  
    if (file == NULL) { 
        printf("Error in opening file\n"); 
  
        // EXIT_FAILURE 
        exit(1); 
    } 
  
    // EXIT_SUCCESS 
    exit(0); 
} 
```

{% endtab %}

{% tab title="Example code C++" %}

```cpp
// err_p2_4.cpp
#include <iostream>
#include <stdlib.h>
using namespace std;
  
int main() 
{ 
    FILE* file; 
  
    // open the file in read-only mode 
    file = fopen("myFile.txt", "r"); 
  
    if (file == NULL) { 
        cout << "Error in opening file" << endl; 
  
        // EXIT_FAILURE 
        exit(1); 
    } 
  
    // EXIT_SUCCESS 
    exit(0); 
} 
```

{% endtab %}
{% endtabs %}

{% hint style="warning" %}
&#x20;   สำหรับ exit(EXIT\_FAILURE) สามารถใช้จำนวนเต็มอื่นที่ไม่ใช่ 1 เพื่อระบุข้อผิดพลาดประเภทต่างๆ
{% endhint %}

แหล่งอ้างอิง ::

* .<https://www.tutorialspoint.com/cprogramming/c_error_handling.htm>
* <https://www.geeksforgeeks.org/error-handling-c-programs/>
* <https://en.cppreference.com/w/cpp/header/cerrno>


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.aic-eec.com/c-c++-for-embedded-programming/error-handling.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
