施展 武汉光电国家研究中心 & 计算机学院 华中科技大学
从键盘输入若干行字符,保存到 d:\a.txt 中,该如何做?
d:\a.txt
%% 键盘输入 → 程序 → 文件 flowchart LR A([键盘]) -->|stdin| B([savefile.exe]) B -->|fputc| C[(d:\a.txt)]
getchar
#include <stdio.h> int main(void) { FILE *fp; char ch; if ((fp = fopen("d:\\a.txt", "w")) == NULL) { printf("can't open the file!"); return -1; } while ((ch = getchar()) != EOF) fputc(ch, fp); fclose(fp); return 0; }
fgetc(stdin)
/* 功能同上,仅把 getchar 换成 fgetc(stdin) */ while ((ch = fgetc(stdin)) != EOF) fputc(ch, fp);
int fgetc(FILE *stream);
int fputc(int c, FILE *stream);
getchar()
fputc(c, stdout)
putchar(c)
#include <stdio.h> int main(void) { FILE *fp; char ch; if ((fp = fopen("d:\\a.txt", "r")) == NULL) { printf("can't open the file!"); return -1; } while ((ch = fgetc(fp)) != EOF) putchar(ch); /* 也可用 fputc(ch, stdout); */ fclose(fp); return 0; }
char *fgets(char *s, int n, FILE *stream);
int fputs(const char *s, FILE *stream);
fgets
gets
fputs
puts
int fprintf(FILE *stream, const char *fmt, …);
int fscanf(FILE *stream, const char *fmt, …);
fscanf(stdin, "%d", &x)
scanf(...)
fprintf(stdout, "%d", x)
printf(...)
命令行:
parts abc.txt a.txt b.txt c.txt 10
把 abc.txt 每 10 行切成一个小文件
abc.txt
flowchart TD A[命令行参数解析\nlen=10] --> B[打开 abc.txt] B --> C{还有目标文件名?} C -->|是| D[新建目标文件] D --> E[读 len 行写入] E --> C C -->|否| F[关闭所有文件]
d:\goods.txt
#include <stdio.h> #include <stdlib.h> void data_write(char *); void data_cal(char *, float); int main(void) { char file[20] = "d:\\goods.txt"; data_write(file); data_cal(file); return 0; }
void data_write(char *filename) { FILE *out; char name[20]; int number; float price; if ((out = fopen(filename, "w")) == NULL) exit(-1); puts("input name、number and price please!"); while (scanf("%s%d%f", name, &number, &price) != EOF) fprintf(out, "%s %d %f\n", name, number, price); fclose(out); }
void data_cal(char *filename) { FILE *in; char name[5]; int number; float price; if ((in = fopen(filename, "r")) == NULL) exit(-1); while (fscanf(in, "%s%d%f", name, &number, &price) != EOF) printf("%s\t%d\t%8.2f\n", name, number, price * number); fclose(in); }
短整数 x = 128 分别占多少字节?
x = 128
%% 128 的两种存储形式 flowchart LR subgraph 文本文件 A["'1' '2' '8'"] --> B["3 字节"] end subgraph 二进制文件 C["0x0080"] --> D["2 字节"] end
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t n, FILE *stream);
int x[] = {12, 8, 34, 421}; FILE *fp = fopen("d:\\a.dat", "wb"); /* 写法 1:一次性写 4 个 int */ fwrite(x, sizeof(int), 4, fp); /* 写法 2:循环写 */ for (int i = 0; i < 4; i++) fwrite(x + i, sizeof(int), 1, fp); fclose(fp);
int x[10], i = 0; FILE *fp = fopen("d:\\a.dat", "rb"); while (fread(x + i, sizeof(int), 1, fp) == 1) i++; fclose(fp);
short x; /* 按二进制读 */ fread(&x, sizeof(short), 1, fp); // x = 0x3231 /* 按文本读 */ fscanf(fp, "%hd", &x); // x = 123
struct goods { long code; char name[20]; float price; } g; /* 把 g 写入文件 */ fwrite(&g, sizeof(struct goods), 1, fp);
while (fread(&g, sizeof(struct goods), 1, in) == 1) printf("%ld\t%s\t%f\n", g.code, g.name, g.price);
int feof(FILE *stream);
/* 正确用法 */ while (!feof(in)) { if (fread(&g, sizeof(struct goods), 1, in) != 1) break; printf("%ld\t%s\t%f\n", g.code, g.name, g.price); }
%% 文本文件数据长度不定,只能顺序读取 sequenceDiagram participant P as fp participant D as 数据流 P->>D: 第1次读 P->>D: 第2次读 P->>D: ...
%% 二进制文件长度固定,可随机访问 stateDiagram-v2 [*] --> Seek Seek --> Read: fseek Seek --> Write: fseek Read --> Seek Write --> Seek
int fseek(FILE *stream, long offset, int origin);
long ftell(FILE *stream);
int fgetpos/fsetpos(FILE *stream, fpos_t *pos);
void rewind(FILE *stream);