哈夫曼树

基本概念

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

  • 带权路径长度:

    模板集合 - 图1

    哈夫曼编码

    注意考虑树只有一个点的情况 ```cpp

    include

    include

    include

    include

    include

    include

using namespace std;

const int N = 1010;

char s[N]; unordered_map rec; // 记录字母出现次数

int main() {

  1. #ifdef SUBMIT
  2. freopen("in.txt", "r", stdin);
  3. freopen("out.txt", "w", stdout);
  4. long _begin_time = clock();
  5. #endif
  6. while (scanf("%s", s), strcmp(s, "END") != 0) {
  7. int len = strlen(s);
  8. rec.clear(); // 记得清空
  9. for (int i = 0; i < len; i++) {
  10. rec[s[i]]++;
  11. }
  12. priority_queue<int, vector<int>, greater<int>> heap; // 优先队列没有clear方法
  13. for (auto it = rec.begin(); it != rec.end(); it++) {
  14. heap.push(it->second);
  15. // cout << (double)it->second / len << ' ';
  16. }
  17. // cout << endl;
  18. int avg = 0;
  19. if (heap.size() == 1) { // 注意,只有一个点时,带权路径长度就是那个点的权值
  20. avg = heap.top();
  21. }
  22. while (heap.size() > 1) { // 至少有两个点才能合并
  23. double a1 = heap.top(); heap.pop();
  24. double a2 = heap.top(); heap.pop();
  25. avg += a1 + a2;
  26. heap.push(a1 + a2);
  27. }
  28. // cout << avg << endl;
  29. int ori = len * 8;
  30. printf("%d %d %.1lf\n", ori, avg, (double)ori / avg);
  31. }
  32. #ifdef SUBMIT
  33. long _end_time = clock();
  34. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  35. #endif
  36. return 0;

}

  1. <a name="IVH85"></a>
  2. ## [Trie字符串统计](https://www.acwing.com/problem/content/description/837/)
  3. ```cpp
  4. #include <iostream>
  5. using namespace std;
  6. const int N = 2e4 + 10;
  7. int son[N][26], cnt[N], idx; // idx=0既是根结点,又代表没有孩子
  8. char s[N];
  9. void insert(char s[]) {
  10. int p = 0;
  11. for (int i = 0; s[i]; i++) {
  12. int u = s[i] - 'a';
  13. if (!son[p][u]) son[p][u] = ++idx;
  14. p = son[p][u];
  15. }
  16. cnt[p]++;
  17. }
  18. int query(char s[]) {
  19. int p = 0;
  20. for (int i = 0; s[i]; i++) {
  21. int u = s[i] - 'a';
  22. if (!son[p][u]) return 0;
  23. p = son[p][u];
  24. }
  25. return cnt[p];
  26. }
  27. int main() {
  28. int n;
  29. cin >> n;
  30. while (n--) {
  31. char op[2];
  32. scanf("%s%s", op, s);
  33. if (op[0] == 'I') {
  34. insert(s);
  35. }
  36. else {
  37. printf("%d\n", query(s));
  38. }
  39. }
  40. return 0;
  41. }

Prim算法求最小生成树

时间复杂度是 O(n^2+m) n表示点数,m表示边数

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int N = 510, INF = 0x3f3f3f3f;
  5. int g[N][N];
  6. int dist[N];
  7. bool st[N];
  8. int n, m;
  9. int prim() {
  10. memset(dist, 0x3f, sizeof dist);
  11. int ans = 0;
  12. for (int i = 0; i < n; i++) {
  13. int t = -1;
  14. for (int j = 1; j <= n; j++) {
  15. if (!st[j] && (t == -1 || dist[j] < dist[t]))
  16. t = j;
  17. }
  18. if (i && dist[t] == INF) return INF;
  19. if (i) ans += dist[t]; // 防止自环,先更新ans,再更新dist
  20. st[t] = true;
  21. for (int j = 1; j <= n; j++) dist[j] = min(dist[j], g[t][j]);
  22. }
  23. return ans;
  24. }
  25. int main() {
  26. cin >> n >> m;
  27. memset(g, 0x3f, sizeof g);
  28. while (m--) {
  29. int u, v, w;
  30. cin >> u >> v >> w;
  31. g[u][v] = g[v][u] = min(g[u][v], w);
  32. }
  33. int ans = prim();
  34. if (ans == INF) puts("impossible");
  35. else cout << ans;
  36. return 0;
  37. }

Kruskal算法求最小生成树

时间复杂度是 O(mlogm), n表示点数,m表示边数

  1. #include <iostream>
  2. #include <algorithm>
  3. using namespace std;
  4. const int N = 2e5 + 10;
  5. int p[N];
  6. struct Edge {
  7. int a, b, w;
  8. bool operator< (const Edge &W) const {
  9. return w < W.w;
  10. }
  11. }edges[N];
  12. int find(int x) {
  13. if (x != p[x]) p[x] = find(p[x]);
  14. return p[x];
  15. }
  16. int main() {
  17. int n, m;
  18. cin >> n >> m;
  19. for (int i = 0; i < m; i++) {
  20. scanf("%d%d%d", &edges[i].a, &edges[i].b, &edges[i].w);
  21. }
  22. sort(edges, edges + m); // 将所有边按权值从小到大排序
  23. for (int i = 1; i <= n; i++) p[i] = i;
  24. int cnt = 0, ans = 0;
  25. for (int i = 0; i < m; i++) {
  26. int a = edges[i].a, b = edges[i].b, w = edges[i].w;
  27. int fa = find(a), fb = find(b);
  28. if (fa != fb) { // 两个顶点不在一个连通块当中
  29. p[fa] = fb;
  30. cnt++;
  31. ans += w;
  32. }
  33. }
  34. if (cnt < n - 1) puts("impossible"); // 边的数量等于顶点数 - 1
  35. else cout << ans;
  36. return 0;
  37. }

Dijkstra求最短路-朴素

时间复杂度是 O(n^2+m), n表示点数,m表示边数

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int N = 510;
  5. int g[N][N], dist[N];
  6. bool st[N];
  7. int n, m;
  8. int dijkstra(int p) {
  9. memset(dist, 0x3f, sizeof dist);
  10. dist[p] = 0;
  11. for (int i = 0; i < n; i++) {
  12. int t = -1;
  13. for (int j = 1; j <= n; j++) {
  14. if (!st[j] && (t == -1 || dist[j] < dist[t]))
  15. t = j;
  16. }
  17. st[t] = true;
  18. for (int j = 1; j <= n; j++)
  19. dist[j] = min(dist[j], dist[t] + g[t][j]);
  20. }
  21. if (dist[n] == 0x3f3f3f3f) return -1;
  22. return dist[n];
  23. }
  24. int main() {
  25. cin >> n >> m;
  26. memset(g, 0x3f, sizeof g);
  27. while (m--) {
  28. int x, y, z;
  29. scanf("%d%d%d", &x, &y, &z);
  30. g[x][y] = min(g[x][y], z);
  31. }
  32. cout << dijkstra(1);
  33. return 0;
  34. }

Dijkstra求最短路-堆优化

时间复杂度O(mlogn),n是点数,m是边数

  1. #include <iostream>
  2. #include <queue>
  3. #include <cstring>
  4. using namespace std;
  5. const int N = 1.5e5 + 10, INF = 0x3f3f3f3f;
  6. typedef pair<int, int> PII;
  7. int n, m;
  8. int h[N], e[N], ne[N], w[N], idx;
  9. int dist[N];
  10. bool st[N];
  11. priority_queue<PII, vector<PII>, greater<PII>> heap;
  12. void add(int a, int b, int c) {
  13. w[idx] = c;
  14. e[idx] = b;
  15. ne[idx] = h[a];
  16. h[a] = idx++;
  17. }
  18. int dijkstra() {
  19. memset(dist, 0x3f, sizeof dist);
  20. dist[1] = 0;
  21. heap.push({0, 1});
  22. while (!heap.empty()) {
  23. auto p = heap.top(); heap.pop();
  24. int ver = p.second, d = p.first;
  25. if (st[ver]) continue;
  26. st[ver] = true;
  27. for (int i = h[ver]; i != -1; i = ne[i]) {
  28. int j = e[i];
  29. if (dist[ver] + w[i] < dist[j]) {
  30. dist[j] = dist[ver] + w[i];
  31. heap.push({dist[j], j});
  32. }
  33. }
  34. }
  35. if (dist[n] > INF / 2) return -1;
  36. return dist[n];
  37. }
  38. int main() {
  39. cin >> n >> m;
  40. memset(h, -1, sizeof h);
  41. while (m--) {
  42. int x, y, z;
  43. scanf("%d%d%d", &x, &y, &z);
  44. add(x, y, z);
  45. }
  46. cout << dijkstra();
  47. return 0;
  48. }

Floyd求最短路

时间复杂度O(n^3)

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int N = 210, INF = 0x3f3f3f3f;
  5. int g[N][N];
  6. int main() {
  7. int n, m, k;
  8. cin >> n >> m >> k;
  9. for (int i = 1; i <= n; i++) {
  10. for (int j = 1; j <= n; j++) {
  11. if (i == j) g[i][j] = 0;
  12. else g[i][j] = INF;
  13. }
  14. }
  15. for (int i = 0; i < m; i++) {
  16. int x, y, z;
  17. scanf("%d%d%d", &x, &y, &z);
  18. g[x][y] = min(g[x][y], z);
  19. }
  20. for (int k = 1; k <= n; k++) {
  21. for (int i = 1; i <= n; i++) {
  22. for (int j = 1; j <= n; j++) {
  23. g[i][j] = min(g[i][j], g[i][k] + g[k][j]);
  24. }
  25. }
  26. }
  27. while (k--) {
  28. int i, j;
  29. scanf("%d%d", &i, &j);
  30. if (g[i][j] >= INF / 2) printf("impossible\n"); // 可能有负边
  31. else printf("%d\n", g[i][j]);
  32. }
  33. }

有向图的拓扑序列

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int N = 1e5 + 10;
  5. int h[N], e[N], ne[N], idx;
  6. int d[N];
  7. int q[N], hh, tt = -1;
  8. int n, m;
  9. void add(int a, int b) {
  10. d[b]++;
  11. e[idx] = b;
  12. ne[idx] = h[a];
  13. h[a] = idx++;
  14. }
  15. bool toposort() {
  16. for (int i = 1; i <= n; i++) {
  17. if (!d[i]) { // 入度为0的点
  18. q[++tt] = i;
  19. }
  20. }
  21. while (hh <= tt) {
  22. int p = q[hh++];
  23. for (int i = h[p]; i != -1; i = ne[i]) {
  24. int j = e[i];
  25. if (--d[j] == 0) {
  26. q[++tt] = j;
  27. }
  28. }
  29. }
  30. return hh == n; // 所有节点都入队
  31. }
  32. int main() {
  33. cin >> n >> m;
  34. memset(h, -1, sizeof h);
  35. while (m--) {
  36. int x, y;
  37. scanf("%d%d", &x, &y);
  38. add(x, y);
  39. }
  40. if (toposort()) {
  41. for (int i = 0; i < n; i++)
  42. printf("%d ", q[i]);
  43. }
  44. else puts("-1");
  45. return 0;
  46. }

哈希

字符串哈希

  1. #include <iostream>
  2. using namespace std;
  3. const int N = 1e5 + 10, P = 131;
  4. typedef unsigned long long ULL;
  5. char str[N];
  6. ULL h[N], p[N];
  7. ULL get(int l, int r) {
  8. return h[r] - h[l - 1] * p[r - l + 1];
  9. }
  10. int main() {
  11. int n, m;
  12. cin >> n >> m;
  13. scanf("%s", str + 1);
  14. p[0] = 1;
  15. for (int i = 1; i <= n; i++) {
  16. h[i] = h[i - 1] * P + str[i];
  17. p[i] = p[i - 1] * P;
  18. }
  19. while (m--) {
  20. int l1, r1, l2, r2;
  21. scanf("%d%d%d%d", &l1, &r1, &l2, &r2);
  22. if (get(l1, r1) == get(l2, r2)) {
  23. puts("Yes");
  24. }
  25. else puts("No");
  26. }
  27. }

模拟散列表

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int N = 100003, null = 0x3f3f3f3f;
  5. int h[N];
  6. int find(int a) {
  7. int k = ((a % N) + N) % N;
  8. while (h[k] != null && h[k] != a) {
  9. k++;
  10. if (k == N) k = 0;
  11. }
  12. return k;
  13. }
  14. int main() {
  15. memset(h, 0x3f, sizeof h);
  16. int n;
  17. cin >> n;
  18. while (n--) {
  19. char op[2];
  20. int x;
  21. scanf("%s%d", op, &x);
  22. if (op[0] == 'I') {
  23. h[find(x)] = x;
  24. }
  25. else {
  26. if (h[find(x)] != x) puts("No");
  27. else puts("Yes");
  28. }
  29. }
  30. return 0;
  31. }

用数组实现一棵完全二叉树

堆排序

只实现插入+查询最小

  1. #include <iostream>
  2. using namespace std;
  3. const int N = 1e5 + 10;
  4. int h[N], hcnt;
  5. void down(int t) {
  6. int p = t;
  7. if (t * 2 <= hcnt && h[t * 2] < h[p]) p = t * 2;
  8. if (t * 2 + 1 <= hcnt && h[t * 2 + 1] < h[p]) p = t * 2 + 1;
  9. if (p != t) {
  10. swap(h[p], h[t]);
  11. down(p);
  12. }
  13. }
  14. int main() {
  15. int n, m;
  16. cin >> n >> m;
  17. hcnt = n;
  18. for (int i = 1; i <= n; i++) {
  19. scanf("%d", &h[i]);
  20. }
  21. for (int i = n / 2; i; i--) down(i); // 建堆O(n)
  22. while (m--) {
  23. printf("%d ", h[1]);
  24. h[1] = h[hcnt--];
  25. down(1);
  26. }
  27. return 0;
  28. }

模拟堆

  1. #include <iostream>
  2. #include <cstring>
  3. using namespace std;
  4. const int N = 1e5 + 10;
  5. int h[N], hp[N], ph[N], hcnt, pcnt;
  6. void hswap(int a, int b) { // 三种交换
  7. swap(ph[hp[a]], ph[hp[b]]);
  8. swap(hp[a], hp[b]);
  9. swap(h[a], h[b]);
  10. }
  11. void up(int p) {
  12. while (p / 2 && h[p] < h[p / 2]) {
  13. hswap(p, p / 2);
  14. p >>= 1;
  15. }
  16. }
  17. void down(int p) {
  18. int t = p;
  19. if (p * 2 <= hcnt && h[p * 2] < h[t]) t = p * 2;
  20. if (p * 2 + 1 <= hcnt && h[p * 2 + 1] < h[t]) t = p * 2 + 1;
  21. if (t != p) {
  22. hswap(t, p);
  23. down(t);
  24. }
  25. }
  26. int main() {
  27. int n;
  28. cin >> n;
  29. while (n--) {
  30. char op[5];
  31. scanf("%s", op);
  32. if (op[0] == 'I') {
  33. int x;
  34. scanf("%d", &x);
  35. hcnt++, pcnt++;
  36. h[hcnt] = x;
  37. ph[pcnt] = hcnt, hp[hcnt] = pcnt;
  38. up(hcnt);
  39. }
  40. else if (op[0] == 'P') {
  41. printf("%d\n", h[1]);
  42. }
  43. else if (strcmp(op, "DM") == 0) {
  44. hswap(1, hcnt);
  45. --hcnt;
  46. down(1);
  47. }
  48. else if (op[0] == 'D') {
  49. int k;
  50. scanf("%d", &k);
  51. k = ph[k];
  52. hswap(k, hcnt);
  53. hcnt--;
  54. up(k), down(k);
  55. }
  56. else if (op[0] == 'C') {
  57. int k, x;
  58. scanf("%d%d", &k, &x);
  59. k = ph[k];
  60. h[k] = x;
  61. up(k), down(k);
  62. }
  63. }
  64. return 0;
  65. }

链表

反转链表

非常值得借鉴的做法,遍历链表,将其存储到数组中进行各种处理

  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. const int N = 1e5 + 10;
  6. int h, e[N], ne[N];
  7. vector<int> q;
  8. int main() {
  9. int n, k;
  10. cin >> h >> n >> k;
  11. while (n--) {
  12. int addr, d, next;
  13. scanf("%d%d%d", &addr, &d, &next);
  14. e[addr] = d, ne[addr] = next;
  15. }
  16. for (int i = h; i != -1; i = ne[i]) {
  17. q.push_back(i);
  18. }
  19. for (int i = 0; i + k - 1 < q.size(); i += k) {
  20. reverse(q.begin() + i, q.begin() + i + k);
  21. }
  22. for (int i = 0; i < q.size(); i++) {
  23. printf("%05d %d ", q[i], e[q[i]]);
  24. if (i + 1 == q.size()) printf("-1\n");
  25. else printf("%05d\n", q[i + 1]);
  26. }
  27. return 0;
  28. }

反转链表

传统的链表做法
非递归
时间复杂度O(n),空间复杂度O(1)

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode(int x) : val(x), next(NULL) {}
  7. * };
  8. */
  9. class Solution {
  10. public:
  11. ListNode* reverseList(ListNode* head) {
  12. ListNode* h = new ListNode(0);
  13. ListNode *p = head;
  14. while (p) {
  15. ListNode *q = p->next;
  16. p->next = h->next;
  17. h->next = p;
  18. p = q;
  19. }
  20. return h->next;
  21. }
  22. };

递归
时间复杂度O(n),空间复杂度O(n)

  1. /**
  2. * Definition for singly-linked list.
  3. * struct ListNode {
  4. * int val;
  5. * ListNode *next;
  6. * ListNode(int x) : val(x), next(NULL) {}
  7. * };
  8. */
  9. class Solution {
  10. public:
  11. ListNode* reverseList(ListNode* head) {
  12. if (!head || !head->next) return head;
  13. ListNode *p = reverseList(head->next);
  14. head->next->next = head;
  15. head->next = nullptr;
  16. return p;
  17. }
  18. };

第k大数

知识点

基于快排的快速选择算法,做法就是在基准值的位置放好之后,如果大于基准值的数的数量cnt>=k,就在左半段寻找第k大数,否则在右半段寻找第k-cnt大数。每次选择了左右之一继续,因此时间复杂度为模板集合 - 图2

模板

  1. // 快排模板
  2. void quick_sort(int q[], int l, int r) {
  3. if (l >= r) return;
  4. // 随机选取基准
  5. int idx = l + rand() % (r - l + 1);
  6. int x = q[idx];
  7. int i = l - 1, j = r + 1;
  8. while (i < j) { //x左边的数<x,右边的数>x
  9. while (q[++i] < x);
  10. while (q[--j] > x);
  11. if (i < j) swap(q[i], q[j]);
  12. }
  13. quick_sort(q, l, j);
  14. quick_sort(q, j + 1, r);
  15. }
  16. // 快速选择
  17. void quick_select(int q[], int l, int r, int k) {
  18. if (l >= r) return q[l];
  19. int idx = l + rnad() % (r - l + 1);
  20. int x = q[idx];
  21. int i = l - 1, j = r + 1;
  22. while (i < j) {
  23. while (q[++i] < x);
  24. while (q[--j] > x);
  25. if (i < j) swap(q[i], q[j]);
  26. }
  27. int tmp = j - l + 1;
  28. if (tmp < k) return quick_select(q, j + 1, r, k - tmp);
  29. else return quick_select(q, l, j, k);
  30. }

字符串

strcpy和ctrncpy的实现

  1. int my_strcmp(const char *s1, const char *s2)
  2. {
  3. while(*s1 && *s2 && *s1 == *s2)
  4. {
  5. s1++;
  6. s2++;
  7. }
  8. return *s1 - *s2;
  9. }
  10. int my_strncmp(const char *s1, const char *s2, size_t n) {
  11. while (n--) {
  12. if (*s1 && *s2 && *s1 == *s2) {
  13. s1++;
  14. s2++;
  15. }
  16. else return *s1 - *s2;
  17. }
  18. return 0;
  19. }

strcat和strncat的实现

注意,dest和src不能相同,可以考虑加上assert判断,但库函数不会有这个问题

  1. char *my_strcat(char *dest, const char *src)
  2. {
  3. char *ret = dest;
  4. while (*dest)
  5. dest++;
  6. while (*dest++ = *src++);
  7. return ret;
  8. }
  9. char *my_strncat(char *dest, const char *src,int n)
  10. {
  11. char *ret = dest;
  12. while (*dest)
  13. dest++;
  14. while (n--) //通过此次while循环,将第二个字符串前n的字符连接到第一个字符串上
  15. *dest++ = *src++;
  16. *dest = '\0';
  17. return ret;
  18. }

动态规划

数字三角形

  1. #include <iostream>
  2. using namespace std;
  3. const int N = 510;
  4. int a[N][N];
  5. int main() {
  6. int n;
  7. cin >> n;
  8. for (int i = 1; i <= n; i++) {
  9. for (int j = 1; j <= i; j++) {
  10. scanf("%d", &a[i][j]);
  11. }
  12. }
  13. for (int i = n - 1; i >= 1; i--) {
  14. for (int j = 1; j <= i; j++) {
  15. a[i][j] += max(a[i + 1][j], a[i + 1][j + 1]);
  16. }
  17. }
  18. cout << a[1][1];
  19. return 0;
  20. }

文件操作

打开关闭

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #define N 100
  4. int main() {
  5. FILE *fp;
  6. char str[N + 1];
  7. //判断文件是否打开失败!
  8. if ( (fp = fopen("d:\\demo.txt", "r")) == NULL ) {
  9. puts("Fail to open file!");
  10. exit(0);
  11. }
  12. //循环读取文件的每一行数据
  13. while( fgets(str, N, fp) != NULL ) {
  14. printf("%s", str);
  15. }
  16. //操作结束后关闭文件!
  17. fclose(fp);
  18. return 0;
  19. }
控制读写权限的字符串(必须指明)
打开方式 说明
“r” 以“只读”方式打开文件。只允许读取,不允许写入。文件必须存在,否则打开失败。
“w” 以“写入”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
“a” 以“追加”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。
“r+” 以“读写”方式打开文件。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败。
“w+” 以“写入/更新”方式打开文件,相当于wr+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
“a+” 以“追加/更新”方式打开文件,相当于a和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。
控制读写方式的字符串(可以不写)
打开方式 说明
“t” 文本文件。如果不写,默认为"t"
“b” 二进制文件。

读写

  • int fputc( int c, FILE *fp );
  • int fputs( const char s, FILE fp );
  • int fprintf(FILE fp,const char format, …)
  • int fgetc( FILE * fp );
  • char fgets( char buf, int n, FILE *fp );
  • int fscanf(FILE fp, const char format, …) ```cpp

    include

    int main() { FILE *fp = NULL;

    fp = fopen(“/tmp/test.txt”, “w+”); fprintf(fp, “This is testing for fprintf…\n”); // FILE放开头 fputs(“This is testing for fputs…\n”, fp); // FILE放最后 fclose(fp); }

include

int main() { FILE *fp = NULL; char buff[255];

fp = fopen(“/tmp/test.txt”, “r”); fscanf(fp, “%s”, buff); printf(“1: %s\n”, buff );

fgets(buff, 255, (FILE*)fp); printf(“2: %s\n”, buff );

fgets(buff, 255, (FILE*)fp); printf(“3: %s\n”, buff ); fclose(fp);

}

// 二进制IO(以数据块的形式读写文件) size_t fread(void ptr, size_t size_of_elements, size_t number_of_elements, FILE a_file); size_t fwrite(const void ptr, size_t size_of_elements, size_t number_of_elements, FILE a_file);

  1. <a name="331tq"></a>
  2. ## 大文件
  3. 首先把整个文件读进来
  4. ```cpp
  5. // define buffer
  6. FILE *fin=fopen("input.bin", "rb");
  7. fseek(fin, 0, SEEK_END);
  8. long f_length=ftell(fin);
  9. fseek(fin, 0, SEEK_SET);
  10. fread(buffer, 1, f_length, fin);

然后考虑分行,可以采用strtok函数

  1. #include <string.h>
  2. #include <stdio.h>
  3. int main () {
  4. char str[80] = "This is\nwww.runoob.com\nwebsite";
  5. const char s[2] = "\n";
  6. char *token;
  7. /* 获取第一个子字符串 */
  8. token = strtok(str, s);
  9. /* 继续获取其他的子字符串 */
  10. while( token != NULL ) {
  11. printf("%s\n", token);
  12. token = strtok(NULL, s);
  13. }
  14. return(0);
  15. }