C/C++ 文件 / 字符串 操作大全

https://blog.csdn.net/qq_34719188/article/details/83341176

文章目录
一、需要提前了解的
1. 文件分类
2. 优缺点
3. 实际举例
4. 乱码原因
二、C文件操作
1. 文件打开方式分类
2. 代码详解(各种读写)
三、C++之 cin、cout
1. ios::cout
1.1 cout格式输出
1.2 cout 成员函数
2. ios::cin
2.1 函数声明
2.2 状态位操作函数
四、C++文件操作
1. 文件打开方式分类
2. 读写文本文件
2.1 读文本文件的一字 / 行
2.2 快速读取 txt 文档的行数
2.3 一次性将 txt 所有内容读到 std::string
2.4 读取坐标数据
2.5 其他读写
2.5.1 读 CSV 文件
2.5.2 写 CSV 文件
2.6 标记位
2.6.1 与文件指针相关的函数
2.6.2 参照位置
3. 读写二进制文件
五、C++字符串操作
1. string 转化为 int、float、long、double
2. atoi()、atof()、atol()、itoa()、sprintf()
3. 格式控制符
4. 万能格式转换
5. 万能四舍五入
6. 获取某一路径下所有文件、文件夹的绝对路径
7. 通过指定模板分割字符串
8. 替换 string 中的字符
9. 文件的复制 / 移动
10. 文件的剪切
11. std::string 和 LPCWSTR的转换
一、需要提前了解的
1. 文件分类
计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有 ASCII 编码,二进制文件是基于值编码的文件
文本文件:以 ASCII 码格式存放,一个字节存放一个字符。 文本文件的每一个字节存放一个 ASCII 码,代表一个字符。这便于对字符的逐个处理,但占用存储空间较多,而且要花费转换时间。
二进制文件:以值(补码)编码格式存放。二进制文件是把数据以二进制数的格式存放在文件中的,其占用存储空间较少。 数据按其内存中的存储形式原样存放
2. 优缺点
文件类型    优点    缺点
文本文件    直观,方便记忆    存储量大,转换为二进制速度慢
二进制文件    存储量小,无需转换    一个字节不对应一个字符,故不能直接输出其字符形式
3. 实际举例
short a=10000;

存储位置    表现形式
内存中    00100111 00010000
ASCII    00110001 00110000 00110000 00110000 00110000
二进制    00100111 00010000
注意:‘0’ 的ASCII在十进制下是48,二进制下是00110000

char a[] = “abcde”;

存储位置    表现形式
内存中    01100001 01100010 01100011 01100100 01100101
ASCII    01100001 01100010 01100011 01100100 01100101
二进制    01100001 01100010 01100011 01100100 01100101
‘a’ 的ASCII在十进制下是97,二进制下是 01100001,也就是说字符串在三种情况下表现一致>

4. 乱码原因
当用记事本打开文件时,它首先读取文件物理上所对应的二进制比特流,然后按照你所选择的解码方式来解释这个流,然后将解释结果显示出来。一般来说,你选取的解码方式会是 ASCII 码形式(ASCII 码的一个字符是 8 个比特),接下来,它 8 个比特 8 个比特地来解释这个文件流。例如文件流 01000000_01000001_01000010_01000011"(下划线’’_’’,为了增强可读性手动添加的),第一个 8 比特’‘01000000’‘按 ASCII 码来解码的话,所对应的字符是字符’‘A’’,同理其它 3 个 8 比特可分别解码为’‘BCD’’,即这个文件流可解释成“ABCD”,然后记事本就将这个“ABCD”显示在屏幕上。
记事本无论打开什么文件都按既定的字符编码工作(如 ASCII 码),所以当他打开二进制文件时,出现乱码也是很必然的一件事情了,解码和译码不对应嘛。例如文件流’‘00000000_00000000_00000000_00000001’'可能在二进制文件中对应的是一个四字节的整数 int 1,在记事本里解释就变成了"NULL_NULL_NULL_SOH"这四个控制符。
二、C文件操作
1. 文件打开方式分类
mode    处理方式    当文件不存在时    当文件存在时    向文件输入    从文件输出
“r”    读取    出错    打开文件    ×    √
“w”    写入    建立新文件    覆盖原有文件    √    ×
“a”    追加    建立新文件    在原有文件后追加    √    ×
“r+”    读取/写入    出错    打开文件    √    √
“w+”    写入/读取    建立新文件    覆盖原有文件    √    √
“a+”    读取/追加    建立新文件    在原有文件后追加    √    √
2. 代码详解(各种读写)
#include <stdio.h>
#include <string.h>  //strlen()

/**
 * [Num2TxtIO description] 这个代码演示的是文本文档和二进制的读写数字
 * 优点:磁盘中的文件易读
 * 缺点:花费时间用于转化,占用磁盘空间多
 */
void txtIO1() {
    short a = 10000;
    FILE *fp = fopen("ascii.txt", "w");
    //int fprintf(FILE *stream, const char *format, ...)
    fprintf(fp, "%d", a);  //ASCII文本文件,记事本下正常显示
    fclose(fp);

    //和上面类似,只不过函数不一样
    FILE *fp2 = fopen("bin.txt", "w");
    //size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
    //其中,ptr:指向保存数据的指针;
    //size:每个数据类型的大小;
    //count:数据的个数;
    //stream:文件指针
    fwrite(&a, 2, 1, fp2);  //sizeof(short) = 2 ,一个数据为 1 ,记事本下乱码
    fclose(fp2);
}

/**
 * [txtIO2 description] 这个代码演示的是文本文档和二进制的读写字符串
 * 优点:不需要花费时间转化,相比于文本,占用磁盘空间小
 * 缺点:磁盘文件不易读
 */
void txtIO2() {
    const char *buf = "abcdefg";
    FILE *fp = fopen("ascii2.txt", "w");
    fprintf(fp, "%s", buf); //ASCII文本文件,记事本下正常显示
    fclose(fp);

    FILE *fp2 = fopen("bin2.txt", "w");
    fwrite(buf, 8, 1, fp2);  //ASCII文本文件,记事本下乱码
    fclose(fp2);
}

/**
 * [readOneCharOnceTimeFromTxt description] 一次读写一个字符(文本操作)
 */
void readOneCharOnceTimeFromTxtIO() {
    FILE *fp = fopen("ascii.txt", "w");
    if(fp == NULL) {
        printf("open error\n");
        return ;
    }
    for(char ch = 'a'; ch <= 'z'; ch++) {
        //int fputc ( int ch, FILE * stream );
        printf("%3c", fputc(ch, fp));
    }
    fputc('\n', fp);
    fputc('\n', fp);
    fputc('\n', fp);  //会读出 \n
    fclose(fp);

    FILE *fp2 = fopen("ascii.txt", "r");
    if(fp2 == NULL) {
        printf("open error\n");
        return ;
    }
    //putchar:传入一个0-127的整数(若传入浮点数将会按整数处理),
    //则会向屏幕输出一个对应该数字的字符;
    putchar(10); //换行
    char ch;
    while((ch = fgetc(fp)) && !feof(fp)) //优先级,关系>赋值
        printf("%3c", ch);
    fclose(fp);

    /**
     * feof 这个函数,是去读标志位判断文件是否结束的。
     * 即在读到文件结尾的时候再去读一次,标志位才会置位,
     * 此时再来作判断文件处理结束状态,文件到结尾
     * 如果用于打印,则会出现多打一次的的现象。
     */
}

/**
 * [readOneLineOnceTimeFromTxt description] 一次读写一行字符(文本操作)
 */
void readOneLineOnceTimeFromTxtIO() {
    FILE *fp = fopen("ascci2.txt", "w");
    if(fp == NULL) {
        printf("fopen error\n");
        return ;
    }
    //int fputs(char *str,FILE *fp) ,正常返回0
    printf("%d\n", fputs("abcdefg\n", fp));
    printf("%d\n", fputs("1234567890\n", fp));
    char buf[] = "xyz";
    printf("%d\n", fputs(buf, fp));
    fclose(fp);

    FILE *fp2 = fopen("ascci2.txt", "r");
    if(fp2 == NULL) {
        printf("fopen error\n");
        return ;
    }
    char buf2[1024];  //用1024是因为很少有文本一行超过1024个字节
    //char *fgets(char *str,int length,FILE *fp)
    while(fgets(buf2, 1024, fp2) != NULL) {
        printf("%s", buf2);
    }
    fclose(fp2);
}

/**
 * [readOneBlockFromBinIO description]一次读写一块字符(二进制操作)
 */
void readOneBlockFromBinIO() {
    //int fwrite(void *buffer, int num_bytes, int count, FILE *fp)
    FILE *fpw = fopen("bin.txt", "wb");
    if(fpw == NULL)
        return ;

    const char *p = "China is great!";/*"china \n is \0 great";*/
    fwrite(p, 1, strlen(p) /*+ 6*/, fpw);
    fclose(fpw);

    FILE *fpr = fopen("bin.txt", "rb");
    if(fpr == NULL)
        return;

    char buf[1024];
    int n;
    //int fread(void *buffer, int num_bytes, int count, FILE *fp)
    n = fread(buf, 1, 1024, fpr);
    printf("n = %d\n", n);
    for(int i = 0; i < n; i++) {
        //x格式:以无符号十六进制形式输出整数。对长整型可以用"%lx"格式输出
        //同样也可以指定字段宽度用"%mx"格式输出
        //u格式:以无符号十进制形式输出整数。对长整型可以用"%lu"格式输出。
        //同样也可以指定字段宽度用“%mu”格式输出
        //%#x是带格式输出, 效果为在输出前加 0x
        printf("%#x\n", buf[i]);
    }
    fclose(fpr);
}

/**
 * [filePtrOffset description] 文件指针偏移
 */
void filePtrOffset() {
    //void rewind ( FILE * stream ) 将文件指针重新指向一个流的开头
    //long ftell ( FILE * stream )  得到流式文件的当前读写位置,其返回值是当前读写位置偏离文件
    //头部的字节数
    //int fseek ( FILE * stream, long offset, int origin )   偏移文件指针
    FILE *fp = fopen("sql.txt", "w+");
    fputs("123456789", fp);
    // rewind(fp);
    // fseek(fp,0,SEEK_END);
    fseek(fp, -5, SEEK_END);
    int len = ftell(fp);
    printf("len = %d\n", len);
}

int main() {

    //txtIO1();
    //txtIO2();
    //readOneCharOnceTimeFromTxt();
    //readOneLineOnceTimeFromTxtIO();
    //readOneBlockFromBinIO();
    //filePtrOffset();

    return 0;
}
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
三、C++之 cin、cout
1. ios::cout
1.1 cout格式输出
控制符    功 能
dec    十进制数输出
hex    十六进制输出
oct    八进制数输出
setfill(‘c’)    在给定的输出域宽度内填充字符 c
setprecison(n)    设显示小数精度为 n 位
setw(n)    设域宽为 n 个字符
setiosflags(ios::fixed)    固定的浮点显示
setiosflags(ios::scientific)    指数显示
setiosflags(ios::left)    左对齐
setiosflags(ios::right)    右对齐
setiosflags(ios::skipws)    忽略前导空白
setiosflags(ios::uppercase)    十六进制数大写输出
setiosflags(ios::lowercase)    十六进制数小写输出
setiosflags(ios::showbase)    当按十六进制输出数据时,前面显示前导符 0x;
当按八进制输出数据时,前面显示前导符 0
endl    输入一个换行符并刷新流
1.2 cout 成员函数
函数声明    功能
ostream&    put( char ) 输出一个字符
ostream&write(char*,int n)    输出字符串
ostream& operator<<(T v)    "万能"输出
#include <iostream>
#include <fstream>
using namespace std;
int main() {
    cout.put('a');
    cout.write("abcd", 2) << endl;
    cout << 'a' << "abcd" << endl;
    return 0;
}
1
2
3
4
5
6
7
8
9
2. ios::cin
2.1 函数声明
cin 函数(get系列)
int get();
istream& get (char& c);
istream& get (char* s, streamsize n); //终止符为’\n’
istream& get (char* s, streamsize n, char delim);
#include <iostream>
using namespace std;
int main() {
    char ch;
    while((ch = cin.get()) != EOF) {
        cout << ch << endl;
    }
    while(cin.get(ch)) {
        cout << ch << endl;
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
using namespace std;
int main() {
    char ch;
    char buf[10];
    while(cin.get(buf, 10)) {
        cout << buf << endl;
    }
    cout << "\n cin.eof() : " << cin.eof()
         << "\n cin.fail(): " << cin.fail()
         << "\n cin.bad() : " << cin.bad()
         << "\n cin.good(): " << cin.good() << endl;
    return 0;
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
函数声明(getline)
istream& getline (char* s, streamsize n );
istream& getline (char* s, streamsize n, char delim );
#include <iostream>
using namespace std;
int main() {
    char buf[10];
    while(cin.getline(buf, 10)) {
        cout << buf << endl;
    }
    cout << "\ncin.eof() : " << cin.eof()
         << "\ncin.fail(): " << cin.fail()
         << "\ncin.bad() : " << cin.bad()
         << "\ncin.good(): " << cin.good() << endl;
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
其他函数
istream& ignore (streamsize n = 1, int delim = EOF);
跳过流中的 n 个字符,或遇到终止字符为止(包含),默认参数忽略一个字符
int peek();
窥视当前指针,文件指针未发生移动
istream& putback (char c) ;
回推插入当前指针位置
#include <iostream>
using namespace std;
int main() {
    char ch[20];
    cin.get(ch, 20, '/'); // i like c/ i like C++ also/
    cout << "the first part is :" << ch << endl;
    cin.ignore(10, 'i');
    cin.putback('i');
    char peek = cin.peek();
    cout << "peek is :" << peek << endl;
    cin.get(ch, 20, '/');
    cout << "this second part is:" << ch << endl;
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2.2 状态位操作函数
状态位操作函数    函 数 功 能
eof()    如果读文件到达文件末尾,返回 true
bad()    如果在读写过程中出错,返回 true
例如:当我们要对一个不是打开为写状态的文件进行写入时,或者我们要写入的设备没有剩余空间的时候
fail()    除了与 bad() 同样的情况下会返回 true 以外,
加上格式错误时也返回 true,
例如当想要读入一个整数,而获得了一个字母的时候。或是遇到 eof
good()    这是最通用的:如果调用以上任何一个函数返回 true 的话,此函数返回 false
clear()    标识位一旦被置位,这些标志将不会被改变,
要想重置以上成员函数所检查的状态标志,你可以使用成员函数 clear(),没有参数。
比如:通过函数移动文件指针,并不会使 eofbit 自动重置
#include <iostream>
using namespace std;

int main() {
    int val;
    cout << "Before a bad input operation:"
         << "\n cin.eof() : " << cin.eof()
         << "\n cin.fail(): " << cin.fail()
         << "\n cin.bad() : " << cin.bad()
         << "\n cin.good(): " << cin.good() << endl;
    cin >> val; // control + D/Z or 'a'
    cout << "After a bad input operation:"
         << "\n cin.eof() : " << cin.eof()
         << "\n cin.fail(): " << cin.fail()
         << "\n cin.bad() : " << cin.bad()
         << "\n cin.good(): " << cin.good() << endl;
    cin.clear();
    cout << "\n cin.eof() : " << cin.eof()
         << "\n cin.fail(): " << cin.fail()
         << "\n cin.bad() : " << cin.bad()
         << "\n cin.good(): " << cin.good() << endl;

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
标读位    意义    good()    eof()    fail()    bad()
goodbit    No errors    true    false    false    false
eofbit    End-of-File reached on input operation    false    true    true    false
failbit    Logical error on i/o operation    false    false    true    false
badbit    Read/writing error on i/o operation    false    false    true    true
#include <iostream>
using namespace std;
int main() {
    char ch;
    while(cin.get(ch), !cin.eof()) {
        cout << ch << endl;
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
四、C++文件操作
1. 文件打开方式分类
文件打开方式    值    含 义
ios::in    0x01    以输入(读)方式打开文件,若文件不存在则报错
ios::out    0x02    以输出(写)方式打开文件, 若文件不存则创建
ios::app    0x08    打开一个文件使新的内容始终添加在文件的末尾,
若文件不存在,则创建
ios::trunc    0x10    若文件存在,则清除文件所有内容;若文件不存在,则创建新文件
ios::binary    0x80    以二进制方式打开文件,缺省时以文本方式打开文件
ios::nocreate    0x20    打开一个已有文件,若该文件不存在,则打开失败
ios::noreplace    0x40    若打开的文件已经存在,则打开失败
对于 ifstream 流, 默认值为 ios::in
对于 ofstream 流,默认值为 ios::out|ios::trunc
对于 fstream 流, 默认值为 ios::int|ios::out|ios::app
2. 读写文本文件
读接口
operator >>
int get();
istream& get(int); |
istream& get(char*,int n, char deli ); |
istream& getline(char * ,int n); |
写接口
operator <<
osream& put(int);
2.1 读文本文件的一字 / 行
#include <iostream>
#include <fstream>
using namespace std;
int main() {
    fstream ifs("src.txt", ios::in);
    if(!ifs) {
        cout << "open error" << endl;
        return -1;
    }
    fstream ofs("dest.txt", ios::out | ios::trunc);
    if(!ofs) {
        cout << "open error" << endl;
        return -1;
    }
    // int data;
    // while(ifs>>data,!ifs.eof()) // 只能以 空格 table 回车 作为标志
    // {
    // cout<<"x"<<endl;
    // ofs<<data<<" ";
    // }
    // char ch;
    // while(ifs.get(ch),!ifs.eof())
    // {
    // ofs.put(ch);
    // }
    // ifs.close();
    // ofs.close();
    char buf[1024];
    // ifs>>noskipws; //是否跳过空格
    while(ifs.get(buf, 1024, '\n')) {
        while(ifs.peek() == '\n')
            ifs.ignore();
        ofs << buf << endl;
    }
    ifs.close();
    ofs.close();
    return 0;
}
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
相关博客:使用ifstream和getline读取文件内容[c++]

2.2 快速读取 txt 文档的行数
#include <sys/stat.h>
#include <iostream>

/**
 * [getTxtLineCount description] 获取文件行数
 * @param  file_name [description] 文件路径
 * @return           [description] txt 文件行数
 */
int getTxtLineCount(std::string file_name) {
    int line_count = 0; ///记录文件中行的数量
    struct stat s;
    stat(file_name.c_str(), &s);
    ///获取指定文本的行数
    std::string file_buf(s.st_size + 1, '\0');
    ///将文件中的数据一次性读出来
    FILE *fp = fopen(file_name.c_str(), "rb");
    fread(&file_buf[0], sizeof(char), file_buf.size(), fp);
    const char *file_buf_tmp = file_buf.c_str(); ///获取文件内容指针
    while (*file_buf_tmp != '\0') {
        ///查找第一个换行
        const char *p = strchr(file_buf_tmp, '\n');
        if (p == NULL) {
            ///最后一行没有'\n'
            ++line_count;
            break;
        }
        ///过滤空行
        line_count += p - file_buf_tmp > 0;
        ///查找下一个'\n'
        file_buf_tmp += p - file_buf_tmp + 1;
    }
    return line_count;
}

int main() {

    std::cout << getTxtLineCount("E:/123.txt") << std::endl;

    return 0;
}
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
2.3 一次性将 txt 所有内容读到 std::string
#include <fstream>
#include <iostream>
#include <string>

/**
 * [getAllContent description] 一次性读取txt全部内容
 * @param file_name [description] 文件路径
 * @param resstr    [description] 读取的内容保存到
 */
void getAllContent(const std::string &file_name, std::string &resstr) {
    std::ifstream ifs(file_name.c_str());
    std::istreambuf_iterator<char> begin(ifs);
    std::istreambuf_iterator<char> end;
    std::string str(begin, end);
    resstr = str;
    ifs.close();
}

int main() {
    std::string path("E:/123.txt");
    std::string result;
    getAllContent(path, result);
    std::cout << result << std::endl;
    return 0;
}
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
2.4 读取坐标数据
#include <fstream>
#include <iostream>
#include <string>
#include <iomanip>

/**
 * [getCoor description] 读取二维坐标数据
 * @param path [description] 文件路径
 */
void getCoor(const std::string &path) {
    std::ifstream ifs(path.c_str());
    if(!ifs)
        return;

    while(!ifs.eof()) {
        float x, y;
        ifs >> x >> y;  // 只能以 空格 table 作为分割标记, ',' 不行
        std::cout << std::setprecision(7) << x << " " << y << std::endl;
        if(ifs.peek() == '\n') { // 防止文件没有以 '\n' 结尾时发生少读一行的情况
            ifs.ignore();
            if(ifs.peek() == '\n')
                break;
        }
    }
    ifs.close();
}

int main() {
    std::string path("E:/123.txt");
    getCoor(path);
    return 0;
}
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
2.5 其他读写
2.5.1 读 CSV 文件
#include <fstream>
#include <iostream>
#include <string>
#include <string.h>

/**
 * [readCSV description] 读取 CSV 文件
 * @param path [description] 文件路径
 */
void readCSV(const std::string &path) {
    FILE *fp = NULL;
    char *line, *record;
    char buffer[1024];
    if ((fp = fopen("Student.csv", "at+")) != NULL) {
        fseek(fp, 170L, SEEK_SET);  //定位到第二行,每个英文字符大小为1
        char delims[] = ",";
        char *result = NULL;
        int j = 0;
        while ((line = fgets(buffer, sizeof(buffer), fp)) != NULL) { //当没有读取到文件末尾时循环继续
            record = strtok(line, ",");
            while (record != NULL) { //读取每一行的数据
                if (strcmp(record, "Ps:") == 0)//当读取到Ps那一行时,不再继续读取
                    return;
                printf("%s ", record);//将读取到的每一个数据打印出来
                if (j == 10)  //只需读取前9列
                    break;
                record = strtok(NULL, ",");
                j++;
            }
            printf("\n");
            j = 0;
        }
        fclose(fp);
        fp = NULL;
    }
}

int main() {

    return 0;
}
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
2.5.2 写 CSV 文件
#include <fstream>
#include <iostream>
#include <string>

/**
 * [writeCSV description] 往 CSV 写数据
 * @param path [description] 文件路径
 */
void writeCSV(const std::string &path) {
    float x, y;
    std::ofstream ofs(path.c_str());
    ofs << x << "," << y << "\n";
    ofs.close();
}

int main() {

    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2.6 标记位
2.6.1 与文件指针相关的函数
成员函数    作用
tellg();    返回当前指针位置 //输入流操作
seekg(绝对位置);    绝对移动
seekg(相对位置,参照位置);    相对操作
seekp(绝对位置);    绝对移动, //输出流操作
seekp(相对位置,参照位置);    相对操作
tellp();    返回当前指针位置
2.6.2 参照位置
成员    意义
ios::beg = 0    相对于文件头
ios::cur = 1    相对于当前位置
ios::end = 2    相对于文件尾
infile.seekg(100); //输入文件中的指针向前移到 100个字节的位置
infile.seekg(-50, ios::cur); //输入文件中的指针从当前位置后移 50 个字节
outfile.seekp(-75, iso::end); //输出文件中指针从文件尾后移 75 个字节
1
2
3
3. 读写二进制文件
ostream & write(const char*buf, int len);;
istream & read(char * buff, int len)
#include <iostream>
#include <fstream>
using namespace std;

struct Student {
    char name[100];
    int num;
    int age;
    char sex;
};

int main() {
    // Student s[3] = {
    // {"li",1001,18,'f'},
    // {"Fun",1002,19,'m'},
    // {"Wang",1004,17,'f'}
    // };
    // ofstream
    ofs("student.data", ios::out | ios::trunc | ios::binary);
    // if(!ofs){
    // cout<<"open error"<<endl;
    // }
    // for(int i=0; i<3; i++)
    // {
    // ofs.write((char*)&s[i],sizeof(s[i]));
    // }
    // ofs.close();
    Student s;
    ifstream ifs("student.data", ios::in | ios::binary);
    if(!ifs)
        cout << "open error" << endl;
    ifs.seekg(sizeof(s), ios::beg);

    while(ifs.read((char *)&s, sizeof(Student)), !ifs.eof()) {
        cout << "Name " << s.name << endl;
        cout << "Num " << s.num << endl;
        cout << "Age " << s.age << endl;
        cout << "Sex " << s.sex << endl;
        cout << "---------------" << endl;
    }
    ifs.close();
    return 0;
}
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
五、C++字符串操作
1. string 转化为 int、float、long、double
#include <iostream>
#include <sstream>    //使用stringstream需要引入这个头文件  
using namespace std;

//模板函数:将string类型变量转换为常用的数值类型(此方法具有普遍适用性)
template <class Type>
Type stringToNum(const string &str) {
    istringstream iss(str);
    Type num;
    iss >> num;
    return num;
}
1
2
3
4
5
6
7
8
9
10
11
12
2. atoi()、atof()、atol()、itoa()、sprintf()
#include <stdlib.h>
#include <stdio.h>  //sprintf

int main(){
    const char *p= "12345";
    //把字符串转换成整型,直至遇到第一个空格
    printf("atoi(p) = %d\n", atoi(p));
    //把字符串转换成长整型,直至遇到第一个空格
    printf("atol(p) = %d\n", atol(p));
    //把字符串转换成浮点数型,直至遇到第一个空格
    printf("atof(p) = %15.4f\n", atof(p));

    int num = 1000;
    char q[6];
    //char* itoa(int value,char* string,int radix);
    //将value所代表的整数转换为字符串
    //其中,value是要转换的整数值,string是存储转换后值的字符数组,radix代表进制
    printf("itoa(num,q,2) = %s\n",itoa(num,q,2));
    //int atoi(const char *nptr);
    //把字符串转换成整型数
    //如果第一个非空格字符不存在或者不是数字也不是正负号则返回零,
    //否则开始做类型转换,之后检测到非数字或结束符 \0 时停止转换,返回整型数
    printf("atoi(\"123a456\") = %d\n",atoi("123a456"));

    //int sprintf(string format, mixed [args]...)
    //字符串格式化函数
    char s[20];
    sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"
    printf("sprintf() = %s\n", s);

    return 0;
}
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
3. 格式控制符
格式    说明
%d    用来输出十进制整数,按整型数据的实际长度输出
%md    m为指定的输出字段的宽度
如果数据的位数小于m,则左端补以空格
若大于m,则按实际位数输出
%ld    输出长整型数据
%o    以无符号八进制形式输出整数。对长整型可以用"%lo"格式输出
同样也可以指定字段宽度用“%mo”格式输出
%x    以无符号十六进制形式输出整数
对长整型可以用"%lx"格式输出
同样也可以指定字段宽度用"%mx"格式输出
%u    以无符号十进制形式输出整数
对长整型可以用"%lu"格式输出
同样也可以指定字段宽度用“%mu”格式输出
%c    输出一个字符
%s    用来输出一个串
%ms    输出的字符串占m列,如字符串本身长度大于m,将字符串全部输出
若串长小于m,则左补空格
%-ms    如果串长小于m,则在m列范围内,字符串向左靠,右补空格
%m.ns    输出占m列,但只取字符串中左端n个字符。
这n个字符输出在m列的右侧,左补空格
%-m.ns    其中m、n含义同上,n个字符输出在m列范围的左侧,右补空格
如果n>m,则自动取n值,即保证n个字符正常输出
%e    数字部分(又称尾数)输出6位小数,指数部分占5位或4位
%m.ne
%-m.ne    m、n和”-”字符含义与前相同
此处n指数据的数字部分的小数位数,m表示整个输出数据所占的宽度
%g    自动选f格式或e格式中较短的一种输出,且不输出无意义的零
%*    printf("%*s",5,“123”); // ##123 ,其中 # 代表空格
%*.*s    printf("%*.*s\n", 25, 8, “Hello world!”); 
//#################Hello#wo ,其中 # 代表空格
4. 万能格式转换
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
#include <typeinfo>

using namespace std;

template<typename in_type, typename out_type>
out_type convert(const in_type &t) {
    stringstream stream;
    stream << t;
    out_type result;
    stream >> result;
    return result;
}

int main(int argc, char *argv[]) {

    double d = 123456;
    string s;
    s = convert<double, string>(d);
    std::cout << typeid(s).name() << std::endl;
    std::cout << d << std::endl;

    return 0;
}
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
5. 万能四舍五入
#include <math.h>
#include <stdio.h>
#include <iostream>

using namespace std;

double Round(double dVal, short iPlaces) {
    double dRetval;
    double dMod = 0.0000001;
    if (dVal < 0.0) dMod = -0.0000001;
    dRetval = dVal;
    dRetval += (5.0 / pow(10.0, iPlaces + 1.0));
    dRetval *= pow(10.0, iPlaces);
    dRetval = floor(dRetval + dMod);
    dRetval /= pow(10.0, iPlaces);
    return(dRetval);
}

int main(int argc, char *argv[]) {

    cout << Round(1.234,2) << endl;  // 1.23
    cout << Round(1.234,0) << endl;  // 1
    cout << Round(123.4,-1) << endl; // 120

    return 0;
}
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
6. 获取某一路径下所有文件、文件夹的绝对路径
#include <string>
#include <vector>
#include <io.h>
#include <iostream>

void getFileAbsolutePath(std::string path, std::vector<std::string> &file_abs_path, std::vector<std::string> &file_name ) {

    long hFile = 0;  //文件句柄
    struct _finddata_t fileinfo;   //自行查看_finddata、_findfirst 和 _findnext
    std::string p;
    if((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1) {
        do {
            //如果是目录,迭代之,如果不是,加入列表
            if((fileinfo.attrib & _A_SUBDIR)) {
                continue;
                if(strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)
                    getFileAbsolutePath( p.assign(path).append("\\").append(fileinfo.name), file_abs_path, file_name);
            } else {
                file_abs_path.push_back(p.assign(path).append("\\").append(fileinfo.name));
                file_name.push_back(fileinfo.name);
            }
        } while(_findnext(hFile, &fileinfo) == 0); _findclose(hFile);
    }
}

int main() {
    string folder = "E:/";  

    vector<string> files;
    getFiles(folder, files);  //files为返回的文件名构成的字符串向量组

    for( int i = 0; i < files.size(); i++ ) { 
        cout << files[i] << endl;
    }

    return 0;
}
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
7. 通过指定模板分割字符串
#include <string>
#include <vector>
#include <iostream>

using namespace std;

/**
 * [splitByPattern description]
 * @param  str [description] 要分割的字符串
 * @param  resVec [description] 存储结果到该变量
 * @param  pattern [description] 分割模板
 */
void splitByPattern(std::string &str, std::vector<std::string> &resVec, const std::string &pattern) {
    resVec.clear();  //清空数据

    if(!str.empty()) {  //去除 首部、尾部 空格
        str.erase(0, str.find_first_not_of(" "));
        str.erase(str.find_last_not_of(" ") + 1);
    }else{
        resVec.push_back(str);
        return;
    }

    std::string strs = str + pattern;  //保证截取最后一段数据被截取下来
    size_t pos = strs.find(pattern);
    size_t size = strs.size();
    while(pos != std::string::npos) {
        std::string x = strs.substr(0, pos);
        resVec.push_back(x);
        strs = strs.substr(pos + 1, size);
        pos = strs.find(pattern);
    }
}


/**
 * [trim description] 去除字符串中的所有空格
 * @param str [description] 输入的字符串
 */
void trim(std::string &str) {
    int index = 0;
    if( !str.empty()) {
        while( (index = str.find(' ', index)) != string::npos) {
            str.erase(index, 1);
        }
    }
}

int main() {

    std::string str("  1 23 456 789   ");
    std::vector<string> vec;
    splitByPattern(str, vec, " ");

    for(int i = 0; i < vec.size() ; ++i)
        std::cout << vec[i] << std::endl;

    return 0;
}
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
8. 替换 string 中的字符
#include<string>
#include<iostream>

/**
 * [replaceSymbol description] 将 string 中的字符替换为另一种字符
 * @param str         [description] 要替换的字符串
 * @param old_pattern [description] 要替换的字符
 * @param new_pattern [description] 要替换成的字符
 */
void replaceSymbol(std::string &str, const std::string &old_pattern, const std::string &new_pattern) {
    std::string::size_type pos(0);
    std::string::size_type old_size(old_pattern.size());
    std::string::size_type new_size(new_pattern.size());
    while ((pos = str.find(old_pattern, pos)) != std::string::npos) {
        str.replace(pos, old_size, new_pattern);
        pos += new_size;
    }
}

int main() {
    std::string s1 = "E:\\123\\456.txt\\";  //E:\123\456.txt
    std::string s2 = "\\";
    std::string s3 = "\\\\";
    replaceSymbol(s1, s2, s3);  //E:\\123\\456.txt
    std::cout << s1 ;
    return 0;
}
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
9. 文件的复制 / 移动
方法一

#include <Windows.h>
#include <stdio.h>

int main() {
    DWORD getlastError;
    if (!CopyFileA("E:/1.txt", "F:/1.txt", false)) {
        printf("ERROR\n");
        getlastError = GetLastError();
        return -1;
    }
    return 0;
}

#if 0
// 成功则返回非0数,失败返回0,并且调用GetLastError()可以获取错误信息.
BOOL WINAPI CopyFile(
    _In_ LPCTSTR lpExistingFileName,  // 一个存在文件的名字
    _In_ LPCTSTR lpNewFileName,  // 新文件的名字
    _In_ BOOL    bFailIfExists  // 如果有同名的文件true则不进行复制,false为覆盖
);
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
方法二

#include <Windows.h>
#include <stdio.h>

int main() {
    //将原图片剪切到制定目录下并重命名
    if(rename("E:/1.txt", "F:/2.txt") != 0)
        printf("fail!\n"); 
    
    return 0;
}
1
2
3
4
5
6
7
8
9
10
方法三

#include <Windows.h>
#include <stdio.h>

int main() {

    //system("move E:/1.txt F:/2.txt");  //文件的移动
    system("copy E:\\3.txt F:\\4.txt");  //文件的复制(这个写成 / 好像不能成功复制,不知道为什么)

    return 0;
}
1
2
3
4
5
6
7
8
9
10
10. 文件的剪切
#include <Windows.h>
#include <stdio.h>

int main() {
    if (!MoveFileA("E:/1.txt", "F:/2.txt")) {
        DWORD getlasterror;
        getlasterror = GetLastError();
        printf("拷贝失败");
        return -1;
    }
    printf("拷贝成功\n");
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
11. std::string 和 LPCWSTR的转换
#include <Windows.h>
#include <string>

//wstring转换成string
std::string WChar2Ansi(LPCWSTR pwszSrc) {
    int nLen = WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, NULL, 0, NULL, NULL);

    if (nLen <= 0) return std::string("");

    char *pszDst = new char[nLen];
    if (NULL == pszDst) return std::string("");

    WideCharToMultiByte(CP_ACP, 0, pwszSrc, -1, pszDst, nLen, NULL, NULL);
    pszDst[nLen - 1] = 0;

    std::string strTemp(pszDst);
    delete[] pszDst;

    return strTemp;
}

//string转换车wstring
std::wstring  StringToWString(const std::string &s) {
    std::wstring wszStr;

    int nLength = MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, NULL, NULL);
    wszStr.resize(nLength);
    LPWSTR lpwszStr = new wchar_t[nLength];
    MultiByteToWideChar(CP_ACP, 0, s.c_str(), -1, lpwszStr, nLength);
    wszStr = lpwszStr;
    delete[] lpwszStr;
    return wszStr;
}

int main() {

    return 0;
}
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
未完待续…

原文:https://blog.csdn.net/qq_34719188/article/details/83341176 
 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值