C风格的字符串

#include <iostream>
#include <string>
#include <cstring>
#include <vector>

using namespace std;

/*
 * 如何理解c风格的字符串的定义:
 * 		1) char类型的数组,但最后一个字符必须是'\0'
 * 		2) const char类型的数组,但最后一个字符必须是'\0'
 * 		3) 由字符串字面值str调用c_str()方法后返回的const char类型的数组
 *
 * 而C++标准库中字符串字面值都是const char类型的数组,即C++中的字符串字面值是C风格字符串中的一种
 */
void test_cstring_style(){
	// 非C风格的字符串定义:
	char charArray1[] = {'a', 'b', 'c'}; //都是c字符串,但只是不以'\0'结尾

	// C风格的字符窜定义:
	char cstring_1[] = {'a', 'b', 'c', '\0'};
	char cstring_2[] = "abc";
	const char *p_cstring_3 = "abc";

	// 循环C风格的字符串:
	//	如果 p_cstring_3是非C风格的字符串,即不是以NULL结尾的,则 所指向的字符数组没有 null 结束符,则
	//	此循环将会失败。这时,循环会从 p_cstring_3 指向的位置开始读数,直到遇到内存中某处 null 结束符为止
	while( *p_cstring_3 ){ // 相当于*p_cstring_3 != NULL
		cout << *p_cstring_3;
		++p_cstring_3;
	}
	/*
	编译失败:不能使用string对象来初始化字符指针
	string s("aa");
	char *p = s;
	但可以使用:char *p = s.c_str()来完成,但如果 c_str 返回的指针指向 const char 类型的数组,则这种
	初始化方式失败,这样做是为了避免修改该数组。正确的初始化应为:
	const char *p = s.c_str(); // ok

	因为对于返回的p类型,在以后的操作中有可能会改变p指向的值,所以应该对p进行复制一份。
	*/
}

void test_string_compare(){
	// 1、C++采用关系操作符比较两个字符串的大小
	string str1("abe");
	string str2("abe");
	if( str1 > str2 ){
		cout << str1 << "大于" << str2 << endl;;
	} else if ( str1 < str2 ){
		cout << str1 << "小于" << str2 << endl;;
	} else {
		cout << str1 << "等于" << str2 << endl;;
	}

	// 2、C中则不是:
	const char *c_str1 = str1.c_str();
	const char *c_str2 = str2.c_str();

	if( c_str1 > c_str2 ){
		// 如果 c_str1 和 c_str2 指向同一数组中的元素(或该数组的溢出位置),上述表达式等效于比较在 c_str1 和 c_str2
		// 中存放的地址;如果这两个指针指向不同的数组,则该表达式实现的比较没有定义
	}
	// C的字符串的比较和比较结果的解释都须使用标准库函数 strcmp 进行:
	int flag = strcmp(c_str1, c_str2);
	if( flag > 0 ){
		cout << "大于" << endl;
	} else if ( flag < 0 ){
		cout << "小于" << endl;
	} else {
		cout << "等于" << endl;
	}
}


void test_cstring_2(){
	// 1、C风格的字符串处理
	// 尽量避免使用 C 风格字符串
	const char *pCharArray = "a very long literal string";
	const unsigned size = strlen(pCharArray) + 1;	// 标准库函数 strlen 用于计算 C 风格字符串中的字符个数,不包括 null 结束符
	for( unsigned int index = 0; index != 1000000; ++index ){
		//在复制【strcpy、strncpy】和串连【strcat、strncat】字符串时,一定要时刻记住算上结束符 null。在
		//定义字符串时要切记预留存放 null 字符的空间,因为每次调用标准库函数后都
		//必须以此结束字符串
		char *test = new char[size+1];
		strcpy(test, pCharArray);
		delete [] test;
	}


	// 2、C++风格的字符串处理
	// 使用 string 类型的版本更短、更容易理解,而且出错的可能性更小
	string str("a very long literal string");
	for( unsigned int index = 0; index != 1000000; ++index ){
		string str2 = str;
	}
	// 自动释放内存
	// 使用C风格的字符串的程序需要自己管理内存的分配和释放,而使用string类型的程序由系统自动进行内存的分配和释放
	// 因此比使用C风格字符串的程序要简短,执行速度也要快一些。
}

void test_cstring_NULL(){

	// 在使用处理 C 风格字符串的标准库函数时,牢记字符串必须以结束符 null结束
	// arr1 是一个没有 null 结束符的字符数组,则计算的结果不可预料。
	char arr1[] = {'c', '+', '+'};
	cout << strlen(arr1) << endl;	// 6

	// 正确结果:
	char arr2[] = {'c', '+', '+', '\0'};
	cout << strlen(arr2) << endl;	// 3
}

void test_cstring_print(){

	// 非C风格的字符串:
	// 非C风格的字符串打印的结果是不确定的,因为没有NULL作为字符串的结尾标志
	char arr1[] = {'c', '+', '+'};
	cout << arr1 << endl;					// c++?@

	// C风格的字符串1
	char arr2[] = {'c', '+', '+', '\0'};
	cout << arr2 << endl;					// c++

	// C风格的字符串2
	const char arr3[] = {'c', '+', '+', '\0'};
	cout << arr3 << endl;					// c++

	// C风格的字符串3
	string str("c++");
	cout << str.c_str() << endl;			// c++

	// ------------------- 动态的字符数组:
	char *p1 = arr1;
	cout << p1 << endl;						// c++?@
	cout << *p1 << endl;					// c

	const char *p2 = arr2;
	cout << p2 << endl;						// c++
	cout << *p2 << endl;					// c

	// ---------------------
	int *pInt = new int[5]();
	cout << pInt << endl;					// 0x592588
	cout << *pInt << endl;					// 0

	// 总结:打印字符数组,会把字符串打印出来,而打印非字符数组则会把内存地址打印出来

}

/*
编写程序连接两个C 风格字符串字面值,把结果存储在一
个C 风格字符串中。然后再编写程序连接两个 string 类
型字符串,这两个 string 类型字符串与前面的C 风格字
符串字面值具有相同的内容
*/
void test_4_3_0(){

	// ------------------ C风格
	char c_arr1[] = {'n', 'e', 'w', '\0'};
	char c_arr2[] = {'w', 'o', 'r', 'l', 'd', '\0'};
	unsigned int size = strlen(c_arr1) + strlen(c_arr2) + 1;

	// 如果是new的方式,即char *c_result = new char[size],则需要手动释放内存,否则程序会自动释放
	char c_result[size];
	strncpy(c_result, c_arr1, strlen(c_arr1)+1);	// 第一次是复制
	strncat(c_result, c_arr2, strlen(c_arr2)+1);	// 第二次是连接
	cout << c_result << endl;

	// ------------------ string类型
	string str1 = "new";
	string str2 = "world";

	string str_result = str1;
	str_result += str2;

	cout << str_result << endl;
}

// 使用数组初始化vector
// 必须指出用于初始化式的第一个元素以及数组最后一个元素的下一位置的地址
void test_usingArrayInitVector(){

	int intArr[] = {1,2,3,4,5};
	vector<int> vec1(intArr, intArr+5);
	for( vector<int>::iterator ite = vec1.begin(); ite != vec1.end(); ite++ ){
		cout << *ite << endl; //12345
	}

	vector<int> vec2(intArr+1, intArr+4);
	for( vector<int>::iterator ite = vec2.begin(); ite != vec2.end(); ite++ ){
		cout << *ite << endl; //234
	}
}

void test_4_3_1(){

	cout << "请随便输入一个字符串:";
	string str;
	getline(cin, str);

	if( str.empty() ){
		cout << "长度为0!" << endl;
		return;
	}
	const char *p = str.c_str();

	for( const char *pBegin = p, *pEnd = p + str.size(); pBegin != pEnd; pBegin++ ){
		cout << *pBegin << endl;
	}
}


void test_4_3_2(){
	const unsigned int size = 5;
	int arr[size] = {1,2,3,4,5};

	int *pBegin = arr;
	int *pEnd	= arr + size;

	vector<int> vec(pBegin, pEnd-1);

	for( vector<int>::iterator ite = vec.begin(); ite != vec.end(); ite++ ){
		cout << *ite << "_";	// 1_2_3_4_
	}
	cout << endl;
}

void test_4_3_3(){
	vector<int> vec;
	for( int i = 0; i != 5; i++ ){
		vec.push_back(i+10);
	}

	int *pArray = new int[vec.size()];
	int *pos = pArray;
	for( vector<int>::iterator ite = vec.begin(); ite != vec.end(); ite++ ){
		*pos = *ite;
		pos++;
	}

	for( int *pBegin = pArray, *pEnd = pArray + vec.size(); pBegin != pEnd; pBegin++ ){
		cout << *pBegin <<  "_";	//10_11_12_13_14_
	}
	cout << endl;

	delete [] pArray;
}


void test_4_3_4(){
	vector<string> vec;
	string flag = "0";
	string temp;
	while( true ){
		cout << "请输入一个字符串:";
		cin >> temp;
		if( temp.empty() ){
			continue;
		}
		if( temp == flag ){
			break;
		}
		vec.push_back(temp);
	}

	// 创建字符指针数组
	char **parr = new char*[vec.size()];
	unsigned int index = 0;
	cout << "您所输入的有效字符串是:";
	for( vector<string>::iterator ite = vec.begin(); ite != vec.end(); ite++ ){
		cout << *ite << " ";
		char *p = new char[(*ite).size()+1];
		// 与 vector 不同,一个数组不能用另外一个数组初始化,也不能将一个数组
		// 赋值给另一个数组,这些操作都是非法的,所以在这里只能用C标准库的strcpy复制函数
		strcpy(p, (*ite).c_str());
		parr[index] = p;
		index++;	// index记得要递增
	}
	cout << endl;

	// 输出字符数组的内容:
	for( unsigned int i = 0; i != vec.size(); i++ ){
		cout << parr[i] << " ";
	}

	// 释放每一个一维数组的内存:
	for( unsigned int i = 0; i != vec.size(); i++ ){
		delete [] parr[i];
	}
}

// 转换成大写的string的方法
string toUpperCase( string &str ){
	for( string::iterator it = str.begin(); it != str.end(); it++ ){
		if( (!isspace(*it)) && islower(*it) ){
			*it = toupper(*it);
		}
	}
	return str;
}



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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值