文件操作

int open(const char filename, int flags);
int open(const char
filename, int flags, mode_t, mode);

  • filename 如果不写路径,默认是当前路径。

  • flags 打开方式,O_RDONLY,O_WRONLY,O_RDWR中只选择一个。其他组合方式,如果没有实际意义,系统也不会处理,如O_RDONLY和O_APPEND

image.png
创建一个文件,不设置文件属主和属组的执行ID(0),文件属主有读写和执行的权限(1+2+4=7),文件属组有读和执行的权限(1+4=5),其他用户没有任何权限(0),则函数调用形式如下

  • 文件属主 文件的创建人
  • 文件属组 文件创建人权限,所属组
  • 其他用户

open(“test”, O_CREAT, 00750);

如果文件创建成功,会返回一个文件描述符,以后对该文件的操作就可以通过此文件描述符进行,否则返回-1,并输出文件描述符。

打开文件

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h> /** open */
  4. #include <sys/stat.h>
  5. #include <sys/types.h>
  6. #include <unistd.h> /** close */
  7. int main(int argvLength, char *argv[])
  8. {
  9. int fol;
  10. // S_IRWXU 文件属主可以,读写执行
  11. // S_IRGRP 文件属组可以,读
  12. // S_IXGRP 文件属组可以,执行
  13. // O_CREAT 如果没有文件的话,创建一个文件
  14. fol = open("file.txt", O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP);
  15. int i = S_IRWXU | S_IRGRP | S_IXGRP;
  16. printf("%d\n", i);
  17. printf("%d\n", fol);
  18. // 关闭文件,释放资源 返回0标识关闭成功,-1表示关闭失败
  19. int closeFlag = close(fol);
  20. printf("关闭成功状态 %d\n", closeFlag);
  21. // 创建一个文件 int creat(const char *filename, mode_t mode);
  22. creat("file2.txt", 00750);
  23. // O_EXCL 与 O_CREAT 配合使用,如果文件已存在会返回-1,并将错误码存在errno中
  24. fol = open("file.txt", O_CREAT | O_EXCL, 00750);
  25. if (fol == -1) {
  26. // 读取变量errno中的的值,并打印
  27. perror("文件打开失败"); // 文件打开是不:File exists
  28. // 有时候也需要使用 char *strerror(int errnum); 函数,有些函数的错误码并不保存在errno中,
  29. // 而是通过返回值返回,就只能使用strerror函数了。
  30. exit(1);
  31. }
  32. return 0;
  33. }

读写文件

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h> /** open */
  4. #include <sys/stat.h>
  5. #include <sys/types.h>
  6. #include <unistd.h> /** close */
  7. /**
  8. * @brief 关闭文件
  9. *
  10. * @param fol
  11. * @return int
  12. */
  13. int closeFile(int fol) {
  14. int closeFlag = close(fol);
  15. if (closeFlag == -1) {
  16. printf("关闭文件失败");
  17. exit(1);
  18. }
  19. printf("关闭文件成功\n");
  20. return 0;
  21. }
  22. void toString(char *p) {
  23. printf("%s\n", p);
  24. }
  25. int main(int argvLength, char *argv[])
  26. {
  27. int fol;
  28. fol = open("file.txt", O_RDWR);
  29. if (fol == -1) {
  30. perror("打开文件失败");
  31. exit(1);
  32. }
  33. // ssize_t write(int fd, void *buffer, size_t count);
  34. // 写入数据
  35. char str[] = "ABC\nDEF\n";
  36. int len = sizeof(str) / sizeof(char);
  37. write(fol, str, len);
  38. closeFile(fol);
  39. printf("写入内容\n %s \n成功\n", str);
  40. fol = open("file.txt", O_RDWR);
  41. // ssize_t read(int fd, void *buffer, size_t count);
  42. // 读文件
  43. char strBlock[100]; // 定义缓冲区
  44. char *p;
  45. int flag;
  46. while ((flag = read(fol, strBlock, 100)) != 0)
  47. {
  48. if (flag == -1) {
  49. perror("读取文件失败");
  50. exit(1);
  51. }
  52. printf("%s \n", strBlock);
  53. toString(strBlock);
  54. p = strBlock;
  55. printf("%s \n", p);
  56. }
  57. closeFile(fol);
  58. return 0;
  59. }

文件指针操作

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h> /** open */
  4. #include <sys/stat.h>
  5. #include <sys/types.h>
  6. #include <unistd.h> /** close */
  7. #include <string.h>
  8. /**
  9. * @brief 关闭文件
  10. *
  11. * @param fol
  12. * @return int
  13. */
  14. int closeFile(int fol) {
  15. int closeFlag = close(fol);
  16. if (closeFlag == -1) {
  17. printf("关闭文件失败");
  18. exit(1);
  19. }
  20. printf("关闭文件成功\n");
  21. return 0;
  22. }
  23. void toString(char *p) {
  24. printf("%s\n", p);
  25. }
  26. int main(int argvLength, char *argv[])
  27. {
  28. int fd;
  29. char inputStr[100];
  30. fd = open("file.txt", O_RDWR);
  31. if (fd == -1) {
  32. printf("打开文件失败");
  33. return -1;
  34. }
  35. char str[] = "ABCDEF\n";
  36. int len = (sizeof(str) / sizeof(char));
  37. write(fd, str, len);
  38. len = (sizeof(inputStr) / sizeof(char));
  39. printf("定义字段长度为:%d\n", len); // 输出100
  40. printf("定义字段长度为:%lu\n", strlen(inputStr)); // 输出1
  41. printf("请输入内容:");
  42. scanf("%s", inputStr); // 输入 abcdef
  43. // 文件指针操作 off_t lseek(int fd, off_t offset, int whence);
  44. // whence 是参考点 取值范围如下。
  45. // SEEK_SET 文件开始位置
  46. // SEEK_CUR 文件指针当前位置
  47. // SEEK_END 文件的结尾
  48. // lseek(fd, 0, SEEK_SET) // 移动光标到开始位置
  49. // lseek(fd, 0, SEEK_END) // 移动光标到结束位置
  50. // lseek(fd, 0, SEEK_CUR) // 获取当前光标位置
  51. lseek(fd, 0, SEEK_SET); // 将光标移动到开始位置
  52. len = (sizeof(inputStr) / sizeof(char));
  53. printf("输入内容的长度为:%d\n", len); // 输出100
  54. printf("输入内容的长度为:%lu\n", strlen(inputStr)); // 输出6
  55. write(fd, inputStr, len);
  56. char nowStr[len];
  57. lseek(fd, 0, SEEK_SET); // 将光标移动到开始位置 // 读写都要控制光标位置
  58. read(fd, nowStr, len);
  59. toString(nowStr);
  60. closeFile(fd);
  61. return 0;
  62. }

硬链接,软链接,删除链接文件

软链接和硬链接的区别:

  • 不能对目录创建硬链接;可以对目录创建软链接,遍历操作会忽略目录的软链接。
  • 不能对不同的文件系统创建硬链接;可以跨文件系统创建软链接。
  • 不能对不存在的文件创建硬链接;可以对不存在的文件创建软链接。
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <fcntl.h> /** open */
  4. #include <sys/stat.h>
  5. #include <sys/types.h>
  6. #include <unistd.h> /** close */
  7. #include <string.h>
  8. /**
  9. * @brief 关闭文件
  10. *
  11. * @param fol
  12. * @return int
  13. */
  14. int closeFile(int fol) {
  15. int closeFlag = close(fol);
  16. if (closeFlag == -1) {
  17. printf("关闭文件失败");
  18. exit(1);
  19. }
  20. printf("关闭文件成功\n");
  21. return 0;
  22. }
  23. int main(int argvLength, char *argv[])
  24. {
  25. int fd;
  26. fd = open("file.txt", O_RDWR | O_CREAT, 00750);
  27. if (fd == -1) {
  28. printf("打开文件失败");
  29. return -1;
  30. }
  31. char str[] = "ABCDEF\n";
  32. int len = (sizeof(str) / sizeof(char));
  33. write(fd, str, len);
  34. // int dup(int oldfd); // copy fd,不需要在open,不够要分开关闭哦
  35. int newfd = dup(fd);
  36. char str1[] = "GHIJKLMN\n";
  37. len = (sizeof(str1) / sizeof(char));
  38. write(newfd, str1, len);
  39. closeFile(newfd);
  40. closeFile(fd);
  41. // int symlink(const char *oldPath, const char *newPath);
  42. // 创建一个符号链接(软链接),成功返回0,失败返回-1,
  43. // 用 ls -al 查看 显示 file1.txt -> ./file.txt
  44. symlink("./file.txt", "./file1.txt");
  45. // int link(const char *oldPath, const char *newPath); // 创建硬链接
  46. symlink("./file.txt", "./file2.txt");
  47. /**
  48. * 区别:不能对目录创建硬链接;可以对目录创建软链接,遍历操作会忽略目录的软链接。
  49. * 不能对不同的文件系统创建硬链接;可以跨文件系统创建软链接。
  50. * 不能对不存在的文件创建硬链接;可以对不存在的文件创建软链接。
  51. */
  52. // int unlink(const char *filename);
  53. // 成功返回0,失败返回-1,,由于文件的硬链接是使用多个文件名来引用同一个数据块,
  54. // 因此unlink函数实质上是将文件连接数减一,连接数为0时,才真正将文件删除
  55. unlink("./file1.txt");
  56. return 0;
  57. }

文件目录新建和删除

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h> /*包含相关函数头文件*/
  4. #include <fcntl.h>
  5. #include <sys/stat.h>
  6. int main(int argc, char **argv) {
  7. // int rmdir(const char *) 删除文件, 只能删除空文件夹
  8. int deleteResult = rmdir("abc");
  9. if (deleteResult == -1) {
  10. perror("删除文件夹失败");
  11. exit(1);
  12. }
  13. // S_IRUSR 读
  14. // S_IXUSR 执行
  15. // S_IWUSR 写
  16. // drwx------
  17. // int result = mkdir("abcd", S_IRUSR | S_IXUSR | S_IWUSR);
  18. // drwxr-x---
  19. int result = mkdir("abcd", 00750);
  20. if (result == -1) {
  21. perror("创建文件目录失败\n");
  22. exit(1);
  23. }
  24. printf("创建文件目录完成\n");
  25. return 0;
  26. }

目录操作

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /*包含相关函数头文件*/
#include <fcntl.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>

int main(int argc, char **argv) {
  // 切换目录
  // int chdir(const char *path);
  chdir("/");

  // 获取当前目录
  // buf缓冲区指针,size_t 缓冲区大小,如果缓冲区不够大会返回NULL,并设置错误码ERANGE
  // char *getcwd(char *buf, size_t size);
  char __dirname[1024];
  char *tempDirname = getcwd(__dirname, sizeof __dirname);

  if (tempDirname == NULL) {
    perror("获取当前目录失败");
    exit(1);
  } else {
    printf("%s\n", tempDirname); // /Users/root/test
    printf("%s\n", __dirname);   // /Users/root/test
  }

  // DIR *opendir(const char *name); 打开文件目录
  // int closedir(DIR *dir); // 关闭文件目录
  DIR *dir;
  struct dirent *dirp;

  dir = opendir(argv[1]);

  if (dir == NULL) {
    perror("打开文件夹失败");
    exit(1);
  }

  printf("打开文件成功\n");

  // struct dirent {
  //   ino_t d_ino; /**索引节点编号*/
  //   ff_t d_off; /**记录的位移*/
  //   signed short int d_reclen; /**记录的长度*/
  //   unsigned char d_type; /**文件的类型*/
  //   har d_name[256]; /**文件名*/
  // }

  while ((dirp = readdir(dir)) != NULL) {
    if (strcmp(dirp->d_name, ".") == 0 || strcmp(dirp->d_name, "..") == 0) {
      // continue; // 跳过父目录,和自身
    }
    if (dirp->d_type == DT_DIR) {
      printf("<directory> %s\n", dirp->d_name);
    } else {
      printf("%s\n", dirp->d_name);
    }
  }

  closedir(dir);
  return 0;
}

获取文件属性

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /*包含相关函数头文件*/
#include <sys/stat.h>


// struct stat {
//   dev_t st_dev; /*设备编号*/
//   int_t st_ino; /*索引节点*/
//   mode_t st_mode; /*文件的类型和访问权限*/
//   nlink_t st_nlink; /*连接到文件的硬连接个数,文件新创建时为1*/
//   uid_t st_uid; /*文件的uid*/
//   gid_t st_gid; /*文件的gid*/
//   dev_t st_rdev; /*设备类型*/
//   off_t st_size; /*文件的大小*/
//   unsigned long st_blksize; /*文件系统I/O缓冲区大小*/
//   unsigned long st_blocks; /*占用块的个数*/
//   time_t st_atime; /*上一次访问文件的时间*/
//   time_t st_mtime; /*上一次修改文件的时间*/
//   time_t st_ctime; /*上一次修改文件属性的时间*/
// }

/* st_mode 
S_IFSOCK 套接字
S_IFLNK 符号连接
S_IFREG 普通文件
S_IFBLK 块设备文件
S_IFDIR 目录文件
S_IFCHR 字符设备文件
S_IFIFO 管道文件
*/

/* 判断一个文件的类型可以通过 (st_mode & IFSOCK) == 0
S_ISSOCK(st_mode) 判断文件是否为套接字
S_ISLINK(st_mode) 判断文件是否为符号连接
S_ISREG(st_mode)  判断文件是否为普通文件
S_ISBLK(st_mode) 判断文件是否为块设备文件
S_ISDIR(st_mode) 判断文件是否为目录文件
S_ISCHR(st_mode) 判断文件是否为字符设备文件
S_IFIFO(st_mode) 判断文件是否为管道文件
*/

int main(int argc, char **argv) {
  struct stat sta;
  if (argc != 2) {
    printf("请输入参数");
    exit(1);
  }

  // int access(const char *filename, int mode);
  // mode 为 R_OK W_OK X_OK 分别表示可读,可写,可执行
  // F_OK 表示文件存在

  if (access(argv[1], F_OK) != -1) {
    if (access(argv[1], R_OK) != -1) {
      printf("文件可以被读取\n");
    }
    if (access(argv[1], W_OK) != -1)
    {
      printf("文件可以被写入\n");
    }
    if (access(argv[1], X_OK) != -1)
    {
      printf("文件可以被执行\n");
    }
  } else {
    printf("文件不存在!!");
    exit(1);
  }

  // 获取文件属性
  // int stat(const char *filename, struct stat *buf);
  int fd = stat(argv[1], &sta);
  // int fstat(int fd, struct stat *buf); 和 stat功能一致,只是如此不一样,fd为以打开的文件描述符
  // open函数也可以返回文件描述符
  printf("文件大小:%lld Byte\n", sta.st_size);
  // 输出文件类型
  switch(sta.st_mode & S_IFMT) {
    case S_IFSOCK:
      printf("套接字\n");
      break;
    case S_IFLNK:
      printf("符号连接\n");
      break;
    case S_IFREG:
      printf("普通文件\n");
      break;
    case S_IFBLK:
      printf("块设备文件\n");
      break;
    case S_IFDIR:
      printf("目录文件\n");
      break;
    case S_IFCHR:
      printf("字符设备文件\n");
      break;
    case S_IFIFO:
      printf("管道文件\n");
      break;
  }

  return 0;
}

修改文件属性,访问权限,属主,属组

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <unistd.h> /*包含相关函数的头文件*/

int main(int argc, char **argv) {
  int result = chmod("./text.txt", 00777);
  if (result == -1) {
    perror("修改文件权限失败");
    exit(1);
  }
  printf("修改文件权限成功");

  // int chown(const char *path, uid_t owner, gid_t group); // 修改用户属主和属组,成功返回0,失败返回-1
  // int utime(const char *filename, struct utimebuf *buf); // 修改文件访问时间与修改时间,成功返回0,失败返回-1

  // 更改正在使用的文件的属性,有以下三种形式
  // int fcntl(int fd, int cmd);
  // int fcntl(int fd, int cmd, long arg);
  // int fcntl(int fd, int cmd, struct flock *lock);

  return 0;
}

标准输入输出流

字符读取,字符写入

FILE fopen(const char filename, const char modes);
int fgetc(FILE
fp);
int fputc(int c, FILE fp);
void rewind(FILE
fp);
int fseek(FILE *fp, long offset, int whence);

#include <stdio.h>
#include <stdlib.h>

int main()
{
  // FILE *fopen(const char *filename, const char *modes);
  // modes = "r" | "w" | "a" | "r+" | "w+" | "a+"
  // "r" 只读,文件必须存在
  // "w" 写,文件不存在的话,创建文件,文件存在则替换文件原有内容
  // "a" 在文件末尾追加,如果不存在的话,创建文件
  // "r+" 读和写,文件必须存在
  // "w+" 读和写,文件不存在创建文件,文件存在替换文件原有内容
  // "a+" 读和追加,如果不存在则创建文件
  FILE *fp;
  FILE *fpw;
  fp = fopen("./text.txt", "r+");
  fpw = fopen("./text_w.txt", "r+");

  if (fp == NULL) {
    perror("打开文件失败!");
    exit(1);
  }

  if (fpw == NULL)
  {
    perror("打开文件失败!");
    exit(1);
  }

  printf("文件打开成功\n");

  int c;
  // 读
  // int fgetc(FILE *fp) 从文件中读取一个字符
  // stdin 表示输入流
  // int fgetc(stdin) 等价于 int getchar();
  // getchar函数是从标准输入流中读取一个字符

  // 写
  // int fputc(int c, FILE *fp); 向指定文件写入一个字符
  // stdout 表示输出流
  // int fputc(c, stdout) 等价于 int putchar(int c);
  // putchar函数是向标准输出流中写入一个字节

  // void rewind(FILE *fp); 重设读写的位置,将读写位置移动到开始位置,
  // int fseek(FILE *fp, long offset, int whence); 和lseek的用法一致
  // fseek(fp, 0, SEEK_SET) // 移动光标到开始位置
  // fseek(fp, 0, SEEK_END) // 移动光标到结束位置
  // fseek(fp, 0, SEEK_CUR) // 获取当前光标位置
  // long ftell(*fp); 返回当前读写位置

  while ((c = fgetc(fp)) != EOF) {
    printf("%d %c\n", c, (char)c);
    fputc(c, fpw);
  }

  fclose(fp);
  fclose(fpw);
  return 0;
}

缓冲区设置

#include <stdio.h>
#include <stdlib.h>

int main()
{

  FILE *fp;
  fp = fopen("text.txt", "a+");

  if (fp == NULL)
  {
    perror("打开文件失败!");
    exit(1);
  }

  int c;

  // 设置缓冲区属性
  // int setvbuf(FILE *fp, char *buf, int mode, size_t size);
  // mode: _IOFBF,_IOLBF,_IONBF 对应全缓冲,行缓冲,无缓冲
  // 全缓冲,缓冲区被填满后才执行输入输出操作
  // 行缓冲,填入换行符时,执行输入输出操作
  // 无缓冲,不对数据进行缓冲
  // (1) setvbuf(fp, NULL, _IONBF, 0); // 设置无缓冲

  // char str[10];
  // (2)setvbuf(fp, str, _IOFBF, 10); // 设置全缓冲

  // (3)setvbuf(fp, NULL, _IOLBF, 0); // 设置行缓冲

  // setbuf方法buf设置为NULL会变成无缓冲,否则为全缓冲,缓冲区大小由stdio.h中的常量BUFSIZE决定,
  // 默认情况为512字节
  // int setbuf(FILE *fp, char *buf);

  // setbuffer如果buf为NULL,缓冲区将被设置成无缓冲,否则为全缓冲,大小由size决定
  // int setbuffer(FILE *fp, char *buf, size_t size);

  // 设置行缓冲等价于setvbuf(fp, NULL, _IOLBF, 0);
  // int setlinebuf(FILE *fp);

  while ((c = getchar()) != '0')
  {
    printf("%c", (char)c);
    fputc(c, fp);
    // 将缓冲区数据,写入磁盘或终端,如果不调用这个的话,
    // 在程序未结束前或缓冲区未满前,不做写入操作
    // int fflush(FILE *fp); // 将缓冲区数据,写入磁盘或终端
    // int fpurge(FILE *fp); // 清空缓存区,丢弃
    // fflush(fp);
  }

  fclose(fp);

  return 0;
}

字符串读取,字符串写入

#include <stdio.h>
#include <stdlib.h>

int main()
{

  FILE *fp;
  FILE *fp1;

  fp = fopen("text.txt", "r+");
  fp1 = fopen("text.txt", "a+");

  if (fp == NULL || fp1 == NULL)
  {
    perror("打开文件失败!");
    exit(1);
  }

  // int fputs(const char *s, FILE *fp);

  fputs("今天是一个好天气", fp1);
  fflush(fp1);

  // char *fgets(char *s, int n, FILE *fp);
  int size = 256;
  char buffer[size];

  // fgets(buffer, size, fp) != NULL
  // int feof(FILE *fp); 测试是否到文件尾。
  while (!feof(fp)) {
    fgets(buffer, size, fp);
    printf("%s", buffer);
  }
  printf("\n");

  fclose(fp);

  return 0;
}

读写数据块

#include <stdio.h>
#include <stdlib.h>
#define LEN 3

struct student {
  int id;
  int score;
};

int read()
{
  struct student array[LEN];
  FILE *fp;
  // DAT是流格式: DAT是是数据流格式
  fp = fopen("./text.dat", "r");

  if (fp == NULL)
  {
    perror("打开文件失败!");
    exit(1);
  }

  // 读取数据块
  // size_t fread(void *ptr, size_t size, size_t n, FILE * fp);
  int num = 0;
  num = fread(array, sizeof(struct student), LEN, fp);

  if (num != LEN) {
    if (feof(fp)) {
      printf("读取文件结束!");
    } else {
      printf("读取文件失败!");
    }
  }

  int i = 0;
  for (; i < LEN; i++) {
    printf("id=%d, score=%d\n", array[i].id, array[i].score);
  }

  fclose(fp);
  return 0;
}

int write()
{
  struct student array[LEN];
  FILE *fp;
  // DAT是流格式: DAT是是数据流格式
  fp = fopen("./text.dat", "w");

  if (fp == NULL)
  {
    perror("打开文件失败!");
    exit(1);
  }

  int i = 0;
  for (; i < LEN; i++)
  {
    printf("id:");
    scanf("%d", &array[i].id);
    printf("分数:");
    scanf("%d", &array[i].score);
    printf("\n");
  }

  // 写入数据块
  // size_t fread(void *ptr, size_t size, size_t n, FILE * fp);
  int sum = 0;
  sum = fwrite(array, sizeof(struct student), LEN, fp);

  if (sum != LEN)
  {
    printf("写入失败");
    exit(1);
  }

  fclose(fp);

  return 0;
}

int main() {
  // 数据块的读取和写入
  write();
  read();
  return 0;
}

格式化输入输出

int printf(const char format, …);
int scanf(const char
format, …);
int fprintf(FILE fp, const char format, …);
int fscanf(FILE fp, const char format, …);

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

// 定义可变参数函数
int myprintf(char *format, ...) {
  // int vfprintf(FILE *fp, const char *format, va_list ap);
  // int vprintf(const char *format, va_list ap);
  // int vfscanf(FILE *fp, const char *format, va_list ap);
  // int vscanf(const char *format, va_list ap);

  // 宏 <stdarg.h>
  // va_list
  // va_start
  // va_arg
  // va_end

  va_list vp;
  int n;
  va_start(vp, format);
  n = vprintf(format, vp);
  va_end(vp);

  return n;
}

int main() {
  // 格式化输入输出
  // int fprintf(FILE *fp, const char *format, ...);
  // stdout 输出流
  // fprintf(stdout, const char *format, ...) 等价于 int printf(const char *format, ...);

  // int fscanf(FILE *fp, const char *format, ...);
  // stdin 输入流
  // fscanf(stdin, const char *format, ...) 等价于 int scanf(const char *format, ...);


  FILE *fp;
  fp = fopen("./text.txt", "w");

  if (fp == NULL) {
    printf("打开文件失败!");
    exit(1);
  }

  int i = 99;
  fprintf(fp, "i = %d\n", i);
  myprintf("%d ,%d\n", i, i);

  fclose(fp);
  return 0;
}