-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathc-language-file.html
More file actions
996 lines (950 loc) · 139 KB
/
c-language-file.html
File metadata and controls
996 lines (950 loc) · 139 KB
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
<!DOCTYPE html><html lang="zh-CN"><head><title>软件技术基础</title><meta property="og:title" content="软件技术基础"><meta charset="UTF-8"><meta name="viewport" content="width=device-width,height=device-height,initial-scale=1.0"><meta name="apple-mobile-web-app-capable" content="yes"><meta http-equiv="X-UA-Compatible" content="ie=edge"><meta property="og:type" content="website"><meta name="twitter:card" content="summary"><style>@media screen{body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button{appearance:none;background-color:initial;border:0;color:inherit;cursor:pointer;font-size:inherit;opacity:.8;outline:none;padding:0;transition:opacity .2s linear;-webkit-tap-highlight-color:transparent}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:disabled,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:disabled,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:disabled,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:disabled{cursor:not-allowed;opacity:.15!important}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover{opacity:1}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:active,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:active,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover:active,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover:active{opacity:.6}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:not(:disabled),body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button:hover:not(:disabled),body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button:hover:not(:disabled),body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button:hover:not(:disabled){transition:none}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button.bespoke-marp-presenter-info-page-prev{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNNjggOTAgMjggNTBsNDAtNDAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button.bespoke-marp-presenter-info-page-next{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJtMzIgOTAgNDAtNDAtNDAtNDAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen]{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZmZmO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4fTwvc3R5bGU+PC9kZWZzPjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI2MCIgeD0iMTAiIHk9IjIwIiBjbGFzcz0iYSIgcng9IjUuNjciLz48cGF0aCBkPSJNNDAgNzBIMjBWNTBtMjAgMEwyMCA3MG00MC00MGgyMHYyMG0tMjAgMCAyMC0yMCIgY2xhc3M9ImEiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button.exit[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button.exit[data-bespoke-marp-osc=fullscreen]{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48ZGVmcz48c3R5bGU+LmF7ZmlsbDpub25lO3N0cm9rZTojZmZmO3N0cm9rZS1saW5lY2FwOnJvdW5kO3N0cm9rZS1saW5lam9pbjpyb3VuZDtzdHJva2Utd2lkdGg6NXB4fTwvc3R5bGU+PC9kZWZzPjxyZWN0IHdpZHRoPSI4MCIgaGVpZ2h0PSI2MCIgeD0iMTAiIHk9IjIwIiBjbGFzcz0iYSIgcng9IjUuNjciLz48cGF0aCBkPSJNMjAgNTBoMjB2MjBtLTIwIDAgMjAtMjBtNDAgMEg2MFYzMG0yMCAwTDYwIDUwIiBjbGFzcz0iYSIvPjwvc3ZnPg==")}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter]{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNODcuOCA0Ny41Qzg5IDUwIDg3LjcgNTIgODUgNTJIMzVhOC43IDguNyAwIDAgMS03LjItNC41bC0xNS42LTMxQzExIDE0IDEyLjIgMTIgMTUgMTJoNTBhOC44IDguOCAwIDAgMSA3LjIgNC41ek02MCA1MnYzNm0tMTAgMGgyME00NSA0MmgyMCIvPjwvc3ZnPg==") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button.bespoke-marp-presenter-note-bigger{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNMTIgNTBoODBNNTIgOTBWMTAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button.bespoke-marp-presenter-note-smaller{background:#0000 url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxMDAgMTAwIj48cGF0aCBmaWxsPSJub25lIiBzdHJva2U9IiNmZmYiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCIgc3Ryb2tlLXdpZHRoPSI1IiBkPSJNMTIgNTBoODAiLz48L3N2Zz4=") no-repeat 50%;background-size:contain;overflow:hidden;text-indent:100%;white-space:nowrap}}@keyframes __bespoke_marp_transition_reduced_outgoing__{0%{opacity:1}to{opacity:0}}@keyframes __bespoke_marp_transition_reduced_incoming__{0%{mix-blend-mode:plus-lighter;opacity:0}to{mix-blend-mode:plus-lighter;opacity:1}}.bespoke-marp-note,.bespoke-marp-osc,.bespoke-progress-parent{display:none;transition:none}@media screen{::view-transition-group(*){animation-duration:var(--marp-bespoke-transition-animation-duration,.5s);animation-timing-function:ease}::view-transition-new(*),::view-transition-old(*){animation-delay:0s;animation-direction:var(--marp-bespoke-transition-animation-direction,normal);animation-duration:var(--marp-bespoke-transition-animation-duration,.5s);animation-fill-mode:both;animation-name:var(--marp-bespoke-transition-animation-name,var(--marp-bespoke-transition-animation-name-fallback,__bespoke_marp_transition_no_animation__));mix-blend-mode:normal}::view-transition-old(*){--marp-bespoke-transition-animation-name-fallback:__bespoke_marp_transition_reduced_outgoing__;animation-timing-function:ease}::view-transition-new(*){--marp-bespoke-transition-animation-name-fallback:__bespoke_marp_transition_reduced_incoming__;animation-timing-function:ease}::view-transition-new(root),::view-transition-old(root){animation-timing-function:linear}::view-transition-new(__bespoke_marp_transition_osc__),::view-transition-old(__bespoke_marp_transition_osc__){animation-duration:0s!important;animation-name:__bespoke_marp_transition_osc__!important}::view-transition-new(__bespoke_marp_transition_osc__){opacity:0!important}.bespoke-marp-transition-warming-up::view-transition-group(*),.bespoke-marp-transition-warming-up::view-transition-new(*),.bespoke-marp-transition-warming-up::view-transition-old(*){animation-play-state:paused!important}body,html{height:100%;margin:0}body{background:#000;overflow:hidden}svg.bespoke-marp-slide{content-visibility:hidden;opacity:0;pointer-events:none;z-index:-1}svg.bespoke-marp-slide:not(.bespoke-marp-active) *{view-transition-name:none!important}svg.bespoke-marp-slide.bespoke-marp-active{content-visibility:visible;opacity:1;pointer-events:auto;z-index:0}svg.bespoke-marp-slide.bespoke-marp-active.bespoke-marp-active-ready *{animation-name:__bespoke_marp__!important}@supports not (content-visibility:hidden){svg.bespoke-marp-slide[data-bespoke-marp-load=hideable]{display:none}svg.bespoke-marp-slide[data-bespoke-marp-load=hideable].bespoke-marp-active{display:block}}}@media screen and (prefers-reduced-motion:reduce){svg.bespoke-marp-slide *{view-transition-name:none!important}}@media screen{[data-bespoke-marp-fragment=inactive]{visibility:hidden}body[data-bespoke-view=""] .bespoke-marp-parent,body[data-bespoke-view=next] .bespoke-marp-parent{inset:0;position:absolute}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc{background:#000000a6;border-radius:7px;bottom:50px;color:#fff;contain:paint;display:block;font-family:Helvetica,Arial,sans-serif;font-size:16px;left:50%;line-height:0;opacity:1;padding:12px;position:absolute;touch-action:manipulation;transform:translateX(-50%);transition:opacity .2s linear;-webkit-user-select:none;user-select:none;white-space:nowrap;will-change:transform;z-index:1;view-transition-name:__bespoke_marp_transition_osc__}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>*,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>*{margin-left:6px}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>:first-child,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>:first-child{margin-left:0}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>span,body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>span{opacity:.8}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>span[data-bespoke-marp-osc=page],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>span[data-bespoke-marp-osc=page]{display:inline-block;min-width:140px;text-align:center}body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=""] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=fullscreen],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=next],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=presenter],body[data-bespoke-view=next] .bespoke-marp-parent>.bespoke-marp-osc>button[data-bespoke-marp-osc=prev]{height:32px;line-height:32px;width:32px}body[data-bespoke-view=""] .bespoke-marp-parent.bespoke-marp-inactive,body[data-bespoke-view=next] .bespoke-marp-parent.bespoke-marp-inactive{cursor:none}body[data-bespoke-view=""] .bespoke-marp-parent.bespoke-marp-inactive>.bespoke-marp-osc,body[data-bespoke-view=next] .bespoke-marp-parent.bespoke-marp-inactive>.bespoke-marp-osc{opacity:0;pointer-events:none}body[data-bespoke-view=""] svg.bespoke-marp-slide,body[data-bespoke-view=next] svg.bespoke-marp-slide{height:100%;left:0;position:absolute;top:0;width:100%}body[data-bespoke-view=""] .bespoke-progress-parent{background:#222;display:flex;height:5px;width:100%}body[data-bespoke-view=""] .bespoke-progress-parent+.bespoke-marp-parent{top:5px}body[data-bespoke-view=""] .bespoke-progress-parent .bespoke-progress-bar{background:#0288d1;flex:0 0 0;transition:flex-basis .2s cubic-bezier(0,1,1,1)}body[data-bespoke-view=next]{background:#0000}body[data-bespoke-view=presenter]{background:#161616}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container{display:grid;font-family:Helvetica,Arial,sans-serif;grid-template:"current dragbar next" minmax(140px,1fr) "current dragbar note" 2fr "info dragbar note" 3em;grid-template-columns:minmax(3px,var(--bespoke-marp-presenter-split-ratio,66%)) 0 minmax(3px,1fr);height:100%;left:0;position:absolute;top:0;width:100%}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent{grid-area:current;overflow:hidden;position:relative}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent svg.bespoke-marp-slide{height:calc(100% - 40px);left:20px;pointer-events:none;position:absolute;top:20px;-webkit-user-select:none;user-select:none;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-parent svg.bespoke-marp-slide.bespoke-marp-active{filter:drop-shadow(0 3px 10px rgba(0,0,0,.5))}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container{background:#0288d1;cursor:col-resize;grid-area:dragbar;margin-left:-3px;opacity:0;position:relative;transition:opacity .4s linear .1s;width:6px;z-index:10}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container:hover{opacity:1}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-dragbar-container.active{opacity:1;transition-delay:0s}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container{background:#222;cursor:pointer;display:none;grid-area:next;overflow:hidden;position:relative}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container.active{display:block}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-next-container iframe.bespoke-marp-presenter-next{background:#0000;border:0;display:block;filter:drop-shadow(0 3px 10px rgba(0,0,0,.5));height:calc(100% - 40px);left:20px;pointer-events:none;position:absolute;top:20px;-webkit-user-select:none;user-select:none;width:calc(100% - 40px)}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container{background:#222;color:#eee;grid-area:note;position:relative;z-index:1}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container button{height:1.5em;line-height:1.5em;width:1.5em}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-wrapper{display:block;inset:0;position:absolute}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-buttons{background:#000000a6;border-radius:4px;bottom:0;display:flex;gap:4px;margin:12px;opacity:0;padding:6px;pointer-events:none;position:absolute;right:0;transition:opacity .2s linear}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-buttons:focus-within,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-presenter-note-wrapper:focus-within+.bespoke-marp-presenter-note-buttons,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container:hover .bespoke-marp-presenter-note-buttons{opacity:1;pointer-events:auto}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note{box-sizing:border-box;font-size:calc(1.1em*var(--bespoke-marp-note-font-scale, 1));height:calc(100% - 40px);margin:20px;overflow:auto;padding-right:3px;white-space:pre-wrap;width:calc(100% - 40px);word-wrap:break-word;scrollbar-color:#eeeeee80 #0000;scrollbar-width:thin}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar{width:6px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar-track{background:#0000}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note::-webkit-scrollbar-thumb{background:#eeeeee80;border-radius:6px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note:empty{pointer-events:none}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note.active{display:block}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note p:first-child{margin-top:0}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-note-container .bespoke-marp-note p:last-child{margin-bottom:0}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container{align-items:center;box-sizing:border-box;color:#eee;display:flex;flex-wrap:nowrap;grid-area:info;justify-content:center;overflow:hidden;padding:0 10px}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-time,body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer{box-sizing:border-box;display:block;padding:0 10px;white-space:nowrap;width:100%}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container button{height:1.5em;line-height:1.5em;width:1.5em}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page{order:2;text-align:center}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-page .bespoke-marp-presenter-info-page-text{display:inline-block;min-width:120px;text-align:center}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-time{color:#999;order:1;text-align:left}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer{color:#999;order:3;text-align:right}body[data-bespoke-view=presenter] .bespoke-marp-presenter-container .bespoke-marp-presenter-info-container .bespoke-marp-presenter-info-timer:hover{cursor:pointer}}@media print{.bespoke-marp-presenter-info-container,.bespoke-marp-presenter-next-container,.bespoke-marp-presenter-note-container{display:none}}</style><style>@charset "UTF-8";@import "https://fonts.bunny.net/css?family=Lato:400,900|Roboto+Mono:400,700&display=swap";div#\:\$p > svg > foreignObject > section{width:1280px;height:720px;box-sizing:border-box;overflow:hidden;position:relative;scroll-snap-align:center center;-webkit-text-size-adjust:100%;text-size-adjust:100%}div#\:\$p > svg > foreignObject > section::after{bottom:0;content:attr(data-marpit-pagination);padding:inherit;pointer-events:none;position:absolute;right:0}div#\:\$p > svg > foreignObject > section:not([data-marpit-pagination])::after{display:none}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1){font-size:2em;margin-block:0.67em}div#\:\$p > svg > foreignObject > section video::-webkit-media-controls{will-change:transform}@page {size:1280px 720px;margin:0}@media print{html, body{background-color:#fff;margin:0;page-break-inside:avoid;break-inside:avoid-page}div#\:\$p > svg > foreignObject > section{page-break-before:always;break-before:page}div#\:\$p > svg > foreignObject > section, div#\:\$p > svg > foreignObject > section *{-webkit-print-color-adjust:exact!important;animation-delay:0s!important;animation-duration:0s!important;color-adjust:exact!important;print-color-adjust:exact!important;transition:none!important}div#\:\$p > svg[data-marpit-svg]{display:block;height:100vh;width:100vw}}div#\:\$p > svg > foreignObject > :where(section){container-type:size}div#\:\$p > svg > foreignObject > section img[data-marp-twemoji]{background:transparent;height:1em;margin:0 .05em 0 .1em;vertical-align:-.1em;width:1em}/*!
* Marp / Marpit Gaia theme.
*
* @theme gaia
* @author Yuki Hattori
*
* @auto-scaling true
* @size 16:9 1280px 720px
* @size 4:3 960px 720px
*/div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) code.hljs{display:block;overflow-x:auto;padding:1em}div#\:\$p > svg > foreignObject > section code.hljs{padding:3px 5px}div#\:\$p > svg > foreignObject > section .hljs{background:#000;color:#f8f8f8}div#\:\$p > svg > foreignObject > section .hljs-comment,div#\:\$p > svg > foreignObject > section .hljs-quote{color:#aeaeae;font-style:italic}div#\:\$p > svg > foreignObject > section .hljs-keyword,div#\:\$p > svg > foreignObject > section .hljs-selector-tag,div#\:\$p > svg > foreignObject > section .hljs-type{color:#e28964}div#\:\$p > svg > foreignObject > section .hljs-string{color:#65b042}div#\:\$p > svg > foreignObject > section .hljs-subst{color:#daefa3}div#\:\$p > svg > foreignObject > section .hljs-link,div#\:\$p > svg > foreignObject > section .hljs-regexp{color:#e9c062}div#\:\$p > svg > foreignObject > section .hljs-name,div#\:\$p > svg > foreignObject > section .hljs-section,div#\:\$p > svg > foreignObject > section .hljs-tag,div#\:\$p > svg > foreignObject > section .hljs-title{color:#89bdff}div#\:\$p > svg > foreignObject > section .hljs-class .hljs-title,div#\:\$p > svg > foreignObject > section .hljs-doctag,div#\:\$p > svg > foreignObject > section .hljs-title.class_{text-decoration:underline}div#\:\$p > svg > foreignObject > section .hljs-bullet,div#\:\$p > svg > foreignObject > section .hljs-number,div#\:\$p > svg > foreignObject > section .hljs-symbol{color:#3387cc}div#\:\$p > svg > foreignObject > section .hljs-params,div#\:\$p > svg > foreignObject > section .hljs-template-variable,div#\:\$p > svg > foreignObject > section .hljs-variable{color:#3e87e3}div#\:\$p > svg > foreignObject > section .hljs-attribute{color:#cda869}div#\:\$p > svg > foreignObject > section .hljs-meta{color:#8996a8}div#\:\$p > svg > foreignObject > section .hljs-formula{background-color:#0e2231;color:#f8f8f8;font-style:italic}div#\:\$p > svg > foreignObject > section .hljs-addition{background-color:#253b22;color:#f8f8f8}div#\:\$p > svg > foreignObject > section .hljs-deletion{background-color:#420e09;color:#f8f8f8}div#\:\$p > svg > foreignObject > section .hljs-selector-class{color:#9b703f}div#\:\$p > svg > foreignObject > section .hljs-selector-id{color:#8b98ab}div#\:\$p > svg > foreignObject > section .hljs-emphasis{font-style:italic}div#\:\$p > svg > foreignObject > section .hljs-strong{font-weight:700}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section :is(h2, marp-h2),div#\:\$p > svg > foreignObject > section :is(h3, marp-h3),div#\:\$p > svg > foreignObject > section :is(h4, marp-h4),div#\:\$p > svg > foreignObject > section :is(h5, marp-h5),div#\:\$p > svg > foreignObject > section :is(h6, marp-h6){margin:.5em 0 0}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1) strong,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2) strong,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3) strong,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4) strong,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5) strong,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6) strong{font-weight:inherit}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h2, marp-h2)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h3, marp-h3)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h4, marp-h4)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h5, marp-h5)::part(auto-scaling),div#\:\$p > svg > foreignObject > section :is(h6, marp-h6)::part(auto-scaling){max-height:580px}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1){font-size:1.8em}div#\:\$p > svg > foreignObject > section :is(h2, marp-h2){font-size:1.5em}div#\:\$p > svg > foreignObject > section :is(h3, marp-h3){font-size:1.3em}div#\:\$p > svg > foreignObject > section :is(h4, marp-h4){font-size:1.1em}div#\:\$p > svg > foreignObject > section :is(h5, marp-h5){font-size:1em}div#\:\$p > svg > foreignObject > section :is(h6, marp-h6){font-size:.9em}div#\:\$p > svg > foreignObject > section blockquote,div#\:\$p > svg > foreignObject > section p{margin:1em 0 0}div#\:\$p > svg > foreignObject > section ol>li,div#\:\$p > svg > foreignObject > section ul>li{margin:.3em 0 0}div#\:\$p > svg > foreignObject > section ol>li>p,div#\:\$p > svg > foreignObject > section ul>li>p{margin:.6em 0 0}div#\:\$p > svg > foreignObject > section code{display:inline-block;font-family:Roboto Mono,monospace;font-size:.8em;letter-spacing:0;margin:-.1em .15em;padding:.1em .2em;vertical-align:baseline}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre){display:block;margin:1em 0 0;overflow:visible}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre) code{box-sizing:border-box;font-size:.7em;margin:0;min-width:100%;padding:.5em}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre)::part(auto-scaling){max-height:calc(580px - 1em)}div#\:\$p > svg > foreignObject > section blockquote{margin:1em 0 0;padding:0 1em;position:relative}div#\:\$p > svg > foreignObject > section blockquote:after,div#\:\$p > svg > foreignObject > section blockquote:before{content:"“";display:block;font-family:Times New Roman,serif;font-weight:700;position:absolute}div#\:\$p > svg > foreignObject > section blockquote:before{left:0;top:0}div#\:\$p > svg > foreignObject > section blockquote:after{bottom:0;right:0;transform:rotate(180deg)}div#\:\$p > svg > foreignObject > section blockquote>:first-child{margin-top:0}div#\:\$p > svg > foreignObject > section mark{background:transparent}div#\:\$p > svg > foreignObject > section table{border-collapse:collapse;border-spacing:0;margin:1em 0 0}div#\:\$p > svg > foreignObject > section table td,div#\:\$p > svg > foreignObject > section table th{border-style:solid;border-width:1px;padding:.2em .4em}div#\:\$p > svg > foreignObject > section footer,div#\:\$p > svg > foreignObject > section header,div#\:\$p > svg > foreignObject > section:after{box-sizing:border-box;font-size:66%;height:70px;line-height:50px;overflow:hidden;padding:10px 25px;position:absolute}div#\:\$p > svg > foreignObject > section:after{--marpit-root-font-size:66%;}div#\:\$p > svg > foreignObject > section header{top:0}div#\:\$p > svg > foreignObject > section footer,div#\:\$p > svg > foreignObject > section header{left:0;right:0}div#\:\$p > svg > foreignObject > section footer{bottom:0}div#\:\$p > svg > foreignObject > section{background-color:var(--color-background);background-image:linear-gradient(135deg, hsla(0,0%,53%,0), hsla(0,0%,53%,.02) 50%, hsla(0,0%,100%,0) 0, hsla(0,0%,100%,.05));color:var(--color-foreground);font-family:Lato,Avenir Next,Avenir,Trebuchet MS,Segoe UI,sans-serif;font-size:35px;height:720px;letter-spacing:1.25px;line-height:1.35;padding:70px;width:1280px;word-wrap:break-word;--color-background:#fff8e1;--color-background-stripe:rgba(69,90,100,.1);--color-foreground:#455a64;--color-dimmed:#6a7a7d;--color-highlight:#0288d1;}div#\:\$p > svg > foreignObject > section{--marpit-root-font-size:35px;}div#\:\$p > svg > foreignObject > section:after{bottom:0;font-size:80%;right:0}div#\:\$p > svg > foreignObject > section:after{--marpit-root-font-size:80%;}div#\:\$p > svg > foreignObject > section a,div#\:\$p > svg > foreignObject > section mark{color:var(--color-highlight)}div#\:\$p > svg > foreignObject > section code{background:var(--color-dimmed);color:var(--color-background)}div#\:\$p > svg > foreignObject > section :is(h1, marp-h1) strong,div#\:\$p > svg > foreignObject > section :is(h2, marp-h2) strong,div#\:\$p > svg > foreignObject > section :is(h3, marp-h3) strong,div#\:\$p > svg > foreignObject > section :is(h4, marp-h4) strong,div#\:\$p > svg > foreignObject > section :is(h5, marp-h5) strong,div#\:\$p > svg > foreignObject > section :is(h6, marp-h6) strong{color:var(--color-highlight)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre){background:var(--color-foreground)}div#\:\$p > svg > foreignObject > section :is(pre, marp-pre)>code{background:transparent}div#\:\$p > svg > foreignObject > section blockquote:after,div#\:\$p > svg > foreignObject > section blockquote:before,div#\:\$p > svg > foreignObject > section footer,div#\:\$p > svg > foreignObject > section header,div#\:\$p > svg > foreignObject > section section:after{color:var(--color-dimmed)}div#\:\$p > svg > foreignObject > section table td,div#\:\$p > svg > foreignObject > section table th{border-color:var(--color-foreground)}div#\:\$p > svg > foreignObject > section table thead th{background:var(--color-foreground);color:var(--color-background)}div#\:\$p > svg > foreignObject > section table tbody>tr:nth-child(odd) td,div#\:\$p > svg > foreignObject > section table tbody>tr:nth-child(odd) th{background:var(--color-background-stripe, transparent)}div#\:\$p > svg > foreignObject > section>:first-child,div#\:\$p > svg > foreignObject > section>header:first-child+*{margin-top:0}div#\:\$p > svg > foreignObject > section:where(.invert){--color-background:#455a64;--color-background-stripe:rgba(255,248,225,.1);--color-foreground:#fff8e1;--color-dimmed:#dad8c8;--color-highlight:#81d4fa;}div#\:\$p > svg > foreignObject > section:where(.gaia){--color-background:#0288d1;--color-background-stripe:rgba(255,248,225,.1);--color-foreground:#fff8e1;--color-dimmed:#cce2de;--color-highlight:#81d4fa;}div#\:\$p > svg > foreignObject > section:where(.lead){align-items:stretch;flex-flow:column nowrap;place-content:safe center center}div#\:\$p > svg > foreignObject > section:where(.lead) :is(h1, marp-h1),div#\:\$p > svg > foreignObject > section:where(.lead) :is(h2, marp-h2),div#\:\$p > svg > foreignObject > section:where(.lead) :is(h3, marp-h3),div#\:\$p > svg > foreignObject > section:where(.lead) :is(h4, marp-h4),div#\:\$p > svg > foreignObject > section:where(.lead) :is(h5, marp-h5),div#\:\$p > svg > foreignObject > section:where(.lead) :is(h6, marp-h6){text-align:center}div#\:\$p > svg > foreignObject > section:where(.lead) p{text-align:center}div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>:is(h1, marp-h1),div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>:is(h2, marp-h2),div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>:is(h3, marp-h3),div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>:is(h4, marp-h4),div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>:is(h5, marp-h5),div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>:is(h6, marp-h6),div#\:\$p > svg > foreignObject > section:where(.lead) blockquote>p{text-align:left}div#\:\$p > svg > foreignObject > section:where(.lead) ol>li>p,div#\:\$p > svg > foreignObject > section:where(.lead) ul>li>p{text-align:left}div#\:\$p > svg > foreignObject > section:where(.lead) table{margin-left:auto;margin-right:auto}div#\:\$p > svg > foreignObject > section[data-marpit-scope-y727au9b] .columns{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-uN8TKVJY] .columns{display:grid;grid-template-columns:3fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-moX5jymP] .columns{display:grid;grid-template-columns:3fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-AUw1fKy1] table{font-size:0.7em}div#\:\$p > svg > foreignObject > section[data-marpit-scope-AUw1fKy1] .columns{display:grid;grid-template-columns:3fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-IWenV49H] table{font-size:0.7em}div#\:\$p > svg > foreignObject > section[data-marpit-scope-39z8XgP2] table{font-size:0.6em}div#\:\$p > svg > foreignObject > section[data-marpit-scope-EFUQia2U] li{font-size:0.8em}div#\:\$p > svg > foreignObject > section[data-marpit-scope-HgOzF42f] .columns{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-JgrCUfCJ] .columns{display:grid;grid-template-columns:3fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-q1UU7n2e] .columns{display:grid;grid-template-columns:1fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-O2hrcYOr] .columns{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-c3ZTroYQ] .columns{display:grid;grid-template-columns:1fr 1fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-scope-lp1ZcjI0] .columns{display:grid;grid-template-columns:1fr 2fr;gap:calc(var(--marpit-root-font-size, 1rem) * 2)}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"]{columns:initial!important;display:block!important;padding:0!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"]::before, div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"]::after, div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="content"]::before, div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="content"]::after{display:none!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container]{all:initial;display:flex;flex-direction:row;height:100%;overflow:hidden;width:100%}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container][data-marpit-advanced-background-direction="vertical"]{flex-direction:column}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"][data-marpit-advanced-background-split] > div[data-marpit-advanced-background-container]{width:var(--marpit-advanced-background-split, 50%)}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"][data-marpit-advanced-background-split="right"] > div[data-marpit-advanced-background-container]{margin-left:calc(100% - var(--marpit-advanced-background-split, 50%))}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] > figure{all:initial;background-position:center;background-repeat:no-repeat;background-size:cover;flex:auto;margin:0}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="background"] > div[data-marpit-advanced-background-container] > figure > figcaption{position:absolute;border:0;clip:rect(0, 0, 0, 0);height:1px;margin:-1px;overflow:hidden;padding:0;white-space:nowrap;width:1px}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="content"], div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="pseudo"]{background:transparent!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background="pseudo"], div#\:\$p > svg[data-marpit-svg] > foreignObject[data-marpit-advanced-background="pseudo"]{pointer-events:none!important}div#\:\$p > svg > foreignObject > section[data-marpit-advanced-background-split]{width:100%;height:100%}
</style></head><body><div class="bespoke-marp-osc"><button data-bespoke-marp-osc="prev" tabindex="-1" title="Previous slide">Previous slide</button><span data-bespoke-marp-osc="page"></span><button data-bespoke-marp-osc="next" tabindex="-1" title="Next slide">Next slide</button><button data-bespoke-marp-osc="fullscreen" tabindex="-1" title="Toggle fullscreen (f)">Toggle fullscreen</button><button data-bespoke-marp-osc="presenter" tabindex="-1" title="Open presenter view (p)">Open presenter view</button></div><div id=":$p"><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="1" data-paginate="true" data-class="lead" data-theme="gaia" lang="zh-CN" class="lead" data-marpit-pagination="1" style="--paginate:true;--class:lead;--theme:gaia;" data-marpit-pagination-total="52">
<h1 id="%E8%BD%AF%E4%BB%B6%E6%8A%80%E6%9C%AF%E5%9F%BA%E7%A1%80">软件技术基础</h1>
<h2 id="%E6%96%87%E4%BB%B6">文件</h2>
<p><strong>施展</strong><br />
武汉光电国家研究中心 & 计算机学院<br />
华中科技大学</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="2" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="2" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5">文件基本概念</h2>
<ul>
<li><strong>变量</strong>和<strong>数组</strong>中的数据存放于<strong>内存</strong>,随程序结束而消失</li>
<li><strong>文件</strong>用于永久保存大量数据</li>
<li>文件位于<strong>外存</strong>(如硬盘、固态盘、光盘)</li>
<li>本章:如何用C程序<strong>建立、更新、处理</strong>数据文件</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="3" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="3" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E4%B8%BB%E8%A6%81%E5%86%85%E5%AE%B9">主要内容</h2>
<ul>
<li>文件的打开与关闭<br />
<code>fopen</code>、<code>fclose</code>、<code>freopen</code> 函数</li>
<li>文本文件的读写<br />
<code>fgetc</code>、<code>fputc</code>、<code>fgets</code>、<code>fputs</code>、<code>fprintf</code>、<code>fscanf</code> 等函数</li>
<li>二进制文件的读写<br />
<code>fread</code>、<code>fwrite</code> 函数</li>
<li>文件的随机读写<br />
<code>fseek</code>、<code>rewind</code>、<code>ftell</code>、<code>fsetpos</code>、<code>fgetpos</code> 等文件指针定位函数</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="4" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="4" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E5%9C%BA%E6%99%AF%E9%97%AE%E9%A2%98">场景问题</h2>
<blockquote>
<p>从键盘输入若干行字符,保存到 <code>d:\a.txt</code> 中,该如何做?</p>
</blockquote>
<p><img src="images/c-file-fig-01.svg" alt="" style="width:600px;" /></p>
<h3 id="%E6%96%B9%E6%A1%88savefileexe-%E8%BF%90%E8%A1%8C%E7%A4%BA%E6%84%8F">方案:<strong>savefile.exe</strong> 运行示意</h3>
<p><img src="images/c-file-fig-02.svg" alt="" style="width:600px;" /></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="5" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="5" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E7%A4%BA%E4%BE%8B%E5%B0%86%E9%94%AE%E7%9B%98%E8%BE%93%E5%85%A5%E5%86%99%E5%85%A5%E6%96%87%E4%BB%B6">示例:将键盘输入写入文件</h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">()</span> {
FILE *fp;
<span class="hljs-type">char</span> ch;
<span class="hljs-keyword">if</span> ((fp = fopen(<span class="hljs-string">"d:\\a.txt"</span>, <span class="hljs-string">"w"</span>)) == <span class="hljs-literal">NULL</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"can't open the file!"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
}
<span class="hljs-keyword">while</span> ((ch = getchar()) != EOF)
fputc(ch, fp);
fclose(fp);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="6" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="6" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C%E6%AD%A5%E9%AA%A4">文件操作步骤</h2>
<ol>
<li><strong>打开文件</strong> —— 建立文件指针与文件间联系</li>
<li>通过<strong>文件指针</strong>对文件进行读写操作</li>
<li><strong>关闭文件</strong> —— 取消文件指针与文件间的联系</li>
</ol>
<p><strong>提示</strong>:打开文件时,就已确定文件读写格式和读写方式!</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="7" data-marpit-scope-y727au9b="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="7" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%89%93%E5%BC%80%E6%96%87%E4%BB%B6%E5%87%BD%E6%95%B0-fopen">打开文件函数 <code>fopen()</code></h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c">FILE *<span class="hljs-title function_">fopen</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *filename, <span class="hljs-type">const</span> <span class="hljs-type">char</span> *mode)</span>;
</code></pre>
<p>按照<code>mode</code>方式打开文件<code>filename</code><br />
成功:返回文件指针<br />
失败:返回<code>NULL</code></p>
<div class="columns">
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c">FILE *fp;
fp=fopen(<span class="hljs-string">"c:\\test.txt"</span>, <span class="hljs-string">"w"</span>);
</code></pre>
</div>
<div>
<p><img src="images/c-file-fig-03.svg" alt="" style="height:200px;" /></p>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="8" data-marpit-scope-uN8TKVJY="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="8" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E7%BB%93%E6%9E%84%E4%BD%93">文件结构体</h2>
<div class="columns">
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">iobuf</span> {</span>
<span class="hljs-type">char</span> *_ptr; <span class="hljs-comment">// 文件当前读写位置指针</span>
<span class="hljs-type">int</span> _cnt; <span class="hljs-comment">// 当前读写位置剩余字节数</span>
<span class="hljs-type">char</span> *_base; <span class="hljs-comment">// 文件缓冲区起始位置</span>
<span class="hljs-type">int</span> _flag; <span class="hljs-comment">// 文件状态标志</span>
<span class="hljs-type">int</span> _file; <span class="hljs-comment">// 文件描述符</span>
<span class="hljs-type">int</span> _charbuf; <span class="hljs-comment">// 跟踪缓冲区状态</span>
<span class="hljs-type">int</span> _bufsiz; <span class="hljs-comment">// 文件缓冲区大小</span>
<span class="hljs-type">char</span> *_tmpfname; <span class="hljs-comment">// 临时文件名</span>
};
<span class="hljs-keyword">typedef</span> <span class="hljs-class"><span class="hljs-keyword">struct</span> _<span class="hljs-title">iobuf</span> <span class="hljs-title">FILE</span>;</span>
</code></pre>
</div>
<div>
<p><code>FILE</code>是<code>stdio.h</code>中定义的结构类型,记录一个文件的相关信息。</p>
<p>←<strong>文件描述符</strong>是个普通整数,用以标明每一个被打开的文件。第一个打开的文件是0,第二个是1,依此类推。</p>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="9" data-marpit-scope-moX5jymP="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="9" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E6%8C%87%E9%92%88">文件指针</h2>
<div class="columns">
<div>
<p>程序中仅用<code>FILE *</code>型变量: FILE指针</p>
<p><img src="images/c-file-fig-04.svg" alt="" style="height:380px;" /></p>
</div>
<div>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="10" data-marpit-scope-AUw1fKy1="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="10" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E6%8C%87%E9%92%88-%E6%A0%87%E5%87%86%E6%96%87%E4%BB%B6">文件指针: <strong>标准文件</strong></h2>
<div class="columns">
<div>
<p>程序中仅用<code>FILE *</code>型变量: FILE指针</p>
<p><img src="images/c-file-fig-04.svg" alt="" style="height:380px;" /></p>
</div>
<div>
<p>C程序会自动打开3个标准文件</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">define</span> stdin (&_iob[0])</span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> stdout (&_iob[1])</span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> stderr (&_iob[2])</span>
</code></pre>
<table>
<thead>
<tr>
<th style="text-align:center">标准文件</th>
<th style="text-align:center">文件指针</th>
<th style="text-align:center">默认值</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">标准输入文件</td>
<td style="text-align:center">stdin</td>
<td style="text-align:center">键盘</td>
</tr>
<tr>
<td style="text-align:center">标准输出文件</td>
<td style="text-align:center">stdout</td>
<td style="text-align:center">显示器</td>
</tr>
<tr>
<td style="text-align:center">标准错误文件</td>
<td style="text-align:center">stderr</td>
<td style="text-align:center">显示器</td>
</tr>
</tbody>
</table>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="11" data-marpit-scope-IWenV49H="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="11" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%89%93%E5%BC%80%E6%96%B9%E5%BC%8F-mode">打开方式 <code>mode</code></h2>
<p>模式字符串由 <strong>访问权限</strong> + <strong>文本/二进制标识</strong> 组合而成,核心标识如下:</p>
<table>
<thead>
<tr>
<th>模式字符</th>
<th>核心功能</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>r</code></td>
<td>只读(Read):打开已存在的文件,文件不存在则报错(<code>fopen</code> 返回 <code>NULL</code>)</td>
</tr>
<tr>
<td><code>w</code></td>
<td>只写(Write):创建新文件;若文件已存在,<strong>清空原有内容</strong>(覆盖)</td>
</tr>
<tr>
<td><code>a</code></td>
<td>追加(Append):创建新文件;若文件已存在,写入内容追加到文件末尾</td>
</tr>
<tr>
<td><code>+</code></td>
<td>读写扩展:附加在 <code>r/w/a</code> 后,开启“读+写”双权限(如 <code>r+</code> 表示读写)</td>
</tr>
<tr>
<td><code>t</code></td>
<td>文本模式(Text):<strong>默认模式</strong>(可省略),换行符会自动转换(<code>\n</code> 系统换行符)</td>
</tr>
<tr>
<td><code>b</code></td>
<td>二进制模式(Binary):不转换换行符,按字节原样读写(如图片、视频文件)</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="12" data-marpit-scope-39z8XgP2="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="12" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%89%93%E5%BC%80%E6%96%B9%E5%BC%8F-mode-%E5%B8%B8%E7%94%A8%E7%BB%84%E5%90%88">打开方式 <code>mode</code> <strong>常用组合</strong></h2>
<table>
<thead>
<tr>
<th>完整模式</th>
<th>权限类型</th>
<th>文件不存在时</th>
<th>已存在文件时</th>
<th>适用场景</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>r</code></td>
<td>只读</td>
<td>报错(NULL)</td>
<td>正常打开,读文件</td>
<td>读取配置文件、日志文件等</td>
</tr>
<tr>
<td><code>w</code></td>
<td>只写</td>
<td>创建文件</td>
<td>清空内容(覆盖)</td>
<td>生成新文件(如导出报表、日志)</td>
</tr>
<tr>
<td><code>a</code></td>
<td>只写(追加)</td>
<td>创建文件</td>
<td>内容追加到末尾</td>
<td>日志追加、累计数据写入</td>
</tr>
<tr>
<td><code>r+</code></td>
<td>读写</td>
<td>报错(NULL)</td>
<td>保留原有内容</td>
<td>读写已存在的文件(不覆盖)</td>
</tr>
<tr>
<td><code>w+</code></td>
<td>读写</td>
<td>创建文件</td>
<td>清空内容(覆盖)</td>
<td>新建可读写文件(如临时文件)</td>
</tr>
<tr>
<td><code>a+</code></td>
<td>读写(追加)</td>
<td>创建文件</td>
<td>读:从开头读;写:追加到末尾</td>
<td>既要读历史内容,又要追加新内容</td>
</tr>
<tr>
<td><code>rb</code></td>
<td>二进制只读</td>
<td>报错(NULL)</td>
<td>按字节读文件</td>
<td>读取图片、音频、二进制数据</td>
</tr>
<tr>
<td><code>wb</code></td>
<td>二进制只写</td>
<td>创建文件</td>
<td>清空并按字节写</td>
<td>写入图片、视频等二进制文件</td>
</tr>
<tr>
<td><code>ab</code></td>
<td>二进制追加</td>
<td>创建文件</td>
<td>字节数据追加到末尾</td>
<td>追加二进制日志、数据流</td>
</tr>
<tr>
<td><code>rb+</code>/<code>wb+</code>/<code>ab+</code></td>
<td>二进制读写</td>
<td>同对应文本模式</td>
<td>同对应文本模式</td>
<td>二进制文件的读写操作</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="13" data-marpit-scope-EFUQia2U="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="13" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%89%93%E5%BC%80%E6%96%B9%E5%BC%8F-mode-%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9">打开方式 <code>mode</code> <strong>注意事项</strong></h2>
<ol>
<li><strong>模式大小写敏感</strong>:必须小写(如 <code>R</code>/<code>W</code> 是错误的)。</li>
<li><strong>文本模式与二进制模式的区别</strong>:
<ul>
<li>文本模式(<code>t</code> 或省略):Windows 系统中,<code>\n</code> 会自动转为 <code>\r\n</code>(换行+回车),读取时反向转换;Linux/Mac 无此转换。</li>
<li>二进制模式(<code>b</code>):完全按字节读写,不做任何转换,<strong>必须用于非文本文件</strong>(图片、压缩包等),否则会导致文件损坏。</li>
</ul>
</li>
<li><strong><code>r+</code> 与 <code>w+</code> 的核心差异</strong>:
<ul>
<li><code>r+</code> 要求文件已存在,不会清空内容;</li>
<li><code>w+</code> 无论文件是否存在,都会创建新文件(覆盖原有)。</li>
</ul>
</li>
<li><strong><code>a+</code> 的特殊行为</strong>:写入时永远追加到末尾,但读取时可以从文件开头开始(需手动调整文件指针,如 <code>fseek</code>)。</li>
<li><strong>模式兼容性</strong>:部分系统(如 Linux)不区分文本/二进制模式(<code>t</code>/<code>b</code> 无实际效果),但为了跨平台兼容,建议明确指定(文本文件省略 <code>t</code>,二进制文件加 <code>b</code>)。</li>
</ol>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="14" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="14" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E5%85%B3%E9%97%AD%E6%96%87%E4%BB%B6%E5%87%BD%E6%95%B0-fclose">关闭文件函数 <code>fclose()</code></h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> <span class="hljs-title function_">fclose</span><span class="hljs-params">(FILE *stream)</span>;
</code></pre>
<p>关闭成功返回 <code>0</code>,失败返回 <code>EOF(-1)</code></p>
<p><img src="images/c-file-fig-05.svg" alt="" style="height:300px;" /></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="15" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="15" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E5%AD%97%E7%AC%A6%E8%AF%BB%E5%86%99%E5%87%BD%E6%95%B0">字符读写函数</h2>
<ul>
<li><code>int fgetc(FILE *stream);</code>
<ul>
<li>从输入流<code>stream</code>当前位置读取一个字符,读写位置后移一个字符,返回读取的字符。到文件尾或读操作出错时返回<code>EOF</code>。</li>
</ul>
</li>
<li><code>int fputc(int c, FILE *stream);</code>
<ul>
<li>参数<code>c</code>转换成为<code>unsigned char</code>类型然后写到输出流<code>stream</code>的当前位置处。返回被写字符;如果写操作出错或遇到文件尾返回<code>EOF</code>。</li>
</ul>
</li>
</ul>
<p><code>fgetc(stdin)</code> 即 <code>getchar()</code><br />
<code>fputc(c, stdout)</code> 即 <code>putchar(c)</code></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="16" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="16" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%93%8D%E4%BD%9C%E6%A0%87%E5%87%86%E8%BE%93%E5%85%A5%E5%92%8C%E8%BE%93%E5%87%BA%E6%96%87%E4%BB%B6">操作<strong>标准输入和输出</strong>文件</h2>
<ul>
<li><code>getchar</code>、<code>gets</code>和<code>scanf</code>函数从<code>stdin</code>文件读数据</li>
<li><code>putchar</code>、<code>puts</code>和<code>printf</code>函数向<code>stdout</code>文件写数据</li>
<li><code>freopen</code>函数可以重定向<code>stdin</code>和<code>stdout</code>,如:
<ul>
<li><code>freopen("d:\\a.txt", "r", stdin);</code> 重定向输入
<ul>
<li>将原本从键盘输入的数据将改为从"d:\a.txt"文件中读取</li>
<li><strong>常用于</strong>: 测试输入数据,尤其是批量重复性检验</li>
</ul>
</li>
<li><code>freopen("d:\\a.txt", "w", stdout);</code> 重定向输出
<ul>
<li>将原本向屏幕输出的数据改为向"d:\a.txt"文件中写入</li>
<li><strong>常用于</strong>: 记录输出数据,方便集中观察分析</li>
</ul>
</li>
</ul>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="17" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="17" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E9%87%8D%E5%AE%9A%E5%90%91%E5%87%BD%E6%95%B0-freopen">文件重定向函数 <code>freopen()</code></h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c">FILE *<span class="hljs-title function_">freopen</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *filename, <span class="hljs-type">const</span> <span class="hljs-type">char</span> *mode, FILE *fp)</span>;
</code></pre>
<p>相当于:</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c">fclose(fp);
fp = fopen(filename, mode);
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="18" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="18" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E4%BD%BF%E7%94%A8-freopen-%E9%87%8D%E5%AE%9A%E5%90%91%E8%BE%93%E5%87%BA">使用 <code>freopen</code> 重定向输出</h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> {
<span class="hljs-type">char</span> ch;
<span class="hljs-keyword">if</span> (freopen(<span class="hljs-string">"d:\\a.txt"</span>, <span class="hljs-string">"w"</span>, <span class="hljs-built_in">stdout</span>) == <span class="hljs-literal">NULL</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"can't open the file!"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
}
<span class="hljs-keyword">while</span> ((ch = getchar()) != EOF)
<span class="hljs-built_in">putchar</span>(ch);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="19" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="19" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E8%AF%BB%E5%8F%96%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%B9%B6%E6%98%BE%E7%A4%BA">读取文件内容并显示</h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> {
FILE *fp;
<span class="hljs-type">char</span> ch;
<span class="hljs-keyword">if</span> ((fp = fopen(<span class="hljs-string">"d:\\a.txt"</span>, <span class="hljs-string">"r"</span>)) == <span class="hljs-literal">NULL</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"can't open the file!"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
}
<span class="hljs-keyword">while</span> ((ch = fgetc(fp)) != EOF)
<span class="hljs-built_in">putchar</span>(ch); <span class="hljs-comment">/* 也可用 fputc(ch, stdout); */</span>
fclose(fp);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="20" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="20" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E9%87%8D%E5%AE%9A%E5%90%91%E8%AF%BB%E5%8F%96%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9%E5%B9%B6%E6%98%BE%E7%A4%BA"><strong>重定向</strong>读取文件内容并显示</h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> {
<span class="hljs-type">char</span> ch;
<span class="hljs-keyword">if</span> (freopen(<span class="hljs-string">"d:\\a.txt"</span>, <span class="hljs-string">"r"</span>,<span class="hljs-built_in">stdin</span>) == <span class="hljs-literal">NULL</span>) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"can't open the file!"</span>);
<span class="hljs-keyword">return</span> <span class="hljs-number">-1</span>;
}
<span class="hljs-keyword">while</span>((ch = getchar()) != EOF)
<span class="hljs-built_in">putchar</span>(ch);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="21" data-marpit-scope-HgOzF42f="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="21" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E5%AD%97%E7%AC%A6%E4%B8%B2%E8%AF%BB%E5%86%99%E5%87%BD%E6%95%B0">字符串读写函数</h2>
<ul>
<li><code>char *fgets(char *s, int n, FILE *stream);</code>
<ul>
<li>从输入流<code>stream</code>当前位置读取一个字符串(<code>strlen(s) < n</code>>),返回读取的字符串。到文件尾或读操作出错时返回<code>NULL</code>。</li>
</ul>
</li>
<li><code>int fputs(const char *s, FILE *stream);</code>
<ul>
<li>参数<code>s</code>写入输出流<code>stream</code>的当前位置处。返回被写入的字符数,如果写操作出错或遇到文件尾返回<code>EOF</code>。</li>
</ul>
</li>
</ul>
<div class="columns">
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">char</span> s[<span class="hljs-number">10</span>]; <span class="hljs-comment">// 输入:hust</span>
fgets(s, <span class="hljs-number">10</span>, <span class="hljs-built_in">stdin</span>); <span class="hljs-comment">// 换行符被读入</span>
gets(s); <span class="hljs-comment">// 换行符不被读入</span>
</code></pre>
</div>
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-built_in">fputs</span>(<span class="hljs-string">"hust"</span>, <span class="hljs-built_in">stdout</span>); <span class="hljs-comment">// 输出:hust</span>
<span class="hljs-built_in">puts</span>(<span class="hljs-string">"hust"</span>); <span class="hljs-comment">// 追加输出换行符:hust</span>
</code></pre>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="22" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="22" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%A0%BC%E5%BC%8F%E8%AF%BB%E5%86%99%E5%87%BD%E6%95%B0">格式读写函数</h2>
<ul>
<li><code>int fprintf(FILE *stream, const char *format, …);</code>
<ul>
<li>将输出参数列表中的数据按指定的格式写入到<code>stream</code>流中。写操作正常返回<strong>输出字符个数</strong>,写操作出错时返回负值。</li>
</ul>
</li>
<li><code>int fscanf(FILE *stream, const char *format, …);</code>
<ul>
<li>从<code>stream</code>流中,按指定的格式读去数据,并赋值给相应的参数变量。函数返回<strong>已输入项数</strong>,如果读操作出错返回<code>EOF</code>。</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>等价关系</th>
<th>说明</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>fscanf(stdin, "%d", &x)</code></td>
<td><code>scanf("%d", &x)</code></td>
</tr>
<tr>
<td><code>fprintf(stdout, "%d", x)</code></td>
<td><code>printf("%d", x)</code></td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="23" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="23" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E7%9A%84%E5%A4%8D%E5%88%B6">文本文件的复制</h2>
<ul>
<li>Windows 命令行:
<ul>
<li><code>copy source_file target_file</code> 命令</li>
</ul>
</li>
<li>Linux 命令行:
<ul>
<li><code>cp source_file target_file</code> 命令</li>
</ul>
</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="24" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="24" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdlib.h></span></span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">int</span> argc, <span class="hljs-type">char</span>* argv[])</span> {
<span class="hljs-type">int</span> ch;
FILE *fpin,*fpout;
<span class="hljs-keyword">if</span>(argc!=<span class="hljs-number">3</span>) { <span class="hljs-comment">/*命令行参数数目不等于3,说明命令行格式不对*/</span>
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Arguments error!\n"</span>);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
}
<span class="hljs-keyword">if</span>((fpin=fopen(argv[<span class="hljs-number">1</span>],<span class="hljs-string">"r"</span>))==<span class="hljs-literal">NULL</span>) { <span class="hljs-comment">/* fpin指向source_file */</span>
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Can't open %s file!\n"</span>,argv[<span class="hljs-number">1</span>]);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
}
<span class="hljs-keyword">if</span>((fpout=fopen(argv[<span class="hljs-number">2</span>],<span class="hljs-string">"w"</span>))==<span class="hljs-literal">NULL</span>) { <span class="hljs-comment">/* fpout指向target_file */</span>
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"Can't open %s file!\n"</span>,argv[<span class="hljs-number">2</span>]);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
}
<span class="hljs-keyword">while</span>((ch=fgetc(fpin))!=EOF) <span class="hljs-comment">/* 从source_file中读字符 */</span>
fputc(ch,fpout); <span class="hljs-comment">/* 向target_file中写字符,实现拷贝复制 */</span>
fclose(fpin); <span class="hljs-comment">/* 关闭source_file */</span>
fclose(fpout); <span class="hljs-comment">/* 关闭target_file */</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="25" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="25" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E7%9A%84%E5%88%86%E8%A7%A3">文本文件的分解</h2>
<p>将一个大的文本文件以行为单位分解成为若干个较小的文本文件,文件名和分解的行数都由用户从命令行输入。</p>
<p>命令行:</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-bash">parts abc.txt a.txt b.txt c.txt 10
</code></pre>
<blockquote>
<p>把 <code>abc.txt</code> 每 10 行切成一个小文件</p>
</blockquote>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="26" data-marpit-scope-JgrCUfCJ="" data-marpit-fragments="5" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="26" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E5%88%86%E8%A7%A3%E6%B5%81%E7%A8%8B">分解流程</h3>
<div class="columns">
<div>
<ol start="0">
<li data-marpit-fragment="1">命令行: <code>parts abc.txt a.txt b.txt c.txt 10</code></li>
<li data-marpit-fragment="2"><code>len=</code>命令行中提取的行数<code>atoi(argv[argc-1])</code></li>
<li data-marpit-fragment="3">以读方式打开源文件<code>fopen(argv[1], "r")</code></li>
<li data-marpit-fragment="4">依次打开目标文件,从源文件读<code>len</code>行写入<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-keyword">for</span>(i = <span class="hljs-number">2</span>; i < argc<span class="hljs-number">-1</span>; i++) {
以写方式打开文件 argv[i]
从argv[<span class="hljs-number">1</span>]读<span class="hljs-number">1</span>行写入argv[i]直到写了len行或源文件到文件尾
关闭 文件argv[i]
}
</code></pre>
</li>
<li data-marpit-fragment="5">关闭源文件<code>argv[1]</code></li>
</ol>
</div>
<div>
<p><img src="images/c-file-fig-06.svg" alt="" style="width:200px;" /></p>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="27" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="27" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdlib.h></span></span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">int</span> argc,<span class="hljs-type">char</span> *argv[])</span> {
FILE *fin, *fout;
<span class="hljs-type">int</span> len = atoi(argv[argc<span class="hljs-number">-1</span>]);<span class="hljs-comment">/*将行数字符串转换为整数*/</span>
<span class="hljs-type">int</span> i, j;
<span class="hljs-type">char</span> a[<span class="hljs-number">81</span>];
<span class="hljs-keyword">if</span>((fin = fopen(argv[<span class="hljs-number">1</span>], <span class="hljs-string">"r"</span>)) == <span class="hljs-literal">NULL</span>){
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"can't open the %s file!\n"</span>, argv[<span class="hljs-number">1</span>]);
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
}
<span class="hljs-keyword">for</span>(i = <span class="hljs-number">2</span>; i < argc<span class="hljs-number">-1</span>; i++){
fout = fopen(argv[i], <span class="hljs-string">"w"</span>);<span class="hljs-comment">/*打开argv[i]指定的文件进行写操作*/</span>
j=<span class="hljs-number">0</span>;
<span class="hljs-keyword">while</span>((fgets(a, <span class="hljs-number">80</span>, fin)!= <span class="hljs-literal">NULL</span>) && j++<len)<span class="hljs-comment">/*从fin中读一行到a中*/</span>
<span class="hljs-built_in">fputs</span>(a, fout);<span class="hljs-comment">/*将a中字符串写到fout中*/</span>
fclose(fout);<span class="hljs-comment">/*写满len行后关闭文件*/</span>
}
fclose(fin);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="28" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="28" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%E4%B8%8E%E5%A4%84%E7%90%86%E7%A8%8B%E5%BA%8F">数据采集与处理程序</h2>
<p>键盘输入: 商品名称、数量、单价 → 计算总金额 → 数据保存到 <code>d:\goods.txt</code></p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdlib.h></span></span>
<span class="hljs-type">void</span> <span class="hljs-title function_">data_write</span><span class="hljs-params">(<span class="hljs-type">char</span> *)</span>; <span class="hljs-comment">/* 数据采集并存盘 */</span>
<span class="hljs-type">void</span> <span class="hljs-title function_">data_cal</span><span class="hljs-params">(<span class="hljs-type">char</span> *, <span class="hljs-type">float</span>)</span>; <span class="hljs-comment">/* 从文件读入数据并进行计算 */</span>
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> {
<span class="hljs-type">char</span> a[<span class="hljs-number">20</span>] = <span class="hljs-string">"d:\\goods.txt"</span>;
data_write(a);
data_cal(a);
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="29" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="29" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="data_write%E8%BE%93%E5%85%A5%E5%B9%B6%E4%BF%9D%E5%AD%98">data_write:输入并保存</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">void</span> <span class="hljs-title function_">data_write</span><span class="hljs-params">(<span class="hljs-type">char</span> *filename)</span> {
FILE *out;
<span class="hljs-type">char</span> name[<span class="hljs-number">20</span>];
<span class="hljs-type">int</span> number;
<span class="hljs-type">float</span> price;
<span class="hljs-keyword">if</span> ((out = fopen(filename, <span class="hljs-string">"w"</span>)) == <span class="hljs-literal">NULL</span>)
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
<span class="hljs-built_in">puts</span>(<span class="hljs-string">"input name、number and price please!"</span>);
<span class="hljs-keyword">while</span> (<span class="hljs-built_in">scanf</span>(<span class="hljs-string">"%s%d%f"</span>, name, &number, &price) != EOF) <span class="hljs-comment">// 输入由用户分隔</span>
<span class="hljs-built_in">fprintf</span>(out, <span class="hljs-string">"%s %d %f\n"</span>, name, number, price); <span class="hljs-comment">// 输出也要自备空格</span>
fclose(out);
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="30" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="30" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="data_cal%E8%AF%BB%E5%8F%96%E5%B9%B6%E8%AE%A1%E7%AE%97">data_cal:读取并计算</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">void</span> <span class="hljs-title function_">data_cal</span><span class="hljs-params">(<span class="hljs-type">char</span> *filename)</span> {
FILE *in;
<span class="hljs-type">char</span> name[<span class="hljs-number">5</span>];
<span class="hljs-type">int</span> number;
<span class="hljs-type">float</span> price;
<span class="hljs-keyword">if</span> ((in = fopen(filename, <span class="hljs-string">"r"</span>)) == <span class="hljs-literal">NULL</span>)
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
<span class="hljs-keyword">while</span> (<span class="hljs-built_in">fscanf</span>(in, <span class="hljs-string">"%s%d%f"</span>, name, &number, &price) != EOF)
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%s\t%d\t%8.2f\n"</span>, name, number, price * number);
fclose(in);
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="31" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="31" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E6%9C%AC%E6%96%87%E4%BB%B6%E6%95%B0%E6%8D%AE%E7%9A%84%E9%97%B4%E9%9A%94%E7%AC%A6">文本文件数据的间隔符</h2>
<p>写入多个数据时需加<strong>间隔符</strong>,以便正确读取。</p>
<p>屏幕输出可读性,机器采集便于后续<code>scanf</code>使用。</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-built_in">fprintf</span>(out, <span class="hljs-string">"%s %d\n"</span>, name, number);
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-built_in">fprintf</span>(out, <span class="hljs-string">"%s\t%d\n"</span>, name, number);
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="32" data-marpit-scope-q1UU7n2e="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="32" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B">文件类型</h2>
<p>文件按照数据格式分为<strong>文本文件</strong>和<strong>二进制文件</strong>两类。</p>
<div class="columns">
<div>
<p><strong>文本文件</strong>:</p>
<p>ASCII 字符序列</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-bash"><span class="hljs-comment"># head -n5 README.md</span>
---
license: mit
---
This is a Llama 2 architecture ...
</code></pre>
</div>
<div>
<p><strong>二进制文件</strong>:</p>
<p>与内存内容一致的原始数据序列</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-bash"><span class="hljs-comment"># xxd stories15M.bin | head</span>
00000000: 2001 0000 0003 0000 0600 0000 0600 0000 ...............
00000010: 0600 0000 007d 0000 0001 0000 b00a 75bd .....}........u.
...
</code></pre>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="33" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="33" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E5%AD%98%E5%82%A8%E7%A9%BA%E9%97%B4%E4%B8%BE%E4%BE%8B">存储空间举例</h2>
<blockquote>
<p>短整数 <code>x = 128</code> 分别占多少字节?</p>
</blockquote>
<p><img src="images/c-file-fig-07.svg" alt="" style="width:1000px;" /></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="34" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="34" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E4%BA%8C%E8%BF%9B%E5%88%B6%E6%96%87%E4%BB%B6%E8%AF%BB%E5%86%99">二进制文件读写</h2>
<p>文件直接输入输出又称为文件成组输入输出。</p>
<p>标准C为文件的直接输入输出提供了两个函数<code>fread</code>和<code>fwrite</code>,适用于二进制形式文件的读写 。</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-keyword">typedef</span> <span class="hljs-type">unsigned</span> <span class="hljs-type">int</span> <span class="hljs-type">size_t</span>;
<span class="hljs-type">size_t</span> <span class="hljs-title function_">fread</span><span class="hljs-params">(<span class="hljs-type">void</span> *ptr, <span class="hljs-type">size_t</span> size, <span class="hljs-type">size_t</span> n, FILE *stream)</span>;
<span class="hljs-comment">// ptr: 存储数据的指针,size: 每个元素大小,n: 元素个数,stream: 文件指针</span>
<span class="hljs-comment">// 返回实际读取的元素个数,<n 表示读到文件尾部,返回实际读取的元素个数</span>
<span class="hljs-comment">// 可以通过 feof() 函数判断文件是否读完,ferror() 函数判断文件是否出错</span>
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">size_t</span> <span class="hljs-title function_">fwrite</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">void</span> *ptr, <span class="hljs-type">size_t</span> size, <span class="hljs-type">size_t</span> n, FILE *stream)</span>;
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="35" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="35" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E5%86%99%E7%A4%BA%E4%BE%8B">写示例</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> x[] = {<span class="hljs-number">12</span>, <span class="hljs-number">8</span>, <span class="hljs-number">34</span>, <span class="hljs-number">421</span>};
FILE *fp = fopen(<span class="hljs-string">"d:\\a.dat"</span>, <span class="hljs-string">"wb"</span>);
<span class="hljs-comment">/* 写法 1:一次性写 4 个 int */</span>
fwrite(x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">4</span>, fp);
<span class="hljs-comment">/* 写法 2:循环写 */</span>
<span class="hljs-keyword">for</span> (<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">4</span>; i++)
fwrite(x + i, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
fclose(fp);
</code></pre>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-bash"><span class="hljs-comment"># xxd a.dat</span>
00000000: 0c00 0000 0800 0000 2200 0000 a501 0000 ........<span class="hljs-string">".......
00000010: 0c00 0000 0800 0000 2200 0000 a501 0000 ........"</span>.......
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="36" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="36" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E8%AF%BB%E7%A4%BA%E4%BE%8B">读示例</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> x[<span class="hljs-number">10</span>], i = <span class="hljs-number">0</span>;
FILE *fp = fopen(<span class="hljs-string">"d:\\a.dat"</span>, <span class="hljs-string">"rb"</span>);
<span class="hljs-keyword">while</span> (fread(x + i, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp) == <span class="hljs-number">1</span>)
i++;
fclose(fp);
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="37" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="37" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E6%96%87%E6%9C%AC-vs-%E4%BA%8C%E8%BF%9B%E5%88%B6%E8%AF%BB%E5%8F%96%E5%B7%AE%E5%BC%82">文本 vs 二进制读取差异</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">short</span> x;
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">short</span>), <span class="hljs-number">1</span>, fp); <span class="hljs-comment">// 按二进制读入1个short数</span>
<span class="hljs-comment">// x=0x3231, 低字节在前</span>
<span class="hljs-built_in">fscanf</span>(fp, <span class="hljs-string">"%hd"</span>, &x); <span class="hljs-comment">// 按文本格式读入1个short数</span>
<span class="hljs-comment">// x=123 </span>
</code></pre>
<p><img src="images/c-file-fig-08.svg" alt="" style="width:1000px;" /></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="38" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="38" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E6%96%87%E4%BB%B6%E5%B0%BE%E6%B5%8B%E8%AF%95%E5%87%BD%E6%95%B0feof">文件尾测试函数<code>feof()</code></h3>
<p>文件尾测试函数<code>feof()</code>,如果到文件尾,返回非0值,否则返回0。</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">define</span> _IOEOF 0x0010 </span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> feof(_stream) ((_stream) ->_flag & _IOEOF) </span>
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="39" data-marpit-scope-O2hrcYOr="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="39" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E4%BD%BF%E7%94%A8feof%E6%8E%A7%E5%88%B6%E5%BE%AA%E7%8E%AF">使用<code>feof()</code>控制循环</h3>
<div class="columns">
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> x;
FILE *fp;
fp = fopen(<span class="hljs-string">"d:\\a.dat"</span>, <span class="hljs-string">"rb"</span>);
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
<span class="hljs-keyword">while</span>(!feof(fp)) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d "</span>, x);
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
}
</code></pre>
</div>
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> x;
FILE *fp;
fp = fopen(<span class="hljs-string">"d:\\a.dat"</span>, <span class="hljs-string">"rb"</span>);
<span class="hljs-keyword">while</span>(!feof(fp)) {
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d "</span>, x);
}
</code></pre>
</div>
</div>
<p>从二进制文件读数据显示到屏幕,用哪个?</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="40" data-marpit-scope-c3ZTroYQ="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="40" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E4%BD%BF%E7%94%A8feof%E6%8E%A7%E5%88%B6%E5%BE%AA%E7%8E%AF-1">使用<code>feof()</code>控制循环…</h3>
<div class="columns">
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> x;
FILE *fp;
fp = fopen(<span class="hljs-string">"d:\\a.dat"</span>, <span class="hljs-string">"rb"</span>);
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
<span class="hljs-keyword">while</span>(!feof(fp)) {
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d "</span>, x);
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
}
</code></pre>
</div>
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> x;
FILE *fp;
fp = fopen(<span class="hljs-string">"d:\\a.dat"</span>, <span class="hljs-string">"rb"</span>);
<span class="hljs-keyword">while</span>(!feof(fp)) { <span class="hljs-comment">// 到EOF还会再来</span>
fread(&x, <span class="hljs-keyword">sizeof</span>(<span class="hljs-type">int</span>), <span class="hljs-number">1</span>, fp);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d "</span>, x); <span class="hljs-comment">// 末尾输出2次</span>
}
</code></pre>
</div>
</div>
<p>只有当文件位置指针到了<strong>文件末尾</strong>,然后<strong>再发生读/写操作</strong>时,标志位<code>(fp->_flag)</code>才会被置为含有<code>_IOEOF</code></p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="41" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="41" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%95%B0%E6%8D%AE%E9%87%87%E9%9B%86%E4%B8%8E%E5%A4%84%E7%90%86%E7%A8%8B%E5%BA%8F%E4%BA%8C%E8%BF%9B%E5%88%B6%E7%89%88">数据采集与处理程序<strong>二进制版</strong></h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdio.h></span></span>
<span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><stdlib.h></span></span>
<span class="hljs-comment">// 声明物品信息结构类型struct goods</span>
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">goods</span> {</span>
<span class="hljs-type">long</span> code; <span class="hljs-comment">// 货物编码</span>
<span class="hljs-type">char</span> name[<span class="hljs-number">20</span>]; <span class="hljs-comment">// 名称</span>
<span class="hljs-type">float</span> price; <span class="hljs-comment">// 价格</span>
};
<span class="hljs-type">void</span> <span class="hljs-title function_">data_write</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *filename)</span>;
<span class="hljs-type">void</span> <span class="hljs-title function_">data_read</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *filename)</span>;
<span class="hljs-type">int</span> <span class="hljs-title function_">main</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span> {
<span class="hljs-type">char</span> fname[]=<span class="hljs-string">"goods_table.dat"</span>;
data_write(fname); <span class="hljs-comment">// 将结构体数组整体写入文件</span>
data_read(fname); <span class="hljs-comment">// 再从文件随机读取</span>
<span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="42" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="42" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E8%BE%93%E5%85%A5%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E5%86%99%E5%85%A5%E7%A3%81%E7%9B%98%E6%96%87%E4%BB%B6">输入商品信息写入磁盘文件</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">void</span> <span class="hljs-title function_">data_write</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *filenamme)</span> {
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">goods</span> <span class="hljs-title">g</span>;</span> <span class="hljs-comment">// 声明 struct goods 类型结构变量</span>
FILE *out;
<span class="hljs-keyword">if</span>((out = fopen(filenamme, <span class="hljs-string">"wb"</span>)) == <span class="hljs-literal">NULL</span>)
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"输入货物编码、名称、价格\n"</span>);
<span class="hljs-keyword">while</span>(<span class="hljs-built_in">scanf</span>(<span class="hljs-string">"%ld%s%f"</span>, &g.code, g.name, &g.price) == <span class="hljs-number">3</span>) {
fwrite(&g, <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">struct</span> goods), <span class="hljs-number">1</span>, out); <span class="hljs-comment">// 写入结构体变量g</span>
}
fclose(out);
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="43" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="43" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E4%BB%8E%E7%A3%81%E7%9B%98%E8%AF%BB%E5%8F%96%E5%95%86%E5%93%81%E4%BF%A1%E6%81%AF%E6%98%BE%E7%A4%BA%E5%88%B0%E5%B1%8F%E5%B9%95">从磁盘读取商品信息显示到屏幕</h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">void</span> <span class="hljs-title function_">data_read</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *filenamme)</span> {
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">goods</span> <span class="hljs-title">g</span>;</span>
FILE *in;
<span class="hljs-keyword">if</span>((in = fopen(filenamme, <span class="hljs-string">"rb"</span>)) == <span class="hljs-literal">NULL</span>)
<span class="hljs-built_in">exit</span>(<span class="hljs-number">-1</span>);
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"货物编码\t名称\t价格\n"</span>);
fread(&g, <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">struct</span> goods), <span class="hljs-number">1</span>, in);
<span class="hljs-keyword">while</span>(!feof(in)) { <span class="hljs-comment">// 注意函数生效条件</span>
<span class="hljs-built_in">printf</span>(<span class="hljs-string">"%ld\t%s\t%f\n"</span>, g.code, g.name, g.price);
fread(&g, <span class="hljs-keyword">sizeof</span>(<span class="hljs-keyword">struct</span> goods), <span class="hljs-number">1</span>, in); <span class="hljs-comment">// 读入结构体变量g</span>
}
fclose(in);
}
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="44" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="44" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E7%9A%84%E8%AF%BB%E5%86%99%E6%96%B9%E5%BC%8F-%E9%A1%BA%E5%BA%8F-vs-%E9%9A%8F%E6%9C%BA%E8%AF%BB%E5%86%99">文件的读写方式: <strong>顺序 vs 随机读写</strong></h2>
<ul>
<li>打开文件时,读写指针指向文件头,读写一个"数据"后,读写指针自动指向下一个"数据"。</li>
<li>文件的读写方式有两种: <strong>顺序读写</strong>和<strong>随机读写</strong>
<ul>
<li><strong>顺序读写</strong>:从文件头到文件尾顺序读写数据。</li>
<li><strong>随机读写</strong>:读写可以从指定的位置进行,不必每次从头顺序开始。</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th>方式</th>
<th>特点</th>
<th>适用文件</th>
</tr>
</thead>
<tbody>
<tr>
<td>顺序</td>
<td>读写指针自动后移</td>
<td>文本/二进制</td>
</tr>
<tr>
<td>随机</td>
<td>可定位任意位置读写</td>
<td>二进制</td>
</tr>
</tbody>
</table>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="45" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="45" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E9%A1%BA%E5%BA%8F%E8%AF%BB%E5%86%99%E7%A4%BA%E6%84%8F">顺序读写示意</h3>
<p><img src="images/c-file-fig-09.svg" alt="" style="width:1000px;" /></p>
<p>按文本格式,读入1个short 数据和1个char数据</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-built_in">fscanf</span>(fp, <span class="hljs-string">"%hd"</span>, &i); <span class="hljs-comment">// x = 123 </span>
<span class="hljs-built_in">fscanf</span>(fp, <span class="hljs-string">"%c"</span>, &c); <span class="hljs-comment">// x = 'a'</span>
</code></pre>
<p><strong>文本文件只能顺序读写</strong>,因为其数据非定长,不能直接定位。</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="46" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="46" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E9%9A%8F%E6%9C%BA%E8%AF%BB%E5%86%99%E7%A4%BA%E6%84%8F">随机读写示意</h3>
<p><img src="images/c-file-fig-10.svg" alt="" style="width:1000px;" /></p>
<ul>
<li>二进制文件数据长度由明确类型给出,<strong>既能顺序,也能随机读写</strong>。</li>
<li>利用文件的<strong>定位函数</strong>和文件的读写函数,即可实现文件的随机读写。</li>
</ul>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="47" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="47" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%96%87%E4%BB%B6%E5%AE%9A%E4%BD%8D%E5%87%BD%E6%95%B0">文件定位函数</h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> <span class="hljs-title function_">fseek</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">long</span> offset, <span class="hljs-type">int</span> origin)</span>;
<span class="hljs-type">long</span> <span class="hljs-title function_">ftell</span><span class="hljs-params">(FILE *stream)</span>;
<span class="hljs-type">void</span> <span class="hljs-title function_">rewind</span><span class="hljs-params">(FILE *stream)</span>;
<span class="hljs-type">int</span> <span class="hljs-title function_">fgetpos</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">fpos_t</span> *pos)</span>;
<span class="hljs-type">int</span> <span class="hljs-title function_">fsetpos</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">const</span> <span class="hljs-type">fpos_t</span> *pos)</span>;
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="48" data-marpit-scope-lp1ZcjI0="" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="48" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E6%96%87%E4%BB%B6%E5%AE%9A%E4%BD%8D%E5%87%BD%E6%95%B0fseek">文件定位函数<code>fseek</code></h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> <span class="hljs-title function_">fseek</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">long</span> offset, <span class="hljs-type">int</span> origin)</span>;
</code></pre>
<ul>
<li>将<code>stream</code>指向的文件之当前读写指针,定位到<code>origin + offset</code>
<ul>
<li>如果正常定位,返回0,否则返回非0值。</li>
<li><code>origin</code>和<code>offset</code>分别称为基准点和偏移量。</li>
</ul>
</li>
</ul>
<div class="columns">
<div>
<p><img src="images/c-file-fig-11.svg" alt="" style="width:350px;" /></p>
</div>
<div>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-comment">// origin 基准点取值</span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> SEEK_SET 0 <span class="hljs-comment">// 文件起始位置为基准点 </span></span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> SEEK_CUR 1 <span class="hljs-comment">// 文件当前位置为基准点</span></span>
<span class="hljs-meta">#<span class="hljs-keyword">define</span> SEEK_END 2 <span class="hljs-comment">// 文件尾部位置为基准点</span></span>
<span class="hljs-comment">// 获取文件当前位置</span>
<span class="hljs-type">long</span> <span class="hljs-title function_">ftell</span><span class="hljs-params">(FILE *stream)</span>; <span class="hljs-comment">// 当前位置相对于文件首的偏移字节数,出错时返回-1L</span>
</code></pre>
</div>
</div>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="49" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="49" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E6%96%87%E4%BB%B6%E5%AE%9A%E4%BD%8D%E5%87%BD%E6%95%B0fgetpos%E5%92%8Cfsetpos">文件定位函数<code>fgetpos</code>和<code>fsetpos</code></h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> <span class="hljs-title function_">fgetpos</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">fpos_t</span> *pos)</span>;
</code></pre>
<p>将<code>stream</code>指向文件的读写指针当前值,保存到<code>pos</code>指针所指的<code>fpos_t</code>类型的对象中。成功保存,fgetpos返回0,否则返回非0值。</p>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> <span class="hljs-title function_">fsetpos</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">const</span> <span class="hljs-type">fpos_t</span> *pos)</span>;
</code></pre>
<p>用<code>fgetpos</code>函数保存到<code>pos</code>指针所指对象中的值来设置<code>stream</code>所指向文件的当前位置。设置成功函数返回0,否则返回非0值。</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="50" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="50" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h3 id="%E6%96%87%E4%BB%B6%E5%AE%9A%E4%BD%8D%E5%87%BD%E6%95%B0rewind">文件定位函数<code>rewind</code></h3>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">void</span> <span class="hljs-title function_">rewind</span><span class="hljs-params">(FILE *stream)</span>;
</code></pre>
<p>将文件指针<code>stream</code>指向文件的读写指针重新定位到文件的起始位置,同时清除文件结束标志和出错标志。</p>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="51" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="51" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E5%85%B6%E5%AE%83%E6%96%87%E4%BB%B6%E6%93%8D%E4%BD%9C">其它文件操作</h2>
<pre is="marp-pre" data-auto-scaling="downscale-only"><code class="language-c"><span class="hljs-type">int</span> <span class="hljs-title function_">fflush</span><span class="hljs-params">(FILE *stream)</span>; <span class="hljs-comment">// 强制刷新缓冲区</span>
<span class="hljs-type">int</span> <span class="hljs-title function_">setvbuf</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">char</span> *buf, <span class="hljs-type">int</span> mode, <span class="hljs-type">size_t</span> size)</span>; <span class="hljs-comment">// 自定义缓冲区</span>
<span class="hljs-type">void</span> <span class="hljs-title function_">setbuf</span><span class="hljs-params">(FILE *stream, <span class="hljs-type">char</span> *buf)</span>; <span class="hljs-comment">// 默认缓冲区</span>
<span class="hljs-type">int</span> <span class="hljs-title function_">remove</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> * filename)</span>; <span class="hljs-comment">// 删除文件</span>
<span class="hljs-type">int</span> <span class="hljs-title function_">rename</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> * oldname, <span class="hljs-type">const</span> <span class="hljs-type">char</span> * newname)</span>; <span class="hljs-comment">// 重命名文件</span>
FILE * <span class="hljs-title function_">tmpfile</span><span class="hljs-params">(<span class="hljs-type">void</span>)</span>; <span class="hljs-comment">// 创建临时文件</span>
<span class="hljs-type">char</span> * <span class="hljs-title function_">tmpnam</span><span class="hljs-params">(<span class="hljs-type">char</span> *s)</span>; <span class="hljs-comment">// 生成临时文件名</span>
<span class="hljs-type">void</span> <span class="hljs-title function_">clearerr</span><span class="hljs-params">(FILE *stream)</span>; <span class="hljs-comment">// 清除错误标志</span>
<span class="hljs-type">int</span> <span class="hljs-title function_">ferror</span><span class="hljs-params">(FILE *stream)</span>; <span class="hljs-comment">// 测试文件错误</span>
<span class="hljs-type">void</span> <span class="hljs-title function_">perror</span><span class="hljs-params">(<span class="hljs-type">const</span> <span class="hljs-type">char</span> *s)</span>; <span class="hljs-comment">// 打印错误信息</span>
</code></pre>
</section>
</foreignObject></svg><svg data-marpit-svg="" viewBox="0 0 1280 720"><foreignObject width="1280" height="720"><section id="52" data-paginate="true" data-theme="gaia" lang="zh-CN" data-marpit-pagination="52" style="--paginate:true;--theme:gaia;" data-marpit-pagination-total="52">
<h2 id="%E6%80%BB%E7%BB%93">总结</h2>
<ul>
<li>文件操作是C语言中重要的<strong>数据持久化</strong>手段</li>
<li>掌握<strong>文本文件</strong>和<strong>二进制文件</strong>的区别及适用场景</li>
<li>熟练使用各种文件<strong>读写函数</strong>(字符、字符串、格式、二进制)</li>
<li>理解<strong>顺序读写</strong>和<strong>随机读写</strong>的原理及应用</li>
<li>掌握<strong>文件定位</strong>和<strong>错误处理</strong>的方法</li>
</ul>
</section>
<script>!function(){"use strict";const t={h1:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"1"},style:"display: block; font-size: 2em; margin-block-start: 0.67em; margin-block-end: 0.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h2:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"2"},style:"display: block; font-size: 1.5em; margin-block-start: 0.83em; margin-block-end: 0.83em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h3:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"3"},style:"display: block; font-size: 1.17em; margin-block-start: 1em; margin-block-end: 1em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h4:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"4"},style:"display: block; margin-block-start: 1.33em; margin-block-end: 1.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h5:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"5"},style:"display: block; font-size: 0.83em; margin-block-start: 1.67em; margin-block-end: 1.67em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},h6:{proto:()=>HTMLHeadingElement,attrs:{role:"heading","aria-level":"6"},style:"display: block; font-size: 0.67em; margin-block-start: 2.33em; margin-block-end: 2.33em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold;"},span:{proto:()=>HTMLSpanElement},pre:{proto:()=>HTMLElement,style:"display: block; font-family: monospace; white-space: pre; margin: 1em 0; --marp-auto-scaling-white-space: pre;"}},e="data-marp-auto-scaling-wrapper",i="data-marp-auto-scaling-svg",n="data-marp-auto-scaling-container";class s extends HTMLElement{container;containerSize;containerObserver;svg;svgComputedStyle;svgPreserveAspectRatio="xMinYMid meet";wrapper;wrapperSize;wrapperObserver;constructor(){super();const t=t=>([e])=>{const{width:i,height:n}=e.contentRect;this[t]={width:i,height:n},this.updateSVGRect()};this.attachShadow({mode:"open"}),this.containerObserver=new ResizeObserver(t("containerSize")),this.wrapperObserver=new ResizeObserver(((...e)=>{t("wrapperSize")(...e),this.flushSvgDisplay()}))}static get observedAttributes(){return["data-downscale-only"]}connectedCallback(){this.shadowRoot.innerHTML=`\n<style>\n svg[${i}] { display: block; width: 100%; height: auto; vertical-align: top; }\n span[${n}] { display: table; white-space: var(--marp-auto-scaling-white-space, nowrap); width: max-content; }\n</style>\n<div ${e}>\n <svg part="svg" ${i}>\n <foreignObject><span ${n}><slot></slot></span></foreignObject>\n </svg>\n</div>\n `.split(/\n\s*/).join(""),this.wrapper=this.shadowRoot.querySelector(`div[${e}]`)??void 0;const t=this.svg;this.svg=this.wrapper?.querySelector(`svg[${i}]`)??void 0,this.svg!==t&&(this.svgComputedStyle=this.svg?window.getComputedStyle(this.svg):void 0),this.container=this.svg?.querySelector(`span[${n}]`)??void 0,this.observe()}disconnectedCallback(){this.svg=void 0,this.svgComputedStyle=void 0,this.wrapper=void 0,this.container=void 0,this.observe()}attributeChangedCallback(){this.observe()}flushSvgDisplay(){const{svg:t}=this;t&&(t.style.display="inline",requestAnimationFrame((()=>{t.style.display=""})))}observe(){this.containerObserver.disconnect(),this.wrapperObserver.disconnect(),this.wrapper&&this.wrapperObserver.observe(this.wrapper),this.container&&this.containerObserver.observe(this.container),this.svgComputedStyle&&this.observeSVGStyle(this.svgComputedStyle)}observeSVGStyle(t){const e=()=>{const i=(()=>{const e=t.getPropertyValue("--preserve-aspect-ratio");if(e)return e.trim();return`x${(({textAlign:t,direction:e})=>{if(t.endsWith("left"))return"Min";if(t.endsWith("right"))return"Max";if("start"===t||"end"===t){let i="rtl"===e;return"end"===t&&(i=!i),i?"Max":"Min"}return"Mid"})(t)}YMid meet`})();i!==this.svgPreserveAspectRatio&&(this.svgPreserveAspectRatio=i,this.updateSVGRect()),t===this.svgComputedStyle&&requestAnimationFrame(e)};e()}updateSVGRect(){let t=Math.ceil(this.containerSize?.width??0);const e=Math.ceil(this.containerSize?.height??0);void 0!==this.dataset.downscaleOnly&&(t=Math.max(t,this.wrapperSize?.width??0));const i=this.svg?.querySelector(":scope > foreignObject");if(i?.setAttribute("width",`${t}`),i?.setAttribute("height",`${e}`),this.svg&&(this.svg.setAttribute("viewBox",`0 0 ${t} ${e}`),this.svg.setAttribute("preserveAspectRatio",this.svgPreserveAspectRatio),this.svg.style.height=t<=0||e<=0?"0":""),this.container){const t=this.svgPreserveAspectRatio.toLowerCase();this.container.style.marginLeft=t.startsWith("xmid")||t.startsWith("xmax")?"auto":"0",this.container.style.marginRight=t.startsWith("xmi")?"auto":"0"}}}const r=(t,{attrs:e={},style:i})=>class extends t{constructor(...t){super(...t);for(const[t,i]of Object.entries(e))this.hasAttribute(t)||this.setAttribute(t,i);this._shadow()}static get observedAttributes(){return["data-auto-scaling"]}connectedCallback(){this._update()}attributeChangedCallback(){this._update()}_shadow(){if(!this.shadowRoot)try{this.attachShadow({mode:"open"})}catch(t){if(!(t instanceof Error&&"NotSupportedError"===t.name))throw t}return this.shadowRoot}_update(){const t=this._shadow();if(t){const e=i?`<style>:host { ${i} }</style>`:"";let n="<slot></slot>";const{autoScaling:s}=this.dataset;if(void 0!==s){n=`<marp-auto-scaling exportparts="svg:auto-scaling" ${"downscale-only"===s?"data-downscale-only":""}>${n}</marp-auto-scaling>`}t.innerHTML=e+n}}};let o;const a=Symbol();let l;const c="marpitSVGPolyfill:setZoomFactor,",d=Symbol(),h=Symbol();const g=()=>{const t="Apple Computer, Inc."===navigator.vendor,e=t?[u]:[],i={then:e=>(t?(async()=>{if(void 0===l){const t=document.createElement("canvas");t.width=10,t.height=10;const e=t.getContext("2d"),i=new Image(10,10),n=new Promise((t=>{i.addEventListener("load",(()=>t()))}));i.crossOrigin="anonymous",i.src="data:image/svg+xml;charset=utf8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%2210%22%20height%3D%2210%22%20viewBox%3D%220%200%201%201%22%3E%3CforeignObject%20width%3D%221%22%20height%3D%221%22%20requiredExtensions%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%3Cdiv%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%20style%3D%22width%3A%201px%3B%20height%3A%201px%3B%20background%3A%20red%3B%20position%3A%20relative%22%3E%3C%2Fdiv%3E%3C%2FforeignObject%3E%3C%2Fsvg%3E",await n,e.drawImage(i,0,0),l=e.getImageData(5,5,1,1).data[3]<128}return l})().then((t=>{null==e||e(t?[u]:[])})):null==e||e([]),i)};return Object.assign(e,i)};let p,m;function u(t){const e="object"==typeof t&&t.target||document,i="object"==typeof t?t.zoom:t;window[h]||(Object.defineProperty(window,h,{configurable:!0,value:!0}),document.body.style.zoom=1.0001,document.body.offsetHeight,document.body.style.zoom=1,window.addEventListener("message",(({data:t,origin:e})=>{if(e===window.origin)try{if(t&&"string"==typeof t&&t.startsWith(c)){const[,e]=t.split(","),i=Number.parseFloat(e);Number.isNaN(i)||(m=i)}}catch(t){console.error(t)}})));let n=!1;Array.from(e.querySelectorAll("svg[data-marpit-svg]"),(t=>{var e,s,r,o;t.style.transform||(t.style.transform="translateZ(0)");const a=i||m||t.currentScale||1;p!==a&&(p=a,n=a);const l=t.getBoundingClientRect(),{length:c}=t.children;for(let i=0;i<c;i+=1){const n=t.children[i];if(n.getScreenCTM){const t=n.getScreenCTM();if(t){const i=null!==(s=null===(e=n.x)||void 0===e?void 0:e.baseVal.value)&&void 0!==s?s:0,c=null!==(o=null===(r=n.y)||void 0===r?void 0:r.baseVal.value)&&void 0!==o?o:0,d=n.children.length;for(let e=0;e<d;e+=1){const s=n.children[e];if("SECTION"===s.tagName){const{style:e}=s;e.transformOrigin||(e.transformOrigin=`${-i}px ${-c}px`),e.transform=`scale(${a}) matrix(${t.a}, ${t.b}, ${t.c}, ${t.d}, ${t.e-l.left}, ${t.f-l.top}) translateZ(0.0001px)`;break}}}}}})),!1!==n&&Array.from(e.querySelectorAll("iframe"),(({contentWindow:t})=>{null==t||t.postMessage(`${c}${n}`,"null"===window.origin?"*":window.origin)}))}function v({once:t=!1,target:e=document}={}){const i=function(t=document){if(t[d])return t[d];let e=!0;const i=()=>{e=!1,delete t[d]};Object.defineProperty(t,d,{configurable:!0,value:i});let n=[],s=!1;(async()=>{try{n=await g()}finally{s=!0}})();const r=()=>{for(const e of n)e({target:t});s&&0===n.length||e&&window.requestAnimationFrame(r)};return r(),i}(e);return t?(i(),()=>{}):i}p=1,m=void 0;const w=Symbol(),b=(e=document)=>{if("undefined"==typeof window)throw new Error("Marp Core's browser script is valid only in browser context.");if(((e=document)=>{const i=window[a];i||customElements.define("marp-auto-scaling",s);for(const n of Object.keys(t)){const s=`marp-${n}`,a=t[n].proto();(o??(o=!!document.createElement("div",{is:"marp-auto-scaling"}).outerHTML.startsWith("<div is"),o))&&a!==HTMLElement?i||customElements.define(s,r(a,{style:t[n].style}),{extends:n}):(i||customElements.define(s,r(HTMLElement,t[n])),e.querySelectorAll(`${n}[is="${s}"]`).forEach((t=>{t.outerHTML=t.outerHTML.replace(new RegExp(`^<${n}`,"i"),`<${s}`).replace(new RegExp(`</${n}>$`,"i"),`</${s}>`)})))}window[a]=!0})(e),e[w])return e[w];const i=v({target:e}),n=()=>{i(),delete e[w]},l=Object.assign(n,{cleanup:n,update:()=>b(e)});return Object.defineProperty(e,w,{configurable:!0,value:l}),l},y=document.currentScript;b(y?y.getRootNode():document)}();
</script></foreignObject></svg></div><script>/*!! License: https://unpkg.com/@marp-team/marp-cli@4.2.3/lib/bespoke.js.LICENSE.txt */
!function(){"use strict";function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var t,n,r=(n||(n=1,t={from:function(e,t){var n,r=1===(e.parent||e).nodeType?e.parent||e:document.querySelector(e.parent||e),o=[].filter.call("string"==typeof e.slides?r.querySelectorAll(e.slides):e.slides||r.children,function(e){return"SCRIPT"!==e.nodeName}),a={},i=function(e,t){return(t=t||{}).index=o.indexOf(e),t.slide=e,t},s=function(e,t){a[e]=(a[e]||[]).filter(function(e){return e!==t})},c=function(e,t){return(a[e]||[]).reduce(function(e,n){return e&&!1!==n(t)},!0)},l=function(e,t){o[e]&&(n&&c("deactivate",i(n,t)),n=o[e],c("activate",i(n,t)))},d=function(e,t){var r=o.indexOf(n)+e;c(e>0?"next":"prev",i(n,t))&&l(r,t)},u={off:s,on:function(e,t){return(a[e]||(a[e]=[])).push(t),s.bind(null,e,t)},fire:c,slide:function(e,t){if(!arguments.length)return o.indexOf(n);c("slide",i(o[e],t))&&l(e,t)},next:d.bind(null,1),prev:d.bind(null,-1),parent:r,slides:o,destroy:function(e){c("destroy",i(n,e)),a={}}};return(t||[]).forEach(function(e){e(u)}),n||l(0),u}}),t),o=e(r);const a=document.body,i=(...e)=>history.replaceState(...e),s="",c="presenter",l="next",d=["",c,l],u="bespoke-marp-",f=`data-${u}`,m=(e,{protocol:t,host:n,pathname:r,hash:o}=location)=>{const a=e.toString();return`${t}//${n}${r}${a?"?":""}${a}${o}`},g=()=>a.dataset.bespokeView,p=e=>new URLSearchParams(location.search).get(e),v=(e,t={})=>{const n={location,setter:i,...t},r=new URLSearchParams(n.location.search);for(const t of Object.keys(e)){const n=e[t];"string"==typeof n?r.set(t,n):r.delete(t)}try{n.setter({...window.history.state??{}},"",m(r,n.location))}catch(e){console.error(e)}},h=(()=>{const e="bespoke-marp";try{return localStorage.setItem(e,e),localStorage.removeItem(e),!0}catch{return!1}})(),y=e=>{try{return localStorage.getItem(e)}catch{return null}},b=(e,t)=>{try{return localStorage.setItem(e,t),!0}catch{return!1}},w=e=>{try{return localStorage.removeItem(e),!0}catch{return!1}},x=(e,t)=>{const n="aria-hidden";t?e.setAttribute(n,"true"):e.removeAttribute(n)},k=e=>{e.parent.classList.add(`${u}parent`),e.slides.forEach(e=>e.classList.add(`${u}slide`)),e.on("activate",t=>{const n=`${u}active`,r=t.slide,o=r.classList,a=!o.contains(n);if(e.slides.forEach(e=>{e.classList.remove(n),x(e,!0)}),o.add(n),x(r,!1),a){const e=`${n}-ready`;o.add(e),document.body.clientHeight,o.remove(e)}})},$=e=>{let t=0,n=0;Object.defineProperty(e,"fragments",{enumerable:!0,value:e.slides.map(e=>[null,...e.querySelectorAll("[data-marpit-fragment]")])});const r=r=>void 0!==e.fragments[t][n+r],o=(r,o)=>{t=r,n=o,e.fragments.forEach((e,t)=>{e.forEach((e,n)=>{if(null==e)return;const a=t<r||t===r&&n<=o;e.setAttribute(`${f}fragment`,(a?"":"in")+"active");const i=`${f}current-fragment`;t===r&&n===o?e.setAttribute(i,"current"):e.removeAttribute(i)})}),e.fragmentIndex=o;const a={slide:e.slides[r],index:r,fragments:e.fragments[r],fragmentIndex:o};e.fire("fragment",a)};e.on("next",({fragment:a=!0})=>{if(a){if(r(1))return o(t,n+1),!1;const a=t+1;e.fragments[a]&&o(a,0)}else{const r=e.fragments[t].length;if(n+1<r)return o(t,r-1),!1;const a=e.fragments[t+1];a&&o(t+1,a.length-1)}}),e.on("prev",({fragment:a=!0})=>{if(r(-1)&&a)return o(t,n-1),!1;const i=t-1;e.fragments[i]&&o(i,e.fragments[i].length-1)}),e.on("slide",({index:t,fragment:n})=>{let r=0;if(void 0!==n){const o=e.fragments[t];if(o){const{length:e}=o;r=-1===n?e-1:Math.min(Math.max(n,0),e-1)}}o(t,r)}),o(0,0)},E=document,L=()=>!(!E.fullscreenEnabled&&!E.webkitFullscreenEnabled),S=()=>!(!E.fullscreenElement&&!E.webkitFullscreenElement),P=e=>{e.fullscreen=()=>{L()&&(async()=>{S()?(E.exitFullscreen||E.webkitExitFullscreen)?.call(E):((e=E.body)=>{(e.requestFullscreen||e.webkitRequestFullscreen)?.call(e)})()})()},document.addEventListener("keydown",t=>{"f"!==t.key&&"F11"!==t.key||t.altKey||t.ctrlKey||t.metaKey||!L()||(e.fullscreen(),t.preventDefault())})},_=`${u}inactive`,T=(e=2e3)=>({parent:t,fire:n})=>{const r=t.classList,o=e=>n(`marp-${e?"":"in"}active`);let a;const i=()=>{a&&clearTimeout(a),a=setTimeout(()=>{r.add(_),o()},e),r.contains(_)&&(r.remove(_),o(!0))};for(const e of["mousedown","mousemove","touchend"])document.addEventListener(e,i);setTimeout(i,0)},I=["AUDIO","BUTTON","INPUT","SELECT","TEXTAREA","VIDEO"],M=e=>{e.parent.addEventListener("keydown",e=>{if(!e.target)return;const t=e.target;(I.includes(t.nodeName)||"true"===t.contentEditable)&&e.stopPropagation()})},O=e=>{window.addEventListener("load",()=>{for(const t of e.slides){const e=t.querySelector("marp-auto-scaling, [data-auto-scaling], [data-marp-fitting]");t.setAttribute(`${f}load`,e?"":"hideable")}})},A=({interval:e=250}={})=>t=>{document.addEventListener("keydown",e=>{if(" "===e.key&&e.shiftKey)t.prev();else if("ArrowLeft"===e.key||"ArrowUp"===e.key||"PageUp"===e.key)t.prev({fragment:!e.shiftKey});else if(" "!==e.key||e.shiftKey)if("ArrowRight"===e.key||"ArrowDown"===e.key||"PageDown"===e.key)t.next({fragment:!e.shiftKey});else if("End"===e.key)t.slide(t.slides.length-1,{fragment:-1});else{if("Home"!==e.key)return;t.slide(0)}else t.next();e.preventDefault()});let n,r,o=0;t.parent.addEventListener("wheel",a=>{let i=!1;const s=(e,t)=>{e&&(i=i||((e,t)=>((e,t)=>{const n="X"===t?"Width":"Height";return e[`client${n}`]<e[`scroll${n}`]})(e,t)&&((e,t)=>{const{overflow:n}=e,r=e[`overflow${t}`];return"auto"===n||"scroll"===n||"auto"===r||"scroll"===r})(getComputedStyle(e),t))(e,t)),e?.parentElement&&s(e.parentElement,t)};if(0!==a.deltaX&&s(a.target,"X"),0!==a.deltaY&&s(a.target,"Y"),i)return;a.preventDefault();const c=Math.sqrt(a.deltaX**2+a.deltaY**2);if(void 0!==a.wheelDelta){if(void 0===a.webkitForce&&Math.abs(a.wheelDelta)<40)return;if(a.deltaMode===a.DOM_DELTA_PIXEL&&c<4)return}else if(a.deltaMode===a.DOM_DELTA_PIXEL&&c<12)return;r&&clearTimeout(r),r=setTimeout(()=>{n=0},e);const l=Date.now()-o<e,d=c<=n;if(n=c,l||d)return;let u;(a.deltaX>0||a.deltaY>0)&&(u="next"),(a.deltaX<0||a.deltaY<0)&&(u="prev"),u&&(t[u](),o=Date.now())})},C=(e=`.${u}osc`)=>{const t=document.querySelector(e);if(!t)return()=>{};const n=(e,n)=>{t.querySelectorAll(`[${f}osc=${JSON.stringify(e)}]`).forEach(n)};return L()||n("fullscreen",e=>e.style.display="none"),h||n("presenter",e=>{e.disabled=!0,e.title="Presenter view is disabled due to restricted localStorage."}),e=>{t.addEventListener("click",t=>{if(t.target instanceof HTMLElement){const{bespokeMarpOsc:n}=t.target.dataset;n&&t.target.blur();const r={fragment:!t.shiftKey};"next"===n?e.next(r):"prev"===n?e.prev(r):"fullscreen"===n?e?.fullscreen():"presenter"===n&&e.openPresenterView()}}),e.parent.appendChild(t),e.on("activate",({index:t})=>{n("page",n=>n.textContent=`Page ${t+1} of ${e.slides.length}`)}),e.on("fragment",({index:t,fragments:r,fragmentIndex:o})=>{n("prev",e=>e.disabled=0===t&&0===o),n("next",n=>n.disabled=t===e.slides.length-1&&o===r.length-1)}),e.on("marp-active",()=>x(t,!1)),e.on("marp-inactive",()=>x(t,!0)),L()&&(e=>{for(const t of["","webkit"])E.addEventListener(t+"fullscreenchange",e)})(()=>n("fullscreen",e=>e.classList.toggle("exit",L()&&S())))}},D=e=>{window.addEventListener("message",t=>{if(t.origin!==window.origin)return;const[n,r]=t.data.split(":");if("navigate"===n){const[t,n]=r.split(",");let o=Number.parseInt(t,10),a=Number.parseInt(n,10)+1;a>=e.fragments[o].length&&(o+=1,a=0),e.slide(o,{fragment:a})}})};var N,B,q,K,F,j,V,U={exports:{}},X=(N||(N=1,U.exports=(B=["area","base","br","col","command","embed","hr","img","input","keygen","link","meta","param","source","track","wbr"],q=function(e){return String(e).replace(/[&<>"']/g,function(e){return"&"+K[e]+";"})},K={"&":"amp","<":"lt",">":"gt",'"':"quot","'":"apos"},F="dangerouslySetInnerHTML",j={className:"class",htmlFor:"for"},V={},function(e,t){var n=[],r="";t=t||{};for(var o=arguments.length;o-- >2;)n.push(arguments[o]);if("function"==typeof e)return t.children=n.reverse(),e(t);if(e){if(r+="<"+e,t)for(var a in t)!1!==t[a]&&null!=t[a]&&a!==F&&(r+=" "+(j[a]?j[a]:q(a))+'="'+q(t[a])+'"');r+=">"}if(-1===B.indexOf(e)){if(t[F])r+=t[F].__html;else for(;n.length;){var i=n.pop();if(i)if(i.pop)for(var s=i.length;s--;)n.push(i[s]);else r+=!0===V[i]?i:q(i)}r+=e?"</"+e+">":""}return V[r]=!0,r})),U.exports),H=e(X);const R=({children:e})=>H(null,null,...e),W=`${u}presenter-`,J={container:`${W}container`,dragbar:`${W}dragbar-container`,next:`${W}next`,nextContainer:`${W}next-container`,noteContainer:`${W}note-container`,noteWrapper:`${W}note-wrapper`,noteButtons:`${W}note-buttons`,infoContainer:`${W}info-container`,infoPage:`${W}info-page`,infoPageText:`${W}info-page-text`,infoPagePrev:`${W}info-page-prev`,infoPageNext:`${W}info-page-next`,noteButtonsBigger:`${W}note-bigger`,noteButtonsSmaller:`${W}note-smaller`,infoTime:`${W}info-time`,infoTimer:`${W}info-timer`},Y=e=>{const{title:t}=document;document.title="[Presenter view]"+(t?` - ${t}`:"");const n={},r=e=>(n[e]=n[e]||document.querySelector(`.${e}`),n[e]);document.body.appendChild((e=>{const t=document.createElement("div");return t.className=J.container,t.appendChild(e),t.insertAdjacentHTML("beforeend",H(R,null,H("div",{class:J.nextContainer},H("iframe",{class:J.next,src:"?view=next"})),H("div",{class:J.dragbar}),H("div",{class:J.noteContainer},H("div",{class:J.noteWrapper}),H("div",{class:J.noteButtons},H("button",{class:J.noteButtonsSmaller,tabindex:"-1",title:"Smaller notes font size"},"Smaller notes font size"),H("button",{class:J.noteButtonsBigger,tabindex:"-1",title:"Bigger notes font size"},"Bigger notes font size"))),H("div",{class:J.infoContainer},H("div",{class:J.infoPage},H("button",{class:J.infoPagePrev,tabindex:"-1",title:"Previous"},"Previous"),H("span",{class:J.infoPageText}),H("button",{class:J.infoPageNext,tabindex:"-1",title:"Next"},"Next")),H("time",{class:J.infoTime,title:"Current time"}),H("time",{class:J.infoTimer,title:"Timer"})))),t})(e.parent)),(e=>{let t=!1;r(J.dragbar).addEventListener("mousedown",()=>{t=!0,r(J.dragbar).classList.add("active")}),window.addEventListener("mouseup",()=>{t=!1,r(J.dragbar).classList.remove("active")}),window.addEventListener("mousemove",e=>{if(!t)return;const n=e.clientX/document.documentElement.clientWidth*100;r(J.container).style.setProperty("--bespoke-marp-presenter-split-ratio",`${Math.max(0,Math.min(100,n))}%`)}),r(J.nextContainer).addEventListener("click",()=>e.next());const n=r(J.next),o=(a=n,(e,t)=>a.contentWindow?.postMessage(`navigate:${e},${t}`,"null"===window.origin?"*":window.origin));var a;n.addEventListener("load",()=>{r(J.nextContainer).classList.add("active"),o(e.slide(),e.fragmentIndex),e.on("fragment",({index:e,fragmentIndex:t})=>o(e,t))});const i=document.querySelectorAll(".bespoke-marp-note");i.forEach(e=>{e.addEventListener("keydown",e=>e.stopPropagation()),r(J.noteWrapper).appendChild(e)}),e.on("activate",()=>i.forEach(t=>t.classList.toggle("active",t.dataset.index==e.slide())));let s=0;const c=e=>{s=Math.max(-5,s+e),r(J.noteContainer).style.setProperty("--bespoke-marp-note-font-scale",(1.2**s).toFixed(4))},l=()=>c(1),d=()=>c(-1),u=r(J.noteButtonsBigger),f=r(J.noteButtonsSmaller);u.addEventListener("click",()=>{u.blur(),l()}),f.addEventListener("click",()=>{f.blur(),d()}),document.addEventListener("keydown",e=>{"+"===e.key&&l(),"-"===e.key&&d()},!0),e.on("activate",({index:t})=>{r(J.infoPageText).textContent=`${t+1} / ${e.slides.length}`});const m=r(J.infoPagePrev),g=r(J.infoPageNext);m.addEventListener("click",t=>{m.blur(),e.prev({fragment:!t.shiftKey})}),g.addEventListener("click",t=>{g.blur(),e.next({fragment:!t.shiftKey})}),e.on("fragment",({index:t,fragments:n,fragmentIndex:r})=>{m.disabled=0===t&&0===r,g.disabled=t===e.slides.length-1&&r===n.length-1});let p=new Date;const v=()=>{const e=new Date,t=e=>`${Math.floor(e)}`.padStart(2,"0"),n=e.getTime()-p.getTime(),o=t(n/1e3%60),a=t(n/1e3/60%60),i=t(n/36e5%24);r(J.infoTime).textContent=e.toLocaleTimeString(),r(J.infoTimer).textContent=`${i}:${a}:${o}`};v(),setInterval(v,250),r(J.infoTimer).addEventListener("click",()=>{p=new Date})})(e)},z=e=>{if(!(e=>e.syncKey&&"string"==typeof e.syncKey)(e))throw new Error("The current instance of Bespoke.js is invalid for Marp bespoke presenter plugin.");Object.defineProperties(e,{openPresenterView:{enumerable:!0,value:G},presenterUrl:{enumerable:!0,get:Q}}),h&&document.addEventListener("keydown",t=>{"p"!==t.key||t.altKey||t.ctrlKey||t.metaKey||(t.preventDefault(),e.openPresenterView())})};function G(){const{max:e,floor:t}=Math,n=e(t(.85*window.innerWidth),640),r=e(t(.85*window.innerHeight),360);return window.open(this.presenterUrl,W+this.syncKey,`width=${n},height=${r},menubar=no,toolbar=no`)}function Q(){const e=new URLSearchParams(location.search);return e.set("view","presenter"),e.set("sync",this.syncKey),m(e)}const Z=e=>{const t=g();return t===l&&e.appendChild(document.createElement("span")),{[s]:z,[c]:Y,[l]:D}[t]},ee=e=>{e.on("activate",t=>{document.querySelectorAll(".bespoke-progress-parent > .bespoke-progress-bar").forEach(n=>{n.style.flexBasis=100*t.index/(e.slides.length-1)+"%"})})},te=e=>{const t=Number.parseInt(e,10);return Number.isNaN(t)?null:t},ne=(e={})=>{const t={history:!0,...e};return e=>{let n=!0;const r=e=>{const t=n;try{return n=!0,e()}finally{n=t}},o=(t={fragment:!0})=>{let n=t.fragment?te(p("f")||""):null;((t,n)=>{const{min:r,max:o}=Math,{fragments:a,slides:i}=e,s=o(0,r(t,i.length-1)),c=o(0,r(n||0,a[s].length-1));s===e.slide()&&c===e.fragmentIndex||e.slide(s,{fragment:c})})((()=>{if(location.hash){const[t]=location.hash.slice(1).split(":~:");if(/^\d+$/.test(t))return(te(t)??1)-1;const r=document.getElementById(t)||document.querySelector(`a[name="${CSS.escape(t)}"]`);if(r){const{length:t}=e.slides;for(let o=0;o<t;o+=1)if(e.slides[o].contains(r)){const t=e.fragments?.[o],a=r.closest("[data-marpit-fragment]");if(t&&a){const e=t.indexOf(a);e>=0&&(n=e)}return o}}}return 0})(),n)};e.on("fragment",({index:e,fragmentIndex:r})=>{n||v({f:0===r||r.toString()},{location:{...location,hash:`#${e+1}`},setter:(...e)=>t.history?history.pushState(...e):history.replaceState(...e)})}),setTimeout(()=>{o(),window.addEventListener("hashchange",()=>r(()=>{o({fragment:!1}),v({f:void 0})})),window.addEventListener("popstate",()=>{n||r(()=>o())}),n=!1},0)}},re=(e={})=>{const t=e.key||window.history.state?.marpBespokeSyncKey||Math.random().toString(36).slice(2),n=`bespoke-marp-sync-${t}`;var r;r={marpBespokeSyncKey:t},v({},{setter:(e,...t)=>i({...e,...r},...t)});const o=()=>{const e=y(n);return e?JSON.parse(e):Object.create(null)},a=e=>{const t=o(),r={...t,...e(t)};return b(n,JSON.stringify(r)),r},s=()=>{window.removeEventListener("pageshow",s),a(e=>({reference:(e.reference||0)+1}))};return e=>{s(),Object.defineProperty(e,"syncKey",{value:t,enumerable:!0});let r=!0;setTimeout(()=>{e.on("fragment",e=>{r&&a(()=>({index:e.index,fragmentIndex:e.fragmentIndex}))})},0),window.addEventListener("storage",t=>{if(t.key===n&&t.oldValue&&t.newValue){const n=JSON.parse(t.oldValue),o=JSON.parse(t.newValue);if(n.index!==o.index||n.fragmentIndex!==o.fragmentIndex)try{r=!1,e.slide(o.index,{fragment:o.fragmentIndex,forSync:!0})}finally{r=!0}}});const i=()=>{const{reference:e}=o();void 0===e||e<=1?w(n):a(()=>({reference:e-1}))};window.addEventListener("pagehide",e=>{e.persisted&&window.addEventListener("pageshow",s),i()}),e.on("destroy",i)}},{PI:oe,abs:ae,sqrt:ie,atan2:se}=Math,ce={passive:!0},le=({slope:e=-.7,swipeThreshold:t=30}={})=>n=>{let r;const o=n.parent,a=e=>{const t=o.getBoundingClientRect();return{x:e.pageX-(t.left+t.right)/2,y:e.pageY-(t.top+t.bottom)/2}};o.addEventListener("touchstart",({touches:e})=>{r=1===e.length?a(e[0]):void 0},ce),o.addEventListener("touchmove",e=>{if(r)if(1===e.touches.length){e.preventDefault();const t=a(e.touches[0]),n=t.x-r.x,o=t.y-r.y;r.delta=ie(ae(n)**2+ae(o)**2),r.radian=se(n,o)}else r=void 0}),o.addEventListener("touchend",o=>{if(r){if(r.delta&&r.delta>=t&&r.radian){const t=(r.radian-e+oe)%(2*oe)-oe;n[t<0?"next":"prev"](),o.stopPropagation()}r=void 0}},ce)},de=new Map;de.clear(),de.set("none",{backward:{both:void 0,incoming:void 0,outgoing:void 0},forward:{both:void 0,incoming:void 0,outgoing:void 0}});const ue={both:"",outgoing:"outgoing-",incoming:"incoming-"},fe={forward:"",backward:"-backward"},me=e=>`--marp-bespoke-transition-animation-${e}`,ge=e=>`--marp-transition-${e}`,pe=me("name"),ve=me("duration"),he=e=>new Promise(t=>{const n={},r=document.createElement("div"),o=e=>{r.remove(),t(e)};r.addEventListener("animationstart",()=>o(n)),Object.assign(r.style,{animationName:e,animationDuration:"1s",animationFillMode:"both",animationPlayState:"paused",position:"absolute",pointerEvents:"none"}),document.body.appendChild(r);const a=getComputedStyle(r).getPropertyValue(ge("duration"));a&&Number.parseFloat(a)>=0&&(n.defaultDuration=a),((e,t)=>{requestAnimationFrame(()=>{e.style.animationPlayState="running",requestAnimationFrame(()=>t(void 0))})})(r,o)}),ye=async e=>de.has(e)?de.get(e):(e=>{const t={},n=[];for(const[r,o]of Object.entries(ue))for(const[a,i]of Object.entries(fe)){const s=`marp-${o}transition${i}-${e}`;n.push(he(s).then(e=>{t[a]=t[a]||{},t[a][r]=e?{...e,name:s}:void 0}))}return Promise.all(n).then(()=>t)})(e).then(t=>(de.set(e,t),t)),be=e=>Object.values(e).flatMap(Object.values).every(e=>!e),we=(e,{type:t,backward:n})=>{const r=e[n?"backward":"forward"],o=(()=>{const e=r[t],n=e=>({[pe]:e.name});if(e)return n(e);if(r.both){const e=n(r.both);return"incoming"===t&&(e[me("direction")]="reverse"),e}})();return!o&&n?we(e,{type:t,backward:!1}):o||{[pe]:"__bespoke_marp_transition_no_animation__"}},xe=e=>{if(e)try{const t=JSON.parse(e);if((e=>{if("object"!=typeof e)return!1;const t=e;return"string"==typeof t.name&&(void 0===t.duration||"string"==typeof t.duration)})(t))return t}catch{}},ke="_tSId",$e="_tA",Ee="bespoke-marp-transition-warming-up",Le=window.matchMedia("(prefers-reduced-motion: reduce)"),Se="__bespoke_marp_transition_reduced_outgoing__",Pe="__bespoke_marp_transition_reduced_incoming__",_e={forward:{both:void 0,incoming:{name:Pe},outgoing:{name:Se}},backward:{both:void 0,incoming:{name:Pe},outgoing:{name:Se}}},Te=e=>{if(!document.startViewTransition)return;const t=t=>(void 0!==t&&(e._tD=t),e._tD);let n;t(!1),((...e)=>{CSS.registerProperty({name:ge("duration"),syntax:"<time>",inherits:!0,initialValue:"-1s"});const t=[...new Set(e).values()];return Promise.all(t.map(e=>ye(e))).then()})(...Array.from(document.querySelectorAll("section[data-transition], section[data-transition-back]")).flatMap(e=>[e.dataset.transition,e.dataset.transitionBack].flatMap(e=>{const t=xe(e);return[t?.name,t?.builtinFallback?`__builtin__${t.name}`:void 0]}).filter(e=>!!e))).then(()=>{document.querySelectorAll("style").forEach(e=>{e.innerHTML=e.innerHTML.replace(/--marp-transition-duration:[^;}]*[;}]/g,e=>e.slice(0,-1)+"!important"+e.slice(-1))})});const r=(n,{back:r,cond:o})=>a=>{const i=t();if(i)return!!a[$e]||!("object"!=typeof i||(i.skipTransition(),!a.forSync));if(!o(a))return!0;const s=e.slides[e.slide()],c=()=>a.back??r,l="data-transition"+(c()?"-back":""),d=s.querySelector(`section[${l}]`);if(!d)return!0;const u=xe(d.getAttribute(l)??void 0);return!u||((async(e,{builtinFallback:t=!0}={})=>{let n=await ye(e);if(be(n)){if(!t)return;return n=await ye(`__builtin__${e}`),be(n)?void 0:n}return n})(u.name,{builtinFallback:u.builtinFallback}).then(e=>{if(!e){t(!0);try{n(a)}finally{t(!1)}return}let r=e;Le.matches&&(console.warn("Use a constant animation to transition because preferring reduced motion by viewer has detected."),r=_e);const o=document.getElementById(ke);o&&o.remove();const i=document.createElement("style");i.id=ke,document.head.appendChild(i),((e,t)=>{const n=[`:root{${ge("direction")}:${t.backward?-1:1};}`,":root:has(.bespoke-marp-inactive){cursor:none;}"],r=t=>{const n=e[t].both?.defaultDuration||e[t].outgoing?.defaultDuration||e[t].incoming?.defaultDuration;return"forward"===t?n:n||r("forward")},o=t.duration||r(t.backward?"backward":"forward");void 0!==o&&n.push(`::view-transition-group(*){${ve}:${o};}`);const a=e=>Object.entries(e).map(([e,t])=>`${e}:${t};`).join("");return n.push(`::view-transition-old(root){${a(we(e,{...t,type:"outgoing"}))}}`,`::view-transition-new(root){${a(we(e,{...t,type:"incoming"}))}}`),n})(r,{backward:c(),duration:u.duration}).forEach(e=>i.sheet?.insertRule(e));const s=document.documentElement.classList;s.add(Ee);let l=!1;const d=()=>{l||(n(a),l=!0,s.remove(Ee))},f=()=>{t(!1),i.remove(),s.remove(Ee)};try{t(!0);const e=document.startViewTransition(d);t(e),e.finished.finally(f)}catch(e){console.error(e),d(),f()}}),!1)};e.on("prev",r(t=>e.prev({...t,[$e]:!0}),{back:!0,cond:e=>e.index>0&&!((e.fragment??1)&&n.fragmentIndex>0)})),e.on("next",r(t=>e.next({...t,[$e]:!0}),{cond:t=>t.index+1<e.slides.length&&!(n.fragmentIndex+1<n.fragments.length)})),setTimeout(()=>{e.on("slide",r(t=>e.slide(t.index,{...t,[$e]:!0}),{cond:t=>{const n=e.slide();return t.index!==n&&(t.back=t.index<n,!0)}}))},0),e.on("fragment",e=>{n=e})};let Ie;const Me=()=>(void 0===Ie&&(Ie="wakeLock"in navigator&&navigator.wakeLock),Ie),Oe=async()=>{const e=Me();if(e)try{return await e.request("screen")}catch(e){console.warn(e)}return null},Ae=async()=>{if(!Me())return;let e;const t=()=>{e&&"visible"===document.visibilityState&&Oe()};for(const e of["visibilitychange","fullscreenchange"])document.addEventListener(e,t);return e=await Oe(),e};((e=document.getElementById(":$p"))=>{(()=>{const e=p("view");a.dataset.bespokeView=e===l||e===c?e:""})();const t=(e=>{const t=p(e);return v({[e]:void 0}),t})("sync")||void 0;o.from(e,((...e)=>{const t=d.findIndex(e=>g()===e);return e.map(([e,n])=>e[t]&&n).filter(e=>e)})([[1,1,0],re({key:t})],[[1,1,1],Z(e)],[[1,1,0],M],[[1,1,1],k],[[1,0,0],T()],[[1,1,1],O],[[1,1,1],ne({history:!1})],[[1,1,0],A()],[[1,1,0],P],[[1,0,0],ee],[[1,1,0],le()],[[1,0,0],C()],[[1,0,0],Te],[[1,1,1],$],[[1,1,0],Ae]))})()}();</script></body></html>