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

一、需要提前了解的


1. 文件分类
  • 计算机的存储在物理上是二进制的,所以文本文件与二进制文件的区别并不是物理上的,而是逻辑上的。这两者只是在编码层次上有差异。简单来说,文本文件是基于字符编码的文件,常见的编码有 ASCII 编码,二进制文件是基于值编码的文件
  • 文本文件:以 ASCII 码格式存放,一个字节存放一个字符。 文本文件的每一个字节存放一个 ASCII 码,代表一个字符。这便于对字符的逐个处理,但占用存储空间较多,而且要花费转换时间。
  • 二进制文件:以值(补码)编码格式存放。二进制文件是把数据以二进制数的格式存放在文件中的,其占用存储空间较少。 数据按其内存中的存储形式原样存放
2. 优缺点
文件类型优点缺点
文本文件直观,方便记忆存储量大,转换为二进制速度慢
二进制文件存储量小,无需转换一个字节不对应一个字符,故不能直接输出其字符形式
3. 实际举例

short a=10000;

存储位置表现形式
内存中00100111 00010000
ASCII00110001 00110000 00110000 00110000 00110000
二进制00100111 00010000

注意:‘0’ 的ASCII在十进制下是48,二进制下是00110000

char a[] = “abcde”;

存储位置表现形式
内存中01100001 01100010 01100011 01100100 01100101
ASCII01100001 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()
goodbitNo errorstruefalsefalsefalse
eofbitEnd-of-File reached on input operationfalsetruetruefalse
failbitLogical error on i/o operationfalsefalsetruefalse
badbitRead/writing error on i/o operationfalsefalsetruetrue
#include <iostream>
using namespace std;
int main() {
	char ch;
	while(cin.get(ch), !cin.eof()) {
		cout << ch << endl;
	}
	return 0;
}

四、C++文件操作


1. 文件打开方式分类
文件打开方式含 义
ios::in0x01以输入(读)方式打开文件,若文件不存在则报错
ios::out0x02以输出(写)方式打开文件, 若文件不存则创建
ios::app0x08打开一个文件使新的内容始终添加在文件的末尾,
若文件不存在,则创建
ios::trunc0x10若文件存在,则清除文件所有内容;若文件不存在,则创建新文件
ios::binary0x80以二进制方式打开文件,缺省时以文本方式打开文件
ios::nocreate0x20打开一个已有文件,若该文件不存在,则打开失败
ios::noreplace0x40若打开的文件已经存在,则打开失败
  • 对于 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;
}

相关博客:使用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;
}
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用来输出十进制整数,按整型数据的实际长度输出
%mdm为指定的输出字段的宽度
如果数据的位数小于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 ,其中 # 代表空格
%*.*sprintf("%*.*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;
}

未完持续…

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值