一、需要提前了解的
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;
}
三、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;
}
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;
}
#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;
}
函数声明(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;
}
其他函数 |
---|
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;
}
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;
}
标读位 | 意义 | 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;
}
四、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;
}
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;
}
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;
}
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;
}
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;
}
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;
}
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 个字节
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;
}
五、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;
}
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;
}
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;
}
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;
}
6. 获取某一路径下所有文件、文件夹的绝对路径
#include <string>
#include <vector>
#include <io.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <cstring>
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()
{
std::string folder = "E:/";
std::vector<std::string> file_abs_path, file_name;
getFileAbsolutePath(folder, file_abs_path, file_name);
for( int i = 0; i < file_abs_path.size(); i++ )
{
std::cout << file_name[i] << std::endl;
}
return 0;
}
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;
}
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;
}
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
方法二
#include <Windows.h>
#include <stdio.h>
int main() {
//将原图片剪切到制定目录下并重命名
if(rename("E:/1.txt", "F:/2.txt") != 0)
printf("fail!\n");
return 0;
}
方法三
#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;
}
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;
}
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;
}
未完持续…