---
# System prepended metadata

title: File I/O

---

# File I/O 
[toc]

## 開啟檔案 

```c=
FILE *fptr;
fptr = fopen("filename.txt" , "mode");
```
### **FILE \*fptr**
- 宣告一個變數，名稱為fptr，類型為FILE
- \* (pointer) 代表fptr指向檔案存取的位址
### **filename.txt**
- 第一個參數代表我們要開啟的檔案，
- 預設路徑為cpp source code存放位址
- 回傳值為該檔案的位址
### **mode**
- 代表我們想要對該檔案執行的動作類型
- 常見類型：

| mode     | meaning | 
|:-------- |:--------| 
| "r"      | **read:**  開啟檔案作為輸入來源  |
| "w"      | **write:** 建立一個新檔案儲存輸出資訊，如果同樣檔名的檔案已經存在，則該檔案內容會被捨棄並被視為一個empty file  |
| "a"     | **append:** 開啟一個檔案做為輸出並在該檔案的最後一行新增輸出資訊。如果該檔案不在則會新增一個檔案  |

## 處理檔案
### 讀取檔案中的字
跟`scanf()`類似，只不過需要多一個參數：file pointer
- fscanf( )
    - ``fscanf(file pointer, “datatype”, data variable)``
    - 從檔案中讀取資料並存在指定類型的變數中
- fgetc( )
    - ``variable = fgetc(filepointer)``
    - 讀取目前filepointer所在位址的一個字元，並回傳該字元
- fgets( )
    - ``fgets(string, num, file pointer)``
    - 讀取目前filepointer所在位址的一串字元，直到讀取了``num-1``個字元為止，並將其作為string儲存

**Example**:
```c=
int main()
{
    FILE *fptr;
    fptr = fopen("input.txt","r");
    
    int num1 = 0, num2 = 0;
    char c1, c2;
    char str[5];
    
    // check whether the file is open
    if(fptr != NULL)
    {
        fscanf(fptr, "%d %d", &num1, &num2);
        printf("%d %d\n", num1, num2);
        
        c1 = fgetc(fptr);
        c2 = fgetc(fptr);
        printf("%c %c\n", c1, c2);
        
        fgets(str, 5 , fptr);
        printf("%s\n", str);
    }
    else
    {
        printf("fail to open 'input.txt'.");
    }
    fclose(fptr);
}
```

### 在檔案上寫字
跟`printf()`類似，只不過需要多一個參數：file pointer
- fprintf()
    - `fprintf(file pointer, “datatype”, data variable)`
    - 在檔案上pointer的位址輸出標準字串
- fputc()
    - `fputc(char, file pointer)`
    - 在檔案上pointer的位址輸出一個字元
- fputs()
    - `fputs(string, file pointer)`
    - 在檔案上pointer的位址輸出一個字串

**Example**:
```c=
int main()
{
    FILE *fptr;
    fptr = fopen("output.txt","w");
    
    int num 25;
    
    // check whether the file is open
    if(fptr != NULL)
    {
        fprintf(fptr,"Below are your message:\n%d\n",num);
        fputc('~',fptr);
        fputs("I want to sleep all day.",fptr);
    }
    else
    {
        printf("fail to open 'output.txt'.");
    }
    fclose(fptr);
}
```
### 重新設置字串位置指標
- fseek()
    - `fseek(file pointer, offset, reference position)`
    - 根據參考位址以及數值，重新設定file pointer位址
     
         | reference position     | meaning     | 
        |:-------------------    |:--------    | 
        | SEEK_SET               | 檔案的開頭    |
        | SEEK_CUR               | 檔案目前的位址 |
        | SEEK_END               | 檔案目前的尾端 |
**Example**:

- 檔案：
<img style="margin:20px auto;padding:1px;border:1px #eee;width:20%;" src="https://i.imgur.com/lvJv3Nk.png" />
- 未使用fseek()
```c=
int main()
{
    FILE *fptr;
    fptr = fopen("input.txt","r");
    
    char c1;
    
    // check whether the file is open
    if(fptr != NULL)
    {
        while(c1 = fgetc(fptr) != EOF)
        {
            c1 = fgetc(fptr);
            printf("%c", c1);
        }
    }
}
```
- 使用fseek()
```c=
int main()
{
    FILE *fptr;
    fptr = fopen("input.txt","r");
    
    char c1;
    
    // check whether the file is open
    if(fptr != NULL)
    {
        while(c1 = fgetc(fptr) != EOF)
        {
            fseek(fptr,-1,SEEK_CUR);
            c1 = fgetc(fptr);
            printf("%c", c1);
        }
    }
}
```
- 輸出：左：未使用`fseek( )`；右：使用`fseek( )`
<img style="margin:28px auto;padding:1px;border:5px #eee;width:40%;" src="https://i.imgur.com/xr6p7ab.png" /> <img style="margin:28px auto;padding:1px;border:5px #eee;width:36%;" src="https://i.imgur.com/BDD8cvX.png" />

## 關閉檔案
### fclose(fptr)
- 關閉檔案
- 釋出記憶體空間
- 不把檔案關閉的話可能會造成fprintf()的異常
:::info
:bulb: 同時開的檔案數量有限，因此我們需要關閉不必要的檔案以節省記憶體空間 
:::

:::success
## :bulb:Exercise 1.
```c=
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE* fptr;
    fptr = fopen("input.txt", "r");
    
    int n=0, m=0;
    char arr[50][50];

    if (fptr != NULL)
    {
    	fscanf(fptr, "%d %d", &n, &m);
    	for (int i = 0; i < n; i++)
        {
		    for (int j = 0; j < m; j++)
		    {
		    	arr[i][j] = 'H';
		    }
		}

		int k;
		fscanf(fptr, "%d", &k);
		int r, c;
		for (int i = 0; i < k; i++)
		{
			fscanf(fptr, "%d %d", &c, &r);
			arr[c][r] = ' ';
		}
	}
	else
	{
		printf("fail to open 'input.txt'.");
	}

	FILE* fptr2;
	fptr2 = fopen("output.txt", "w");
	if (fptr2 != NULL)
	{
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < m; j++)
			{
				fprintf(fptr2, "%c", arr[i][j]);
			}
			fputc('\n', fptr2);
		}
	}
	else
	{
		printf("fail to open 'output.txt'.");
	}
	fclose(fptr2);
}
```
:::
:::info
## :bulb:Homework 1.
```c=
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
	FILE* fptr;
	FILE* fptr2;
	fptr = fopen("input.txt", "r");
	fptr2 = fopen("output.txt", "w");

	int num;
	char spec[15][15],input;
	scanf("%d", &num);
	for (int i = 0; i < num; i++)
	{
		scanf("%s", spec[i]);
	}
	
	int result = 1;
	bool bo = 0;
	if (fptr != NULL && fptr2 != NULL)
	{
		char c;
		while (fgetc(fptr) != EOF)
		{
			char str[15];
			fseek(fptr, -1, SEEK_CUR);
			for(int j=0 ; j<15 ; j++)
			{
				c = fgetc(fptr);
				if (((int)c >= 65 && (int)c <= 90) || ((int)c >= 97 && (int)c <= 122))
				{
					str[j] = c;
				}
				else
				{
					str[j] = '\0';
					if (j == 0)
					{
						fputc(c,fptr2);
						break;
					}
					for (int k = 0; k < num; k++)
					{
						result = strcmp(str, spec[k]);
						if (result == 0)
						{
							
							break;
						}
					}
					if (result == 0)
						fprintf(fptr2, "***%c", c);
					else
						fprintf(fptr2, "%s%c", str, c);
					break;
				}
			}
		}
	}
	else
	{
		printf("Failed to open 'input.txt' or 'output.txt'.");
	}
	fclose(fptr);
	fclose(fptr2);
}

```
:::