LeetCode C++ String to Integer (atoi) 字串轉整數

今天要練習的 LeetCode 題目是 String to Integer (atoi) 字串轉整數,並且以 C++ 實作出來。

LeetCode 題目

https://leetcode.com/problems/string-to-integer-atoi/
難度:Medium

String to Integer (atoi) 是 LeetCode 題目的第 8 題,

題目是實作一個字串轉整數,有一些需求,

  • 要能夠忽略空白開頭。
  • 能處理 '-', '+' 符號。
  • 如果數字超過 32 bit 長度,則回傳最大數值,大於 2^31-1 回傳 2147483647,小於 -2^31 則回傳 -2147483648。

解題思路

先把字串前面出現的空白都忽略,直到遇到第一個出現的 '-', '+' 符號或數字,然後紀錄正負號,如果是負號開頭的話就在 sign 變數設定為 -1 記錄一下,最後的數字再乘上 sign 即可,接著忽略 0 開頭的數字。

主要邏輯為一個 while 迴圈去使用 isdigit 判斷每個字元是不是數字,該字元是數字的話就將字元減去 '0' 就可以得到數字,然後將該數字再加上之前的 sum * 10,最後整個 while 迴圈會遇到 '\0' 結束字元時 isdigit 會判斷成不是數字進而終止 while 迴圈,最後再將 sum 乘上 sign 變數就可以回傳最終結果。

針對 32 bit 整數邊界進行處理,大於 2147483647 回傳 2147483647,小於 -2147483648 則回傳 -2147483648,另外輸入是超長的數字字串是 long 存不下的話,也會針對 len 長度太長進行邊界處理。

答案

以下為 C++ String to Integer (atoi) 的 solution

cpp-string-to-integer-atoi.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// g++ cpp-string-to-integer-atoi.cpp -o a.out
#include <iostream>
#include <string>
using namespace std;

class Solution {
public:
int myAtoi(string s) {
long sum = 0;
int i = 0;
int sign = 1;

while (isspace(s[i])) { i++; }

if (s[i] == '-') {
sign = -1;
i++;
} else if (s[i] == '+') {
i++;
}

while (s[i] == '0') { i++; }

int len = 0;
while (isdigit(s[i])) {
sum = sum * 10 + s[i] - '0';
i++;
len++;
if (len > 10)
break;
}

sum = sum * sign;
if (sum > 2147483647)
return 2147483647;
else if (sum < -2147483648)
return -2147483648;
else
return sum;
}
};

int main() {
Solution s;
string s1 = "123";
cout << s.myAtoi(s1) << "\n";
string s2 = "0032";
cout << s.myAtoi(s2) << "\n";
string s3 = "4193 with words";
cout << s.myAtoi(s3) << "\n";
string s4 = " -42";
cout << s.myAtoi(s4) << "\n";
string s5 = "-91283472332";
cout << s.myAtoi(s5) << "\n";
string s6 = "+1";
cout << s.myAtoi(s6) << "\n";
string s7 = "20000000000000000000";
cout << s.myAtoi(s7) << "\n";
string s8 = " 0000000000012345678";
cout << s.myAtoi(s8) << "\n";
string s9 = "00000-42a1234";
cout << s.myAtoi(s9) << "\n";
return 0;
}

參考
String to Integer (atoi) - LeetCode
https://leetcode.com/problems/string-to-integer-atoi/
字符串转换整数 (atoi) (String to Integer (atoi)) - 力扣 (LeetCode)
https://leetcode-cn.com/classic/problems/string-to-integer-atoi/description/

其它相關文章推薦
C/C++ 新手入門教學懶人包
LeetCode C++ two sum 兩數之和
LeetCode C++ Range Sum Query - Immutable 區域和檢索

C/C++ fclose 用法與範例

本篇 ShengYu 介紹 C/C++ fclose 的用法與範例,檔案的讀取或寫入都需要先開檔,有開檔就有關檔,fopen 開檔對應的關檔函式就是 fclose 。

C/C++ 要使用 fclose 的話需要引入的標頭檔 <stdio.h>,如果要使用 C++ 的標頭檔則是引入 <cstdio>
fclose 函式原型為

1
int fclose(FILE * stream);

stream:指向 FILE 物件的指標

以下 C/C++ fclose 的用法介紹將分為這幾部份,

  • C/C++ fclose 的基本用法
  • C/C++ fclose 正確的關檔

那我們開始吧!

C/C++ fclose 的基本用法

這邊介紹 C/C++ fclose 基本用法,fopen 開檔成功回傳不為 NULL,fopen 開檔失敗則會回傳 NULL,開檔成功的話就繼續處理之後的程式邏輯,接著使用 fputs 進行寫入字串,fputs 會將字串寫入直到遇見結束字元為止,最後再 fclose 關檔,

cpp-fclose.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// g++ cpp-fclose.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;

fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fputs("hello world\n", fp);
fputs("123", fp);
fputs("456", fp);
fclose(fp);
return 0;
}

輸出 output.txt 的內容如下,

1
2
hello world
123456

那麼為什麼開檔失敗就不用 fclose 關檔呢?詳見下一節。

C/C++ fclose 正確的關檔

這邊介紹 C/C++ fclose 正確的關檔方式與技巧,實務上有一些情況可能會導致 fp 為 NULL 而讓 fclose 對 NULL 進行關檔,例如開檔失敗,或其它手動賦值為 NULL 等等情形,那 fclose 對 NULL 進行關檔發生什麼事呢?

這邊示範 fclose 直接對 NULL 關檔看看會怎麼樣,

cpp-fclose2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
// g++ cpp-fclose2.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;

fp = NULL;

// fputs("123", fp); // crash if fp is NULL
fclose(fp); // crash if fp is NULL

return 0;
}

結果程式會中止,產生 Segmentation fault,輸出如下,另外 fputs 寫入到 NULL 的 FILE * 檔案指標也是同樣的結果,

1
Segmentation fault (core dumped)

所以在 fclose 關檔時帶入的 FILE * 檔案指標是 NULL 的話就會造成很嚴重的後果,在程式撰寫時要特別小心注意。

以上就是 C/C++ fclose 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ fopen 用法與範例
C/C++ fread 用法與範例
C/C++ fgets 用法與範例
C/C++ fwrite 用法與範例
C/C++ fputs 用法與範例

C/C++ fputs 用法與範例

本篇 ShengYu 介紹 C/C++ fputs 的用法與範例,C/C++ fputs 將字串寫到 stream 裡直到遇見結束字元才停止,fputs 除了可以將字串寫入到檔案裡以外也能將字串寫入到標準輸出上,詳見本篇範例。

C/C++ 要使用 fputs 的話需要引入的標頭檔 <stdio.h>,如果要使用 C++ 的標頭檔則是引入 <cstdio>
fputs 函式原型為

1
int fputs(const char * str, FILE * stream);

str:存放字串的地方,將會被輸出到 stream
stream:指向 FILE 物件的指標

以下 C/C++ fputs 的用法介紹將分為這幾部份,

  • C/C++ fputs 寫入字串到檔案的基本用法
  • C/C++ fputs 寫入字串到標準輸出

那我們開始吧!

C/C++ fputs 將字串寫入到檔案的基本用法

這邊介紹 C/C++ fputs 寫入文字檔的基本用法,在用 fputs 來寫入文字檔前要先 fopen 開檔成功才能對檔案寫入,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功。

接著使用 fputs 進行寫入字串,這邊示範將 "123""456\n""hello world" 等字串寫入文字檔裡,fputs 會將字串寫入直到遇見結束字元為止,寫完後最後 fclose 關檔,

cpp-fputs.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// g++ cpp-fputs.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;

fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fputs("123", fp);
fputs("456\n", fp);
fputs("hello world", fp);
fclose(fp);
return 0;
}

輸出 output.txt 的內容如下,

1
2
123456
hello world

C/C++ fputs 將字串寫入到標準輸出

C/C++ fputs 除了對檔案寫入字串以外也可以用來對標準輸出進行寫入字串,範例如下,標準輸出為 stdout 就不需要像檔案一樣開檔了,

cpp-fputs2.cpp
1
2
3
4
5
6
7
8
9
// g++ cpp-fputs2.cpp -o a.out
#include <stdio.h>

int main() {
fputs("hello world\n", stdout);
printf("123456\n");

return 0;
}

標準輸出如下,

1
2
hello world
123456

以上就是 C/C++ fputs 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ fopen 用法與範例
C/C++ fread 用法與範例
C/C++ fgets 用法與範例
C/C++ fwrite 用法與範例
C/C++ fclose 用法與範例

C/C++ fwrite 用法與範例

本篇 ShengYu 介紹 C/C++ fwrite 的用法與範例,C/C++ 可以使用 fwrite 將文字寫入到檔案裡,在 fwrite 函式的引數裡可以指定要寫入幾個 bytes 字元,fwrite 除了可以將文字寫入到檔案裡以外也能將文字寫入到標準輸出上,詳見本篇範例。

C/C++ 要使用 fwrite 的話需要引入的標頭檔 <stdio.h>,如果要使用 C++ 的標頭檔則是引入 <cstdio>
fwrite 函式原型為

1
size_t fwrite(const void * ptr, size_t size, size_t count, FILE * stream);

ptr:指向一塊元素陣列的指標,該元素陣列將會被寫入到檔案裡
size:要寫入的每一個元素大小(單位為 byte)
count:要寫入的元素數量
stream:指向 FILE 物件的指標

以下 C/C++ fwrite 的用法介紹將分為這幾部份,

  • C/C++ fwrite 將文字寫入到檔案的基本用法
  • C/C++ fwrite 將文字寫入到標準輸出
  • C/C++ fwrite 寫入二進制檔
  • C/C++ fwrite 將 struct 資料寫入二進制檔

那我們開始吧!

C/C++ fwrite 將文字寫入到檔案的基本用法

這邊介紹 C/C++ fwrite 寫入文字檔的基本用法,在用 fwrite 來寫入文字檔前要先 fopen 開檔成功才能對檔案寫入,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功。

接著使用 fwrite 進行寫入文字,我們宣告的 buffer 有 1024 大小,但是裡面只有 24 的字元需要寫入到檔案裡,所以這邊 fwrite 第三個引數填入 24,fwrite 會回傳寫入了多少 bytes,沒有意外的話就是跟我們帶入的大小一樣,也就是 numwritten 預期會是 24,寫完後最後 fclose 關檔,

cpp-fwrite.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// g++ cpp-fwrite.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[1024] = "hello world\n123\n456\n789\n";
size_t numwritten;

fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

numwritten = fwrite(buffer, sizeof(char), 24, fp);
printf("write %zu bytes\n", numwritten);
fclose(fp);
return 0;
}

結果輸出如下,

1
write 24 bytes

輸出 output.txt 的內容如下,

1
2
3
4
hello world
123
456
789

C/C++ fwrite 將文字寫入到標準輸出

C/C++ fwrite 除了對檔案寫入文字以外也可以用來對標準輸出進行寫入文字,範例如下,標準輸出為 stdout 就不需要像檔案一樣開檔了,

cpp-fwrite2.cpp
1
2
3
4
5
6
7
8
9
10
11
// g++ cpp-fwrite2.cpp -o a.out
#include <stdio.h>

int main() {
char buffer[32] = "hello world\n";
size_t numwritten;
numwritten = fwrite(buffer, sizeof(char), 12, stdout);
printf("write %zu bytes\n", numwritten);

return 0;
}

標準輸出如下,

1
2
hello world
write 12 bytes

C/C++ fwrite 寫入二進制檔

這邊介紹 C/C++ fwrite 寫入二進制檔,假如只寫入單純一筆 int 的資料的話,範例如下,

cpp-fwrite3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// g++ cpp-fwrite3.cpp -o a.out
#include <stdio.h>

int main() {
int num = 5;

FILE *fp = fopen("output.bin", "wb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

size_t numwritten = fwrite(&num, sizeof(int), 1, fp);
printf("write %zu bytes\n", numwritten);
fclose(fp);
return 0;
}

hexdump output.bin 輸出如下,

1
2
3
$ hexdump output.bin
0000000 05 00 00 00
0000004

假如要寫入 int 陣列的資料的話,範例如下,

cpp-fwrite4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// g++ cpp-fwrite4.cpp -o a.out
#include <stdio.h>

int main() {
int arr[3] = {1, 2, 3};

FILE *fp = fopen("output.bin", "wb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

size_t numwritten;
numwritten = fwrite(&arr, sizeof(int), 3, fp);
// or
/*for (int i = 0; i < 3; i++) {
numwritten += fwrite(&arr[i], sizeof(int), 1, fp);
}*/
printf("write %zu bytes\n", numwritten);
fclose(fp);
return 0;
}

hexdump output.bin 輸出如下,

1
2
3
$ hexdump output.bin
0000000 01 00 00 00 02 00 00 00 03 00 00 00
000000c

上例中也可以搭配用 for 迴圈的方式寫入,

1
2
3
for (int i = 0; i < 3; i++) {
numwritten += fwrite(&arr[i], sizeof(int), 1, fp);
}

要用 fread 讀取二進制檔資料的話可以看看這篇

C/C++ fwrite 將 struct 資料寫入二進制檔

這邊示範 C++ 用 fwrite 將 struct 資料寫入二進制檔,寫入 struct 資料前先寫入 struct 的筆數,這樣在讀取二進制檔案時可以方便先知道要讀取幾筆 struct 資料,

cpp-fwrite5.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// g++ cpp-fwrite5.cpp -o a.out
#include <stdio.h>

struct Student {
int id;
char name[4];
int age;
};

int main() {
struct Student st[3] = {
{1, "ab", 18},
{2, "cd", 19},
{3, "ef", 20},
};
int count = 3;

FILE *fp = fopen("output.bin", "wb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fwrite(&count, sizeof(int), 1, fp); // 寫入筆數
fwrite(st, sizeof(struct Student), 3, fp);
fclose(fp);
return 0;
}

hexdump output.bin 輸出如下,

1
2
3
4
5
$ hexdump output.bin
0000000 03 00 00 00 01 00 00 00 61 62 00 00 12 00 00 00
0000010 02 00 00 00 63 64 00 00 13 00 00 00 03 00 00 00
0000020 65 66 00 00 14 00 00 00
0000028

要用 fread 將二進制檔的資料讀取到 struct 裡的話可以看看這篇

以上就是 C/C++ fwrite 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ fopen 用法與範例
C/C++ fread 用法與範例
C/C++ fgets 用法與範例
C/C++ fputs 用法與範例
C/C++ fclose 用法與範例

C/C++ fgets 用法與範例

本篇 ShengYu 介紹 C/C++ fgets 的用法與範例,C/C++ 可以使用 fgets 從檔案裡讀取一行文字出來,fgets 函式會一直讀取到換行字元或檔尾為止,fgets 除了從檔案裡讀取一行文字以外還能從標準輸入讀取一行文字,詳見本篇範例。

C/C++ 要使用 fread 的話需要引入的標頭檔 <stdio.h>,如果要使用 C++ 的標頭檔則是引入 <cstdio>
fgets 函式原型為

1
char * fgets(char * str, int num, FILE * stream);

str:指向一塊字元陣列的指標,讀取的字串將會複製到這裡
num:讀取字元複製到 str 的最大數量(包含 '\0' 結束字元)
stream:指向 FILE 物件的指標

以下 C/C++ fgets 的用法介紹將分為這幾部份,

  • C/C++ fgets 從檔案一次讀取一行文字
  • C/C++ fgets 從檔案讀取多行文字
  • C/C++ fgets 從標準輸入讀取一行文字

那我們開始吧!

C/C++ fgets 從檔案一次讀取一行文字

這邊介紹 C/C++ fgets 一次讀取一行,以下範例示範 C/C++ 用 fgets 來讀取文字檔的內容,假設我們要讀取一個 input.txt,input.txt 內容長這樣如下,

input.txt
1
2
hello world
123456

在使用 fgets 前要先 fopen 開檔成功才能進行檔案內容讀取,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功。

宣告一塊字元陣列 buffer 大小為 32,所以 fgets 最多讀取 32 個 bytes 不超過 buffer 的大小,然後將讀到的文字用 printf 印出來,最後 fclose 關檔,

cpp-fgets.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// g++ cpp-fgets.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[32];

fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fgets(buffer, 32, fp);
printf("%s\n", buffer);
fclose(fp);
return 0;
}

結果輸出如下,

1
hello world

C/C++ fgets 從檔案讀取多行文字

這邊介紹 C/C++ fgets 讀取多行,input.txt 跟上述例子相同,這次 fgets 搭配 while 迴圈來不斷地讀取多行文字,buffer 大小為 32,所以這邊 fgets 每次最多讀取 32 個 bytes,每次將讀到的文字用 printf 印出來,如果 fgets 讀完會回傳 NULL,接著就結束 while 迴圈,然後 fclose 關檔,

cpp-fgets2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// g++ cpp-fgets2.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[32];

fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

while (fgets(buffer, 32, fp) != NULL) {
printf("%s", buffer);
}
printf("close file\n");
fclose(fp);
return 0;
}

結果輸出如下,

1
2
3
hello world
123456
close file

C/C++ fgets 從標準輸入讀取一行文字

C/C++ fgets 除了從檔案裡讀取一行文字以外也可以用來從標準輸入讀取一行文字,範例如下,標準輸入為 stdin 就不需要像檔案一樣開檔了,

cpp-fgets3.cpp
1
2
3
4
5
6
7
8
9
10
11
// g++ cpp-fgets3.cpp -o a.out
#include <stdio.h>

int main() {
char buffer[32];
printf("input: ");
fgets(buffer, 32, stdin);
printf("%s\n", buffer);

return 0;
}

啟動程式後輸入 123456 的輸出如下,

1
2
input: 123456
123456

以上就是 C/C++ fgets 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ fopen 用法與範例
C/C++ fread 用法與範例
C/C++ fwrite 用法與範例
C/C++ fputs 用法與範例
C/C++ fclose 用法與範例

C/C++ fread 用法與範例

本篇 ShengYu 介紹 C/C++ fread 的用法與範例,C/C++ 可以使用 fread 從文字檔裡讀取內容出來,在 fread 函式的引數裡可以指定要讀取幾個 bytes 字元,fread 除了從檔案裡讀取文字以外還能從標準輸入讀取文字,詳見本篇範例。

C/C++ 要使用 fread 的話需要引入的標頭檔 <stdio.h>,如果要使用 C++ 的標頭檔則是引入 <cstdio>
fread 函式原型為

1
size_t fread(void * ptr, size_t size, size_t count, FILE * stream);

ptr:指向一塊記憶體的指標,該塊記憶體至少要(size * count)個的大小
size:要讀取的每一個元素大小(單位為 byte)
count:要讀取的元素數量
stream:指向 FILE 物件的指標

以下 C/C++ fread 的用法介紹將分為這幾部份,

  • C/C++ fread 從檔案讀取文字的基本用法
  • C/C++ fread 從檔案多次讀取文字
  • C/C++ fread 從標準輸入讀取文字
  • C/C++ fread 讀取二進制檔
  • C/C++ fread 讀取二進制檔資料到 struct 裡

那我們開始吧!

C/C++ fread 從檔案讀取文字的基本用法

這邊介紹 C/C++ fread 從檔案讀取文字的基本用法,以下範例示範 C/C++ 用 fread 來讀取文字檔的內容,假設我們要讀取一個 input.txt,input.txt 內容長這樣如下,

input.txt
1
2
hello world
123456

那麼用 fread 來讀取文字檔的程式碼如下,在使用 fread 前要先 fopen 開檔成功才能進行檔案內容讀取,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功。

接著使用 fread 進行讀取,這邊示範用 fread 讀取 1024 bytes,如果檔案內容小於 1024 bytes 的話,這次的 fread 就會讀完整個檔案的內容且回傳讀取了多少 bytes,如果檔案內容大於 1024 的話,這次的 fread 最多只會讀取 1024 bytes,你需要再次呼叫 fread 來讀取剩下的檔案內容,這個 fread 第三個引數的 1024 數字是可以調整的,但不能超過 buffer 變數的大小,接著將 buffer 用 printf 印出來,最後 fclose 關檔,

cpp-fread.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// g++ cpp-fread.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[1024];
size_t numread;

fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

numread = fread(buffer, sizeof(char), 1024, fp);
printf("read %lu bytes\n", numread);
printf("%s\n", buffer);
fclose(fp);
return 0;
}

fread 讀取完後用 printf 印出來結果輸出如下,

1
2
hello world
123456

C/C++ fread 從檔案多次讀取文字

這邊示範 C/C++ fread 從檔案多次讀取文字的範例,搭配一個 while 無窮迴圈進行 fread 讀取,並且每次只讀 10 的元素,直到 fread 回傳的 numread 為 0 才跳離 while 迴圈,然後 fclose 關檔,

cpp-fread2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// g++ cpp-fread2.cpp -o a.out
#include <stdio.h>
#include <string.h>

int main() {
FILE *fp;
char buffer[1024];
size_t numread;

fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

while (1) {
memset(buffer, 0, 1024);
numread = fread(buffer, sizeof(char), 10, fp);
if (numread == 0)
break;
printf("read %lu bytes\n", numread);
printf("%s\n", buffer);
}
fclose(fp);
return 0;
}

結果輸出如下,

1
2
3
4
5
read 10 bytes
hello worl
read 9 bytes
d
123456

C/C++ fread 從標準輸入讀取文字

C/C++ fread 除了從檔案裡讀取文字以外也可以用來從標準輸入讀取文字,範例如下,標準輸入為 stdin 就不需要像檔案一樣開檔了,

cpp-fread3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// g++ cpp-fread3.cpp -o a.out
#include <stdio.h>

int main() {
char buffer[32];
size_t numread;

printf("input: ");
numread = fread(buffer, sizeof(char), 10, stdin);
printf("read %lu bytes\n", numread);
printf("%s\n", buffer);

return 0;
}

啟動程式後輸入 hello world 123 的輸出如下,

1
2
3
input: hello world 123
read 10 bytes
hello worl

C/C++ fread 讀取二進制檔

這邊介紹 C/C++ fwrite 讀取二進制檔,假如只讀取單純一筆 int 的資料的話,範例如下,

cpp-fread4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// g++ cpp-fread4.cpp -o a.out
#include <stdio.h>

int main() {
int num;

FILE *fp = fopen("input.bin", "rb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

size_t numread = fread(&num, sizeof(int), 1, fp);
printf("read %lu bytes\n", numread);
printf("%d\n", num);
fclose(fp);
return 0;
}

結果輸出如下,

1
2
read 1 bytes
5

假如要讀取 int 陣列的資料的話,範例如下,

cpp-fread5.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// g++ cpp-fread5.cpp -o a.out
#include <stdio.h>

int main() {
int arr[3];

FILE *fp = fopen("input.bin", "rb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

size_t numread;
numread = fread(&arr, sizeof(int), 3, fp);
// or
/*for (int i = 0; i < 3; i++) {
numread += fread(&arr[i], sizeof(int), 1, fp);
}*/
printf("read %lu bytes\n", numread);
printf("%d, %d, %d\n", arr[0], arr[1], arr[2]);
fclose(fp);
return 0;
}

結果輸出如下,

1
2
read 3 bytes
1, 2, 3

上例中也可以搭配用 for 迴圈的方式寫入,

1
2
3
for (int i = 0; i < 3; i++) {
numread += fread(&arr[i], sizeof(int), 1, fp);
}

要用 fwrite 將資料寫入二進制檔的話可以看看這篇

C/C++ fread 讀取二進制檔資料到 struct 裡

這邊示範 C/C++ fread 讀取二進制檔資料到 struct 裡,先用 fread 讀一個 int 知道有幾筆 struct 的資料後,之後再用 for 迴圈搭配 fread 讀取 count 次 struct 的資料,

cpp-fread6.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// g++ cpp-fread6.cpp -o a.out
#include <stdio.h>

struct Student {
int id;
char name[4];
int age;
};

int main() {
struct Student st[10] = {0};
int count;

FILE *fp = fopen("input.bin", "rb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fread(&count, sizeof(int), 1, fp);
printf("count: %d\n", count);

for (int i = 0; i < count; i++) {
fread(&st[i], sizeof(struct Student), 1, fp);
printf("id: %d, name: %s, age: %d\n",
st[i].id, st[i].name, st[i].age);
}
fclose(fp);
return 0;
}

結果輸出如下,

1
2
3
4
count: 3
id: 1, name: ab, age: 18
id: 2, name: cd, age: 19
id: 3, name: ef, age: 20

更好的寫法是讀完筆數後,去 new 動態記憶體配置對應的 struct 筆數,如下所示,跟上例不同的地方還有這次我把 fread 一次讀取 count 筆 struct 資料,

cpp-fread7.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// g++ cpp-fread7.cpp -o a.out
#include <stdio.h>

struct Student {
int id;
char name[4];
int age;
};

int main() {
int count;

FILE *fp = fopen("input.bin", "rb");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fread(&count, sizeof(int), 1, fp);
printf("count: %d\n", count);

struct Student *st = new Student[count];
fread(st, sizeof(struct Student), 3, fp);

for (int i = 0; i < count; i++) {
printf("id: %d, name: %s, age: %d\n",
st[i].id, st[i].name, st[i].age);
}
fclose(fp);
return 0;
}

結果輸出同上。要如何用 fwrite 將 struct 寫入二進制的範例可以看這篇

以上就是 C/C++ fread 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ fopen 用法與範例
C/C++ fgets 用法與範例
C/C++ fwrite 用法與範例
C/C++ fputs 用法與範例
C/C++ fclose 用法與範例

C/C++ fopen 用法與範例

本篇 ShengYu 介紹 C/C++ fopen 的用法與範例,C/C++ 不管是文字檔的讀取或寫入都需要先開檔,即使是二進制檔的讀取或寫入也是需要先開檔,詳見本篇範例。

C/C++ 要使用 fopen 的話需要引入的標頭檔 <stdio.h>,如果要使用 C++ 的標頭檔則是引入 <cstdio>
fopen 函式原型為

1
FILE * fopen(const char * filename, const char * mode);

filename:檔案名稱 (可包含路徑)
mode:開檔模式,"r" 開檔且讀取文字檔、"w" 開檔且覆蓋寫入文字檔、"a" 開檔且添加文字檔在檔尾、"rb" 開檔且讀取二進制檔、"wb" 開檔且覆蓋寫入二進制檔、"ab" 開檔且添加二進制在檔尾

以下 C/C++ fopen 的用法介紹將分為這幾部份,

  • C/C++ fopen 開檔並且一次讀取文字檔全部內容
  • C/C++ fopen 開檔並且一次讀取一行
  • C/C++ fopen 開檔並且一次寫入全部文字到檔案
  • C/C++ fopen 開檔並且一次寫入一行

那我們開始吧!

C/C++ fopen 開檔並且一次讀取文字檔全部內容

這邊介紹 C/C++ fopen 開檔並且一次讀取文字檔全部內容,一開始要先用 fopen 開檔,要先 fopen 開檔成功才能進行檔案內容讀取,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功,之後用 fread 進行文字檔的讀取,

cpp-fopen.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// g++ cpp-fopen.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[1024];
size_t numread;

fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

numread = fread(buffer, sizeof(char), 1024, fp);
printf("read %lu bytes\n", numread);
printf("%s\n", buffer);
fclose(fp);
return 0;
}

C/C++ fopen 開檔並且一次讀取一行

這邊介紹 C/C++ fopen 開檔並且一次讀取一行,一開始要先用 fopen 開檔,要先 fopen 開檔成功才能進行檔案內容讀取,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功,之後用 fgets 進行文字檔的讀取,如果要讀取多行的話可以搭配 for / while 迴圈使用,

cpp-fopen2.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// g++ cpp-fopen2.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[32];

fp = fopen("input.txt", "r");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fgets(buffer, 32, fp);
printf("%s\n", buffer);
fclose(fp);
return 0;
}

C/C++ fopen 開檔並且一次寫入全部文字到檔案

這邊介紹 C/C++ fopen 開檔並且一次寫入全部文字到檔案,一開始要先用 fopen 開檔,要先 fopen 開檔成功才能對檔案寫入,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功,之後用 fwrite 將文字寫入檔案裡,

cpp-fopen3.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// g++ cpp-fopen3.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;
char buffer[1024] = "hello world\n123456\n";
size_t numwritten;

fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

numwritten = fwrite(buffer, sizeof(char), 24, fp);
printf("write %zu bytes\n", numwritten);
fclose(fp);
return 0;
}

C/C++ fopen 開檔並且一次寫入一行

這邊介紹 C/C++ fopen 開檔並且一次寫入一行,一開始要先用 fopen 開檔,要先 fopen 開檔成功才能對檔案寫入,fopen 開檔回傳 NULL 表示開檔失敗,如果不是 NULL 表示開檔成功,之後用 fputs 將文字寫入檔案裡,fputs 會將字串寫入直到遇見結束字元為止,如果要寫入多行的話可以搭配 for / while 迴圈使用,

cpp-fopen4.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// g++ cpp-fopen4.cpp -o a.out
#include <stdio.h>

int main() {
FILE *fp;

fp = fopen("output.txt", "w");
if (fp == NULL) {
printf("failed to open the file.\n");
return 1; // EXIT_FAILURE
}

fputs("hello world\n", fp);
fclose(fp);
return 0;
}

以上就是 C/C++ fopen 的用法與範例介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
如果你想學習 C++ 相關技術,可以參考看看下面的文章,
C/C++ 新手入門教學懶人包
C/C++ fread 用法與範例
C/C++ fgets 用法與範例
C/C++ fwrite 用法與範例
C/C++ fputs 用法與範例
C/C++ fclose 用法與範例

GIMP 圖片縮放

本篇介紹 GIMP 圖片縮放,GIMP 功能太多,縮放很常用到,每次都會忘記在選單的哪個位置,這次決定紀錄起來!

我 Ubuntu 使用的 Gimp 版本為 2.8.16,圖片縮放從 Gimp 選單列找到圖片,然後選擇縮放圖片,接著輸入想要的寬跟高,通常我都使用原比例縮放(右邊有個鎖的圖示),所以選擇寬跟高其中一個輸入就好,確定完畢後按 Enter。

其它相關文章推薦
GIMP 圖片裁切
GIMP 去背/去除背景

Python min 用法與範例

本篇 ShengYu 介紹 Python min 用法與範例,Python min 函式是用來求兩數最小值,Python min 函式也可以拿來計算 list 的最小值,

Python min 求兩數最小值

Python 內建就有提供 min() 函式可以使用,免去重新自己寫一個 min 函式的時間,以下為 Python min 兩數求最小值的方法,

python3-min-1.py
1
2
3
4
5
6
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

print(min(2, 4))
print(min(9, 5))
print(min(14.6, 16.1))

Python min 輸出結果如下,

1
2
3
2
5
14.6

Python min 函式求 list 最小值

Python min 也可以求 list 的最小值,方法如下,

python3-min-2.py
1
2
3
4
5
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

mylist = [3,1,-7,4,0,2]
print(min(mylist))

Python min 輸出結果如下,

1
-7

以上就是 Python min 用法與範例的介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

其它相關文章推薦
Python 新手入門教學懶人包

Visual Studio Code javascript go to definition 無法跳至定義處解決方法

本篇 ShengYu 紀錄 VS Code javascript go to definition 無法跳至定義處解決方法,某天我要 trace 別人的 javascript 程式碼時,因為要追蹤的函式在別支 js 檔案,讓 F12 跳至定義處這個功能沒有作用,也就是我在 a.js 要追蹤的某函式定義在 b.js 跳至定義處會沒有效果(同檔案內的函式是可以跳至定義處的),但是如果 a.js b.js 都有開啟再分頁的話就可以順利的跳至定義處,我心想難不成我要把專案下所有的 js 都開啟再分頁上嗎?這太蠢了!我決定先解決這惱人的問題,後來好在順利找到解決方式,解決方法如下,

在專案的最頂層目錄下建立一個 jsconfig.json,內容如下,

jsconfig.json
1
2
3
4
5
6
7
8
9
{
"compilerOptions": {
"target": "ES6"
},
"exclude": [
"node_modules",
"**/node_modules/*"
]
}

接著就可以跳至定義處了!

以上就是 Visual Studio Code javascript go to definition 無法跳至定義處解決方法介紹,
如果你覺得我的文章寫得不錯、對你有幫助的話記得 Facebook 按讚支持一下!

參考文章
visual studio code - how to using vscode JavaScript’s ‘go to definition’ cross files? - Stack Overflow
https://stackoverflow.com/questions/49184790/how-to-using-vscode-javascripts-go-to-definition-cross-files

其它相關文章推薦
Visual Studio Code 常用快捷鍵
Visual Studio Code 安裝 C/C++11 環境教學