导航

CV学习日志:C语言中文件IO使用要点

Posted on 2020-01-27 22:51  dzyBK  阅读(182)  评论(0编辑  收藏  举报

1.prinf(fmt,…)/sprinf(str,fmt,…)/fsprintf(file,fmt,…)

         (1)格式:%[标志][宽度][.精度][长度]<类型>

         (2)宽度:若实际位数大于宽度则按实际位数输出,若小于宽度则用空格或0填充

         (3)精度:对整型若超出则完整输出若不足则高位补0,对浮点型表示最多输出的小数位,对字串表示最多输出的字符数

         (4)标志

                  对齐方式:-表示左对齐输出,而默认是右对齐车联网

                  符号显示:+表示正负数前正负号,空格表示正数前加空格、负数前加负号

                  空位填充:0表示左边有空位则用0填充(但对指定了最大精度的整型失效)

                  进制前缀:#表示八进制前加o、十六进制前加0x

2.scanf(fmt, …)/sscanf(str,fmt,…)/fscanf(file,…)

         (1)从键盘流/字符流/文件流读数据

         (2)读取时跳过输入流开头的空字符(如space/enter/tab)

         (3)读到空字符(如space/enter/tab)时返回

         (4)scanf输入回车后才能启动读

         (5)成功读时返回读的项数,失败(出错或读到文件尾)返回EOF

3.fwrite(ptr, size, count, file)/fread(ptr, size, count, file)

         (1)fwrite从ptr写入size*count字节到file、fread从file中读取size*count字节到ptr

         (2)参数ptr尺寸应不小于size*count,否则程序崩溃

         (3)等价地fwrite(ptr,size,count,file)=fwrite(ptr,size*count,1,file)=fwrite(ptr,1,size*count,file)

         (4)等价地fread(ptr,size,count,file)=fread(ptr,size*count,1,file)=fread(ptr,1,size*count,file)

         (5)fread不能跳过空字符(如space/enter/tab),对于文件是由字符文件头和二进制数据段组成的且文件头与数据段由空字符分隔的文件,在读取时要注意读取此空字符(用fget函数即可),否则不能正确地读取数据段。

 

         以下使用样例,依赖于C++14和Spdlog。

 1 #include <spdlog/spdlog.h>
 2 using namespace std;
 3 
 4 class AboutCIO
 5 {
 6 public:
 7     static void aboutPrintf(int argc = 0, char** argv = 0)
 8     {
 9         //1.
10         string path = "./text.txt";
11         vector<int> idxs = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; //C++11 list initialization
12         vector<float> vals = { 1.1f, 2.2f, 3.3f, 4.4f, 5.5f, 6.6f, 7.7f, 8.8f, 9.9f };
13 
14         //2.
15         FILE* file = fopen(path.c_str(), "w"); //write header informations like record numbers for more convenient fscanf if possible
16         for (int k = 0; k < idxs.size(); ++k) fprintf(file, "index: %-10d\tvalue: %-10.3f\n", idxs[k], vals[k]);//fscanf stops when meeting null chars: space, enter, tab and so on.
17         fclose(file);
18         spdlog::info("{} write to: {}", __FUNCTION__, path);
19     }
20     static void aboutScanf(int argc = 0, char** argv = 0)
21     {
22         //1.
23         string path = "./text.txt";
24         vector<int> idxs;
25         vector<float> vals;
26 
27         //2.
28         int idx;
29         float val;
30         char tmp[50];
31         FILE* file = fopen(path.c_str(), "r");//read header informations like record numbers first if possible
32         while (fscanf(file, "%s%d%s%f", tmp, &idx, tmp, &val) != EOF) { idxs.push_back(idx); vals.push_back(val); }
33         fclose(file);
34 
35         //3.
36         for (int k = 0; k < idxs.size(); ++k) spdlog::info("index: {:<10d}\tvalue: {:<10.3f}", idxs[k], vals[k]);
37         spdlog::info("{} read from: {}", __FUNCTION__, path);
38     }
39 
40     static void aboutWrite(int argc = 0, char** argv = 0)
41     {
42         //1.
43         string path = "./mat.bin";
44         vector<int> mat = { 1, 2, 3, 4, 5, 6, 7, 5, 9, 10, 11, 12 };
45         const char* type = typeid(mat[0]).name();
46         int rows = 3;
47         int cols = 4;
48         int stride = int(sizeof(mat[0])) * 4;
49 
50         //2.
51         FILE* file = fopen(path.c_str(), "w");//it is necessary to use header informations for binary files
52         fprintf(file, "type: %s\nrows: %d\ncols: %d\nstride: %d\n", type, rows, cols, stride);//space and enter are necessary for fscanf
53         fwrite(mat.data(), stride, rows, file);//matrix with discontinous storage also could be writen row by row for less memory
54         fclose(file);
55         spdlog::info("{} write to: {}", __FUNCTION__, path);
56     }
57     static void aboutRead(int argc = 0, char** argv = 0)
58     {
59         //1.
60         string path = "./mat.bin";
61         vector<int> mat(1); //type must be determined first
62 
63         //2.
64         char type[10], tmp[50];
65         int rows, cols, stride;
66         FILE* file = fopen(path.c_str(), "r");
67         fscanf(file, "%s%s%s%d%s%d%s%d", tmp, type, tmp, &rows, tmp, &cols, tmp, &stride);
68         fgetc(file);//fread could not skip null chars
69         mat.resize(rows * cols); //assume that stride be equal to sizeof(type) * cols
70         fread(mat.data(), stride, rows, file);
71         fclose(file);
72 
73         //3.
74         spdlog::info("type: {}\nrows: {}\ncols:{}\nstride: {}", type, rows, cols, stride);
75         for (int i = 0, io = 0; i < rows; ++i, io += cols)
76         {
77             string str = fmt::format("row{}: ", i);
78             for (int j = 0, jo = io; j < cols; ++j, ++jo) str += fmt::format("{:<10d}", mat[jo]);
79             spdlog::info(str);
80         }
81         spdlog::info("{} read from: {}", __FUNCTION__, path);
82     }
83 };
84 
85 int main(int argc, char** argv)
86 {
87     spdlog::set_pattern("%v");
88     AboutCIO::aboutPrintf(argc, argv);
89     AboutCIO::aboutScanf(argc, argv);
90     spdlog::info("");
91     AboutCIO::aboutWrite(argc, argv);
92     AboutCIO::aboutRead(argc, argv);
93     return 0;
94 }
View Code