精华内容
下载资源
问答
  • c++字符串与c字符串

    万次阅读 多人点赞 2019-05-27 19:32:26
    字符串字面量3.C++ std::string 3.1 C风格字符串的优势和劣势3.2 使用string3.2.1 std::string 字面量3.2.2 c++字符串的数值转换(1)字符串转数值(2)数值转字符串3.2.3 常用字符串函数3.2.4 原始字符串字面量 ...


    你编写的每个应用程序都会使用某种类型的字符串。使用老式C语言时,没有太多的选择,只
    能使用普通的以null结尾的字符数组来表示字符串。遗憾的是,这种表示方式会导致很多问题,例 如会导致安全攻击的缓冲区溢出。C++ STL包含了一个安全易用的std::string类,这个类没有这些 缺点。

    1. C风格的字符串

    在C语言中,字符串表示为字符的数组。字符串中的最后一个字符是空字符(\0’)
    C++包含一些来自C语言的字符串操作函数,它们在< cstring >头文件中定义。

    函数名称说明
    strlen()返回字符串长度,不包含空字符‘\0’的一字节,字符串长度不等于字符个数
    strcpy()字符串拷贝

    C和C++中的sizeof操作符可用于获得给定数据类型或变量的大小。例如,sizeof(char)返回1,
    因为char的大小是1字节。但是,在C风格的字符串中,sizeof()和strlen()是不同的。绝对不要通过 sizeof()获得字符串的大小。如果C风格的字符串存储为char[],则sizeof()返回字符串使用的实际内存,包括‘\0’字符。例如:

    char text[]= "abcdef";
    size_t s1= sizeof(text); // is 7
    size_t s2 = strlen(text); // is 6
    

    但是,如果C风格的字符串存储为char*, sizeof()就返回指针的大小!例如:

    const char* text2 = "abcdef";
    size_t s3 = sizeof(text2); // is platform-dependent
    size_t s4 = strlen(text2); // is 6
    

    在32位模式编译时,s3的值为4,而在64位编译时,s3的值为8,因为这返回的是指针const char*
    的大小。可在<cstring>头文件中找到操作字符串的C函数的完整列表。

    在Microsoft Visual Studio中使用C风格的字符串函数时,编译器可能会给 出安全相关的警告甚或错误,说明这些函数已经被废弃了。使用其他C标准库函数可以避免这些警告,例如
    strcpy_s()和strcat_s(),这些函数是“安全C库” (ISO/IEC TR 24731)标准的一部分。然而,最好的解决方案是切换到C++的 string 类。

    2. 字符串字面量

    注意,C++程序中编写的字符串要用引号包围。例如,下面的代码输出字符串"hello",这段代码
    包含这个字符串本身,而不是一个包含这个字符串的变量:

    cout <<"hello" << endl;
    

    在上面的代码中,"hello”是一个字符串字面量(string literal),因为这个字符串以值的形式写出,
    而不是一个变量。与字符串字面量关联的真正内存在内存的只读部分中。通过这种方式,编译器可 以重用等价字符串字面量的引用,来优化内存的使用。也就是说,即使一个程序使用了 500次"hello"字符串字面量,编译器也只在内存中创建一个hello实例。这种技术称为字面量池
    (literal pooling)。
    字符串字面量可以赋值给变量,但因为字符串字面量位于内存的只读部分,且使用了字面量池,
    所以这样做会产生风险。C++标准正式指出:字符串字面量的类型为“n个const char的数组”,然而为了向后兼容较老的不支持const的代码,大部分编译器不会强制程序将字符串字面量赋值给 const char类型的变量。这些编译器允许将字符串赋值给不带有const的char,而且整个程序可以 正常运行,除非试图修改字符串。一般情况下,试图修改字符串的行为是没有定义的。它可能会导 致程序崩溃;可能使程序继续执行,看起来没有什么莫名其妙的副作用;可能不加通告地忽略修改 行为;可能修改行为是有效的,这完全取决于编译器。例如,下面的代码展示了未定义的行为:

    char* ptr = "hello"; // Assign the string literal to a variable.
    ptr[1] = 'a ';       // Undefined behavior!
    

    一种更安全的编码方法是在引用字符串常量时,使用指向 const 字符的指针。下面的代码包含
    同样的 bug,但由于这段代码将字符串字面量赋值给 const char* 所以编译器会捕捉到任何写入只 读内存的企图。

    const char* ptr = "hello";  // Assign the string literal to a variable.
    ptr[ 1] = 'a';              // Error! Attempts to write to read-only memory
    

    还可以将字符串字面量用作字符数组(char®的初始值。这种情况下,编译器会创建一个足以放 下这个字符串的数组,然后将字符串复制到这个数组。因此,编译器不会将字面量放在只读的内存中,也不会进行字面量的池操作。

    char arr [] = "hello"; // Compiler takes care of creating appropriate sized 
    					   // character array arr.
    arr[ 1] = 'a ';        // The contents can be modified.
    

    3.C++ std::string 类

    C++提供了一个得到极大改善的字符串概念,并作为标准库的一部分提供了这个字符串的实现。 在C++中,std::string是一个类(实际上是basic string模板类的一个实例),这个类支持
    <cstring >中提 供的许多功能,还能自动管理内存分配。string类在std名称空间的< string >头文件中定义。

    3.1 C风格字符串的优势和劣势

    优势劣势
    很简单,底层使用了基本的字符类型和数组结构为了模拟一等字符串数据类型,需要付出很多努力
    量级轻,如果使用得当,只会占用所需的内存使用难度大,而且很容易产生难以找到的内存bug
    很低级,因此可以按操作原始内存的方式轻松操作和复制字符串没有利用C++的面向对象特性
    能够很好地被C语言程序员理解要求程序员了解底层的表示方式

    3.2 使用string类

    尽管string是一个类,但是几乎总是可以把string当做内建类型使用。事实上,把string想象为
    简单类型更容易发挥string的作用。通过运算符重载的神奇作用,C++的string使用起来比C字符串容易得多。

    3.2.1 std::string 字面量

    源代码中的字符串字面量通常解释为const char*。使用用户定义的标准字面量”s”可以把字符串
    字面量解释为std::string。例如:

    auto stringl = "Hello World"; // stringl will be a const char*
    auto string2 = "Hello World"s; // string2 will be an std::string
    

    3.2.2 c++字符串的数值转换

    数值转字符串字符串转数值
    to_string(int val)int stoi(const string& str, size_t *idx=0, int base=10)
    to_string(unsigned val)long stol(const string& str, size_t *idx=0, int base=10)
    to_string(long val)unsigned long stoul(const string& str, size_t *idx=0, int base=10)
    (1)字符串转数值

    int stoi(const string& str, size_t *idx=0, int base=10)

    stoi将n进制字符串转为十进制,第二个参数是字符串起始位置,第三个参数表示n进制

    也可以直接用重载的 int stoi(const string& str),默认字符串为十进制,起始位置为0,制

    #include<string>
    #include <iostream>
    #include <exception>
    using namespace std;
    int main()
    {
    	int i=0;
    	try
    	{
    		i = stoi("FEEF", 0, 16);
    		//int i = stoi("我的"); 输入非法时,可以捕获异常"invalid stoi argument"
    	}
    	catch (exception e)
    	{
    		cout << e.what() << endl;
    	}
    	system("pause");
    	return 0;
    }
    

    输出结果:
    在这里插入图片描述

    (2)数值转字符串

    转十进制可以用to_string,但是低版本的编译器可能不支持

    转多进制可以用_itoa_s,但似乎没有安全机制,导致无法捕获异常

    	char cstr[20];
    	_itoa_s(100,cstr,2);
    	cout << cstr << endl;
    

    转多进制还可以用 stringstream

    #include<string>
    #include <iostream>
    #include <sstream>
    #include <bitset>
    using namespace std;
    int main()
    {
    
       int num = 1234;
       stringstream stream;
    
       //转二进制
       stream << bitset<16>(num);
       cout << stream.str() <<endl;
       stream.str(""); //清空缓存,如果注释掉,那么会输出所有的历史结果
       //转8进制
       stream << oct << num;
       cout << stream.str() << endl;
       stream.str("");
       //转十六进制
       stream << hex << num;
       cout << stream.str() << endl;
       stream.str("");
       system("pause");
       return 0;
    }
    

    结果:
    在这里插入图片描述

    如果需要把格式化后的字符串通过>>输出到字符串, 必须每次都调用clear()方法

    3.2.3 c++常用字符串函数

    函数功能
    append将字符添加到字符串的末尾
    at返回字符串中的指定位置处的元素的引用
    c_str将字符串的内容转换为 C 样式空终止字符串
    data转换为字符数组的字符串的内容
    empty测试是否该字符串包含的字符
    erase从指定位置字符串中移除元素或某个范围的元素
    find与指定的字符序列匹配的子字符串的第一个匹配项的向前搜索字符串
    find_first_not_of搜索与指定任何的字符串元素相匹配的第一个字符的字符串
    find_first_of搜索与指定任何的字符串元素相匹配的第一个字符的字符串
    rfind向后方向中的首次出现的与指定的字符序列匹配的子字符串搜索字符串
    pop_back清除该字符串的最后一个元素
    push_back该字符串的末尾添加一个元素
    insert将某个元素的数目或某个范围的元素插入到指定位置的字符串
    length返回字符串中的元素的当前数目
    replace替换指定的字符或从其他区域或字符串或 C 字符串复制的字符在字符串中位于指定位置处的元素
    substr从指定位置的字符串开头的复制的子字符串的最大字符数

    3.2.4 原始字符串字面量

    原始字符串字面量(raw string literal)是可以横跨多行代码的字符串字面量,不需要转义嵌入的双引号,像\t和\1!这种转义序列不按照转义序列的方式处理,而是按照普通文本的方式处理。如果像下面这样编写普通的字符串字面量,那么会收到一个编译器错误,因为 字符串包含了未转义的引号:

    string str = "Hello "World"!// Error!
    

    对于普通的字符串,必须转义双引号,如下所示:

    string str = "Hello \"World\"!";
    

    对于原始字符串字面量,就不需要转义引号了。
    原始字符串字面量的写法:

    string str = R"(Hello "World"!)";
    

    原始字符串字面量可以跨越多行代码。例如,如果像下面这样编写普通的字符串字面量,那么会收到一个编译器错误,因为普通的字符串字面量不能跨越多行:

    string str = "Line 1
    Line 2 with \t"; // Error!
    

    可使用如下原始字符串字面量来替代:

    string str = R"(Line 1
    Line 2 with \t)";
    

    这也说明,使用原始字符串字面量时,\t转义字符没有替换为实际的制表符字符,而是按照字面形式保存。将str写入控制台得到的输出如下所示:
    Line 1
    Line 2 with \t
    因为原始字符串字面量以)“结尾,所以使用这个语法时,不能在字符串中嵌入)”。例如,下面的 字符串是不合法的,因为在这个字符串中间包含了一个)”:

    string str = R"(The characters )"n are embedded in this string)" // Error!
    

    如果需要嵌入)",则需要使用扩展的原始字符串字面量语法,如下所示:

    R"d-char-sequence(r-char-sequence)d-char-sequence"
    

    r-char-sequence是实际的原始字符串。d-char-sequence是可选的分隔符序列,原始字符串首尾的分隔符序列应该一致。分隔符序列最多能有16个字符。应选择未出现在原始字符串字面量中的序列作为分隔符序列。上面的例子可以改用唯一的分隔符序列:

    string str = R"-(The characters )" are embedded in this string)-";
    

    在操作数据库查询字符串和正则表达式等字符串时,原始字符串字面量可以令程序的编写更加方便。

    展开全文
  • C++ 字符串 对象 C++ 字符串 对象 创建方法 C++ 字符串 对象 输出到控制台 C++ 字符串 拼接 ...C++ 字符串 方法调用 ( 栈内存对象 ) C++ 字符串 方法调用 ( 堆内存对象 ) C / C++ 字符串 完整代码示例



    C++ 字符串 对象


    C++ 字符串 :

    • 1.string 类 : C++ 中的字符串是 string 类 对象 ;
    • 2.string 类定义位置 : 该 string 类定义在 iostream 头文件中 , 不必引入另外的头文件 ;
    #include <iostream>
    



    C++ 字符串 对象 创建方法


    C++ 字符串 对象 创建方法 :

    • 1.直接赋值 : 直接使用 C 字符串赋值 ;
    	//① 使用字符串赋值
    	string string_c_plus_1 = " Hello ";
    
    • 2.构造方法 : 调用 string 构造方法 创建 string 对象 ;
      • ① 传入 string 参数 : string 构造方法可以传入 string 对象 ;
      • ② 传入 C 字符串参数 : string 构造方法也可以传入 一个 C 字符串 ;
    	//② 调用构造方法 初始化字符串
    	string string_c_plus_2(string_c_plus_1);
    	string string_c_plus_3(" World ");
    
    • 3.使用 new 分配内存 : 使用 new 为 String 对象分配一块堆内存空间 , 返回 string * 类型的指针 ;
    	//③ 使用 new 申请的内存 , 需要使用 delete 释放
    	string *string_c_plus_4 = new string(" New ");
    	delete string_c_plus_4;
    

    调用该 string* 对象的方法需要使用 -> 进行调用 ;

    堆内存使用原则 :
    ① 使用 new 申请的内存 , 需要使用 delete 释放 ;
    ② 使用 new [] 申请的数组 , 需要使用 delete[] 释放 ;
    ③ 使用 malloc 申请的内存 , 需要使用 free 释放 ;




    C++ 字符串 对象 输出到控制台


    C++ 字符串 对象 输出到控制台 :

    • 1.不能直接使用 cout 输出 : 下面的用法是错误的 ; 使用 cout 不能直接将 string 对象输出 ;
    	//这种用法是错误的
    	string string_c_plus_1 = " Hello ";
    	cout << string_c_plus_1 << endl;
    
    • 2.输出方法 : 需要将 string 对象转成 C 字符串 , 然后再输出 :
    	//调用 string 对象的 c_str() 方法 , 获取其 C 字符串 , 然后再输出到控制台
    	string string_c_plus_1 = " Hello ";
    	cout << string_c_plus_2.c_str() << endl;
    

    在 Java 中输出 String 对象 , 默认会调用其 toString 方法 , 但是在 C 中不可以直接使用 ;




    C++ 字符串 拼接


    C++ 字符串拼接 :

    • 1.使用 “+” 符号拼接 : 这里的加号进行了操作符重载 , 字符串之间相加代表了字符串的拼接操作 ;
    	//① "+" : 操作符重载 , 重新定义了 加号运算符的行为 , 
    	//		这里加号可以实现字符串拼接 , 与 Java 类似
    	string string_c_plus_5 = string_c_plus_1 + string_c_plus_3;
    
    • 2.调用 string 对象的 append 方法 : 调用 string 对象的 append() 方法 , 传入要拼接的字符串 ;
    	//② 调用 string 对象的 append 方法 , 拼接字符串
    	string string_c_plus_6 = string_c_plus_1.append( string_c_plus_3 );
    
    • 3.代码示例 :
    	//C++ 字符串拼接
    	//① "+" : 操作符重载 , 重新定义了 加号运算符的行为 , 这里加号可以实现字符串拼接 , 与 Java 类似
    	//② 调用 string 对象的 append 方法 , 拼接字符串
    	string string_c_plus_5 = string_c_plus_1 + string_c_plus_3;
    	string string_c_plus_6 = string_c_plus_1.append( string_c_plus_3 );
    
    • 4.运行结果 :
     Hello  World
     Hello  World
    

    在这里插入图片描述

    操作符重载 : 重新定义了操作符的作用 , 这里的 “+” 就是重新定义了其作用 , 拼接字符串 ;




    C++ 字符串 方法调用 ( 栈内存对象 )


    C++ 字符串 方法调用 : 该字符串 ( string ) 对象 在栈内存中 ;

    • 1.获取字符串长度 : 调用 string 对象的 size() 方法 , 即可返回字符串长度 ;
    	//① 使用字符串赋值
    	string string_c_plus_1 = " Hello ";
    	//获取 C++ 字符串长度 : 调用 string 对象的 size() 方法 , 获取字符串长度
    	int string_c_plus_1_size = string_c_plus_1.size();
    
    • 2.判断字符串是否为空 : 调用 string 对象的 empty() 方法 , 判断字符串是否为空 ;
    	//① 使用字符串赋值
    	string string_c_plus_1 = " Hello ";
    	//判断 C++ 字符串是否为空 : 调用 string 对象的 empty() 方法 ; 
    	bool string_c_plus_1_empty = string_c_plus_1.empty();
    
    • 3.代码示例 :
    	//使用字符串赋值
    	string string_c_plus_1 = " Hello ";
    	
    	//获取 C++ 字符串长度 : 调用 string 对象的 size() 方法 , 获取字符串长度
    	int string_c_plus_1_size = string_c_plus_1.size();
    	cout << "string_c_plus_1_size : " << string_c_plus_1_size << endl;
    
    	//判断 C++ 字符串是否为空 : 调用 string 对象的 empty() 方法 ; 
    	bool string_c_plus_1_empty = string_c_plus_1.empty();
    	cout << "string_c_plus_1_empty : " << string_c_plus_1_empty << endl;
    
    • 4.运行结果 :
    string_c_plus_1_size : 14
    string_c_plus_1_empty : 0
    

    在这里插入图片描述

    使用 “.” 方式调用栈内存对象的方法 ;




    C++ 字符串 方法调用 ( 堆内存对象 )


    C++ 字符串 堆内存对象 方法调用 :

    • 1.堆内存对象创建 : 使用 new 创建的 string 对象 需要在堆内存中为其分配内存 , 返回的是 string* 指针类型 ;
    	//使用 new 创建的对象 , 就不能使用 . 访问其方法和变量 , 需要使用 -> 符号进行访问 
    	// -> 相当于 (*). 运算, 先读取指针内容 , 然后访问其方法或变量
    
    	string* string_c_plus_7 = new string(" New String ");
    
    • 1.获取字符串长度 : 调用 string 对象的 size() 方法 , 即可返回字符串长度 ; 需要使用 -> 代替 . 操作 ;
    	//① 获取字符串长度 : 
    	int string_c_plus_7_size = string_c_plus_7->size();
    
    • 2.判断字符串是否为空 : 调用 string 对象的 empty() 方法 , 判断字符串是否为空 ; 需要使用 -> 代替 . 操作 ;
    	//② 判断字符串是否为空 : 
    	bool string_c_plus_7_empty = string_c_plus_7->empty();
    
    • 3.使用指针的好处 :
      • ① 扩大作用域 : 如果在栈内存中使用 , 有作用域限制 , 出了栈内存 作用域 , 该对象就无效了 ;
      • ② 方便参数传递 : 指针 大小为 4 ( 32 位系统 ) 或 8 ( 64 位系统 ) 个字节 , 其当做参数传递 比直接传递对象 ( 动辄几十上百字节甚至更高 ) 效率更高 ;
    • 4.代码示例 :
    	//使用 new 创建的对象 , 就不能使用 . 访问其方法和变量 , 需要使用 -> 符号进行访问 
    	// -> 相当于 (*). 运算, 先读取指针内容 , 然后访问其方法或变量
    
    	string* string_c_plus_7 = new string(" New String ");
    	
    	//① 获取字符串长度 : 
    	int string_c_plus_7_size = string_c_plus_7->size();
    	cout << "string_c_plus_7 : " << string_c_plus_7_size << endl;
    
    	//② 判断字符串是否为空 : 
    	bool string_c_plus_7_empty = string_c_plus_7->empty();
    	cout << "string_c_plus_7_empty : " << string_c_plus_7_empty << endl;
    
    	//释放堆内存
    	delete string_c_plus_7;
    
    	//使用指针的好处 : 
    	// ① 如果在栈内存中使用 , 有作用域限制 , 出了栈内存 作用域 , 该对象就无效了 ; 
    	// ② 指针 大小为 4 ( 32 位系统 ) 或 8 ( 64 位系统 ) 个字节 , 
    	//	  其当做参数传递 比直接传递对象 ( 动辄几十上百字节甚至更高 ) 效率更高 
    
    • 5.运行结果 :
    string_c_plus_7 : 12
    string_c_plus_7_empty : 0
    

    在这里插入图片描述




    C / C++ 字符串 完整代码示例


    // 001_CMake_1.cpp: 定义应用程序的入口点。
    //
    
    #include "001_CMake_1.h"
    #include "c_extern.h"
    
    using namespace std;
    
    //定义方法接收 int& 引用类型变量
    //并在方法中修改该变量的值
    void quote(int& b) {
    	b = 888;
    }
    
    int main()
    {
    	cout << "Hello CMake。" << endl;
    
    	//1. C C++ 兼容
    	//博客地址 : https://hanshuliang.blog.csdn.net/article/details/98840708
    	//调用 c_extern.h 头文件中定义的方法
    	//该方法定义在了 C 语言文件中
    	add(1, 2);
    
    
    	//2. 引用数据类型
    	//博客地址 : https://hanshuliang.blog.csdn.net/article/details/99239635
    	//代码 展示 流程 : 
    	//① 定义 普通 类型 变量
    	int a = 8;
    	//② 定义 引用类型变量, 格式 : 类型名称& 变量名 = 对应类型变量名称 ;
    	int& b = a;
    	//③ 调用函数传入引用类型参数 : 将引用类型传给接收引用类型的方法
    	quote(b);
    	//④ 打印引用数据类型的修改结果 , 结果是 b 被修改成了 888
    	cout << b << endl;
    
    	//引用数据类型定义与使用 : 
    	// ① 引用数据类型定义 : 类型名称& 变量名 = 对应类型变量名称 ;
    	// ② 引用数据类型的使用方法 : 直接当做原来的变量使用即可, 可以替换原来变量的位置使用
    
    	//引用类型解析 : 
    	// ① int& 是引用数据类型 , b 是 a 的引用 
    	// ② 分配一块内存存放 int 类型数据 8 , 将该内存赋予一个别名 a
    	// ③ 同时又给该内存赋予另外一个别名 b 
    
    
    	//3. 字符串使用
    	//C 字符串 表示方法 : 
    	// ① 字符数组 : 本质是 字符 数组 char[] , 这里注意字符数组要以 NULL 或 '\0' 结尾; 
    	char string_c[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
    	// ② 指针 : 使用指针形式表示字符串 , 默认末尾增加 '\0' ;
    	char* string_c_p = "hello";
    
    	//字符串打印 : 
    	// ① 打印字符串 , cout 后的 << 后可以打印 字符串 , 也可以打印变量
    	// ② 输出 cout << 字符串或变量1 << 字符串或变量2 ... << endl 可以拼接 输出信息
    	cout << "string_c : " << string_c << endl;
    	cout << "string_c_p : " << string_c_p << endl;
    
    	//C 语言中的字符串操作
    	//拷贝字符串 
    	char string_c_copy_destination[6];
    	char string_c_copy_source[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
    	// ① 参数 : strcpy 方法是拷贝字符串的方法 , 第一个参数是目标字符串 , 第二个参数是源字符串
    	// ② 作用 : 该方法是将 源字符串 拷贝到 目标字符串中
    	strcpy(string_c_copy_destination, string_c_copy_source);
    	// ③ 打印拷贝结果 : 
    	cout << "string_c_copy_destination : " << string_c_copy_destination << endl;
    
    	//拼接字符串 
    	//① 定义目标字符串 : 拼接字符串的目标字符串的大小一定要大于等于要拼接的两个字符串大小之和, 否则会报错
    	char string_c_cat_destination[30] = " cat dst ";
    	char string_c_cat_source[] = " cat src ";
    	//② 拼接字符串方法参数 : 第一个参数是目标字符串 , 第二个参数是源字符串
    	//③ 目标字符串大小 : 注意 目标字符串的 大小一定要大于 两个字符串实际大小
    	strcat(string_c_cat_destination, string_c_cat_source);
    	//④ 打印字符串拼接结果 : 
    	cout << "string_c_cat_destination : " << string_c_cat_destination << endl;
    
    
    	//获取字符串长度
    	//① 参数 : 传入要获取的字符串 , 该长度不含 '\0' 结尾标志
    	//② 作用 : 获取实际的字符串长度 , 即自动识别 '\0' 位置 , 获取其长度 , 与所占用的内存大小无关
    	char string_c_len[] = { 'h', 'e', 'l', 'l', 'o', '\0' };
    	char string_c_len2[20] = { 'h', 'e', 'l', 'l', 'o', '\0' };
    	char * string_c_len3 = "hello";
    	
    	//① 字符数组长度 , 测量从开始到 '\0' 的长度, 不包括 '\0'
    	int len1 = strlen(string_c_len);
    	//② 指定大小的字符数组长度 , 结果不是指定的大小的值 , 获取的是实际字符串长度
    	int len2 = strlen(string_c_len2);
    	//③ 指针表示的字符串 , 其获取的大小是实际字符串大小, 不包含自动添加的 '\0' 
    	int len3 = strlen(string_c_len3);
    	//④ 打印 三个字符串大小
    	cout << "len1 : " << len1
    		<< " len2 : " << len2
    		<< " len3 : " << len3
    		<< endl;
    
    
    	//字符串比较
    	// ① 参数说明 : 参数是需要比较的两个字符串 , 第一个参数 str1 , 第二个参数 str2
    	// ② 对比规则 : str1 和 str2 两个字符串 , 从左到右 逐个对比 ASCII 码 大小 ; 
    	//		a. 如果 str1 等于 str2 , 返回 0; 
    	//		b. 如果 str1 > str2 , 返回值 大于 0 ;
    	//		c. 如果 str1 < str2 , 返回值 小于 0 ;
    
    	//定义需要比较的字符串
    	char* string_c_comp_1 = "Hello";
    	char* string_c_comp_2 = "Hello";
    	char* string_c_comp_3 = "hello";
    
    	// ① 两个字符串相等
    	int cmp_result_1_2 = strcmp(string_c_comp_1, string_c_comp_2);
    	// ② "Hello" 字符串 (H 对应 ASCII 72) 小于 "hello" 字符串 (h 对应 ASCII 104) , 返回值 小于 0
    	int cmp_result_1_3 = strcmp(string_c_comp_1, string_c_comp_3);
    	// ③ "hello" 字符串 (h 对应 ASCII 104) 大于 "Hello" 字符串 (H 对应 ASCII 72) , 返回值 大于 0
    	int cmp_result_3_1 = strcmp(string_c_comp_3, string_c_comp_1);
    
    	//输出字符串对比结果
    	cout << "cmp_result_1_2 : " << cmp_result_1_2 
    		<< " cmp_result_1_3 : " << cmp_result_1_3
    		<< " cmp_result_3_1 : " << cmp_result_3_1
    		<< endl;
    
    
    	// C++ string 类 : 该类定义在 iostream 头文件中
    	//创建 string 类型对象有三种方法 : 
    	//① 直接使用字符串赋值 
    	//② 调用构造方法赋值 
    	//③ 最后可以调用 new 为字符串分配一块内存
    
    	//① 使用字符串赋值
    	string string_c_plus_1 = " Hello ";
    
    	//② 调用构造方法 初始化字符串
    	string string_c_plus_2(string_c_plus_1);
    	string string_c_plus_3(" World ");
    
    	//上面的三种字符串不需要释放 , 因为其定义在栈内存中 , 下面使用 new 创建字符串的情况需要 delete 释放内存 ; 
    
    	//③ 使用 new 申请的内存 , 需要使用 delete 释放
    	string *string_c_plus_4 = new string(" New ");
    	delete string_c_plus_4;
    
    	//使用 new [] 申请的数组 , 需要使用 delete[] 释放
    	//使用 malloc 申请的内存 , 需要使用 free 释放
    
    	//C++ 字符串输出
    	//字符串对象不能直接在 cout 中输出, cout << string string_c_plus_5 << endl; 是错误的
    	//cout << string_c_plus_2 << endl;
    	//要将 string 对象打印到控制台上, 需要将其转为 C 字符串 , char* 或 char[] 才能输出
    	cout << string_c_plus_1.c_str() << endl;
    
    
    	//C++ 字符串拼接
    	//① "+" : 操作符重载 , 重新定义了 加号运算符的行为 , 这里加号可以实现字符串拼接 , 与 Java 类似
    	//② 调用 string 对象的 append 方法 , 拼接字符串
    	string string_c_plus_5 = string_c_plus_1 + string_c_plus_3;
    	string string_c_plus_6 = string_c_plus_1.append( string_c_plus_3 );
    
    	//输出拼接的字符串
    	cout << string_c_plus_5.c_str() << endl;
    	cout << string_c_plus_6.c_str() << endl;
    	
    
    
    	//获取 C++ 字符串长度 : 调用 string 对象的 size() 方法 , 获取字符串长度
    	int string_c_plus_1_size = string_c_plus_1.size();
    	cout << "string_c_plus_1_size : " << string_c_plus_1_size << endl;
    
    	//判断 C++ 字符串是否为空 : 调用 string 对象的 empty() 方法 ; 
    	bool string_c_plus_1_empty = string_c_plus_1.empty();
    	cout << "string_c_plus_1_empty : " << string_c_plus_1_empty << endl;
    
    	//使用 new 创建的对象 , 就不能使用 . 访问其方法和变量 , 需要使用 -> 符号进行访问 
    	// -> 相当于 (*). 运算, 先读取指针内容 , 然后访问其方法或变量
    
    	string* string_c_plus_7 = new string(" New String ");
    	
    	//① 获取字符串长度 : 
    	int string_c_plus_7_size = string_c_plus_7->size();
    	cout << "string_c_plus_7 : " << string_c_plus_7_size << endl;
    
    	//② 判断字符串是否为空 : 
    	bool string_c_plus_7_empty = string_c_plus_7->empty();
    	cout << "string_c_plus_7_empty : " << string_c_plus_7_empty << endl;
    
    	//释放堆内存
    	delete string_c_plus_7;
    
    	//使用指针的好处 : 
    	// ① 如果在栈内存中使用 , 有作用域限制 , 出了栈内存 作用域 , 该对象就无效了 ; 
    	// ② 指针 大小为 4 ( 32 位系统 ) 或 8 ( 64 位系统 ) 个字节 , 
    	//	  其当做参数传递 比直接传递对象 ( 动辄几十上百字节甚至更高 ) 效率更高 
    
    
    
    
    
    	return 0;
    }
    

    展开全文
  • Python 通过字符串调用类方法或方法

    千次阅读 2019-04-08 14:22:42
    今天遇到个问题,在一个里面,想要通过字符串调用类里面的方法,即(注意,以下为错误代码演示,只是为了表述问题): class A(object): def a(self): print('xxxxx') def b(self): c= 'a' self.c() ...
    • 问题描述

    今天遇到个问题,在一个类里面,想要通过字符串调用类里面的方法,即(注意,以下为错误代码演示,只是为了表述问题):

    class A(object):
    	def a(self):
    		print('xxxxx')
    
    	def b(self):
    		c= 'a'
    		self.c()
    
    test = A()
    test.b()
    
    

     如上面代码所示,在b函数里面,我将字符 a 赋值给了 c ,然后在后面,想要通过 self.c() 的方式,来替代 self.a(),完成对 a 函数的调用。当然,上面的代码毫无疑问的报错了,那么,怎么才能通过字符串调用类里面的函数呢?

    • 解决方法

    首先,来解决类里面通过字符串来调用函数的问题,其实也很简单,我们需要用到一个稍微高阶一点的Python自带函数: getattr()

    直白的说,这个函数是获取一个实例(也可以说是类)里面的属性或方法。用法为:

    getattr(object, name[, default])

               第一个object参数为: 传入一个实例或者类

               第二个name参数为:  你想要获得的这个类或实例里面的属性或方法的名称

               第三个参数default为: 如果没有在这个类或实例里面找到对应的属性或方法,应该返回什么。

               如果想要详细了解这个内建函数的使用方法,请看:Python getattr() 函数 | 菜鸟教程

               这里举个例子:

    class A(object):
    	def a(self):
    		print('sfsdf')
    
    test = A()
    print(getattr(test, 'a', 'None'))
    print(getattr(test, 'b', 'None'))

     运行结果如下:

     

     从上面的代码,我们可以看到,getattr()函数获得了 test 实例里面的 a 方法,然后将该方法打印了出来,我们还想获取 test 实例的 b 方法, 但是 test 实例并没有 b 方法,所以就返回了我们预先指定的 None。这就是getattr() 函数的用法。说到这里,相信不少童鞋已经知道怎么通过字符串调用类方法了,完整代码如下:

    class A(object):
    	def a(self):
    		print('GodLordGee')
    
    	def b(self):
    		c= 'a'
    		func = getattr(self, c, None)
    		func()
    
    test = A()
    test.b()

     

    如上,我们就可以通过字符串,调用类里面的方法了。

    也许很多童鞋能够理解这个内建函数的用法,但是却不知道这个函数的实际使用场景,那么我可以在这里给你提供一个使用场景:

        你写了一个类,类里面有很多个功能函数,还有一个主函数。在主函数里面,会传进来不同的字符串,这些字符串表示程序想要调用的方法。例如:主函数传进来一个 ‘start’ 字符串,表示程序现在要调用start函数;又过了一会,主函数传进来了一个 'pause' 字符串,表示程序现在想要调用pause函数;再过了一会,主函数传进来了一个‘stop’ 字符串,表示程序现在想要调用stop函数。那么,如上所述的一个过程,我们只需要一个getattr()函数,就可以很方便的调用类里面的各种方法。

     

    • 扩展知识

    知道了如何通过字符串调用类里面的方法,那么,如果通过字符串直接调用方法呢?这里有三个函数可以帮助我们实现这个功能(eval、locals、globals):

    >>> def a():
    	print('I am a')
    
    	
    >>> def b():
    	print('I am b')
    
    	
    >>> eval('a')
    <function a at 0x000002C526C81C80>
    >>> eval('a')()
    I am a
    >>> eval('b')()
    I am b
    >>> locals()['a']()
    I am a
    >>> locals()['b']()
    I am b
    >>> globals()['a']()
    I am a
    >>> globals()['b']()
    I am b
    >>> 

     

    相信通过上面的代码,大家已经知道如果通过字符串调用方法了。如果想要详细了解上述三个函数的具体用法,请谷歌百度哦~

    Tips:尽量不要使用eval函数,因为eval is evil。使用这个函数是不安全的,自己用还好,但如果是搭建了个服务器什么的,别有用心的人上传上来恶意代码,你的程序用eval一执行,那岂不是GG ?

    展开全文
  • C++中字符串的比较与排序

    千次阅读 2019-08-15 21:14:35
    C++中字符串的比较与排序 字符串的比较是指将两个字符串的对应字符进行比较。如果相同则对比下一对对应字符,直到不同或两个字符串同时结束。 字符串排序是指将字符串数组按指定顺序进行排序。 include <iostream...

    C++中字符串的比较与排序

    字符串的比较是指将两个字符串的对应字符进行比较。如果相同则对比下一对对应字符,直到不同或两个字符串同时结束。

    字符串排序是指将字符串数组按指定顺序进行排序。

    include <iostream>
    
    int strCmp(const void* a,const void* b)
    {
    	return (*(std::string const*)a).compare (*(std::string const*)b);
    }
    
    int main(int argc,const char* argv[])
    {
    
    	std::string str1 = "Hello World!";
    	std::string str2 = "Hello World!";
    
    	/*
    	字符串str1中的第一个字符与字符串str2中的第一个字符进行比较
    	如果相同,则对比各自的第二个字符,直到第二个字符串结束
    	如果一直相同,则返回0;如果有不同,若str1中的字符ACCII码大于str2中的ASCII码,则返回正数,否则返回负数。
    	*/
    	std::cout << str1.compare(str2) << std::endl;
    
    
    	std::string str3[] = {"xian","nanjing","shanghai","kunming"};
    
    	//求字符数组str3的第一个元素所占的字节数。该值时作为下面qsort函数的参数使用
    	size_t size = sizeof(str3[0]);
    
    	//以下求字符数组的元素个数。该值也是作为下面qsort函数的参数使用
    	size_t nmemb = sizeof(str3)/size;
    
    	/*
    	调用库函数qsort对数组str3进行排序。
    	第一个参数是要排序的数组名
    	第二个参数是要排序的数组的元素个数
    	第三个参数是要排序的数组的每个元素所占的字节数
    	第四个参数是排序条件,它是一个函数的函数名
    	*/
    	qsort(str3,nmemb,size,strCmp);
    
    	for(int i = 0;i < nmemb;i++)
    		std::cout << str3[i] << std::endl;
    
    
    	return 0;
    }
    
    展开全文
  • JavaScript通过字符串调用方法

    千次阅读 2018-10-15 11:27:19
    同学:如何通过名称字符串调用方法呢? 我:不是可以通过反射吗? 同学:那(js)javascropt呢? 我:咦咦咦,等我想想!!!!!! 我(内心独白):这个咋个没有遇到过呢,好像以前遇到都是在java,那么js没有有...
  • C# 如何利用反射,将字符串转化为类名并调用类中方法
  • c++调用函数,返回字符串数组

    千次阅读 2019-04-20 17:39:13
    c++调用函数,返回字符串数组 输出结果: a 1 v a 1 v 请按任意键继续... 代码如下: char str_1[20]; char w[20]; int a[10] = {1,2}; char * happy() { sprintf(str_1,"a %d v",a[0]); ...
  • java 操作字符串都有哪些?它们之间有什么区别? String、StringBuffer、StringBuilder String : final修饰,String的方法都是返回new String。即对String对象的任何改变都不影响到原对象,对字符串的修改...
  • I . 字符串定义 I . 字符串拼接 III . 字符串 API 调用 IV . 字符串 Demo 示例
  • C语言中字符串比较

    千次阅读 多人点赞 2020-11-02 13:18:19
    在单片机串口实现字符串命令解析这篇文章分析了在串口通信如何去解析字符串命令,这篇文章就来讨论下字符串比较的方法都有哪些? 说起比较运算,肯定第一时间想到了C语言关于比较的相关运算符 “>、<...
  • Java实现字符串逆序输出

    万次阅读 多人点赞 2018-11-22 14:52:46
    【题目描述】 写一函数,使输入的一个字符串按反序存放,在主函数输入输出反序...首先定义两个String字符串a,b,其中a用于存放正序的字符串,b用于存放逆序的字符串,然后在定义一个字符数组c,然后调用类库的t...
  • JAVA中遍历字符串中字符的三种方法

    万次阅读 多人点赞 2020-04-21 20:05:44
    1).toCharArray() 2).length(), charAt() 3).length(), substring(i ,i+1) public static void main(String[] args) { String str = "keep walking!!!"; //方法一 char[] charArray = str.toCh...
  • 微机原理,DOS功能调用及常用字符串操作。
  • 写一个函数,使输入的一个字符串按反序存放,在主函数输入和输出字符串。 2 解法 //C程序设计第五版(谭浩强) //章节:第七章 用函数实现模块化程序设计 //练习7.5 写一个函数,使输入的一个字符串按反序存放,...
  • Python关于字符串的使用演示

    千次阅读 2018-08-08 16:17:45
    的形式调用的,字符串中除了len()函数,基本都是通过.调用的。 1.字符串变量子串的截取 Python不支持单字符类型,类似于java中的char,单字符在 Python 中也是作为一个字符串使用。Python访问子字符串,是使用方...
  • python根据字符串调用函数

    千次阅读 2016-05-30 14:13:36
    在python可以根据字符串调用函数:   1、 使用getattr从字符串调用函数   在多进程,可能传递过来的是一个字符串,那么我怎么来调用一个已经存在的函数呢,主要就是使用到getattr函数的作用,这个函数...
  • js将字符串作为函数调用

    万次阅读 2018-09-29 18:27:21
    使用场景: 开发,选择不同的业务场景(将近10个),弹出一个公共的对话框,点击对话框的确认按钮,根据不同类型调用不同方法。...eval(str) 函数可计算某个字符串,并执行其中的的 JavaScri...
  • 8.5 写一个函数,使输入的一个字符串按反序存放,在主函数输入和输出字符串。 #include//8.5 写一个函数,使输入的一个字符串按反序存放,在主函数输入和输出字符串。 void input(char s[]) { gets(s); } ...
  • 为什么英文字符串是可以的,但是使用中文字符串时,为什么会出现乱码的现象? 原因:vs环境下使用的是Unicode编码,而python下的是utf-8编码。在vs环境,是不支持utf-8的显示的。所以会出现乱码 1:当传入中文...
  • 请编写函数fun(char *s),其功能是:删除字符串中的数字字符。主函数中输入字符串,调用函数,并输出结果字符串。例如若输入的字符串是:34AB9C6DE, 则应输出:ABCDE
  • C#调用C++接口返回字符串的做法

    千次阅读 2016-04-12 19:26:43
    作者:朱金灿来源:... 因此需要一种间接的做法,简单来说就是C#定义一个创建空字符串的接口,传递这个接口指针给C++模块,然后在C++模块中调用这个C#接口创建一个空的字符串接口。然后在
  • 函数反射也是同样的道理,就是通过查找函数字符串进而找到对应的函数来调用。 通过以上方法可以实现,不同模块之间的解耦,方便修改不同的模块,易于扩展! 首选要有函数字符串和函数标识符一一对应的关系表及其操作...
  • 传递英文字符串的时候没问题。。传中文的时候就不能运行了 求高手解答 ![图片说明](https://img-ask.csdn.net/upload/201605/06/1462536829_21716.jpg) ![图片说明]...
  • 调用的时候的参数param就是类名,比如是"login"我可以: if(param == "login") { login s = new login() s.exec()... } 现在问题是: 有100个这样的,我不想写if去处理。 有什么办法可以根据param的值,把这个...
  • python--根据字符串调用类方法或函数

    千次阅读 2018-05-16 23:44:17
    本文作者使用的python版本为: python 3.5.1根据字符串调用类方法使用python内置函数getattr可实现。getattr函数输入一个对象和一个字符串,返回与字符串同名的对象的属性。该函数原型为: getattr(object, name...
  • C#调用C/C++的DLL实现字符串的传递

    千次阅读 2018-05-31 11:02:27
    然后新建一个C/C++源程序文件,完成的DLL需要处理的功能,如:int dlltest(char *str, char *ans){……}str作为传入的字符串,ans作为传回的字符串,因内存实际在C#调用端分配,提供内存引用。 新建...
  • C++ string类中字符串处理函数

    千次阅读 2018-05-24 16:51:14
    string 提供字符串处理函数,利用这些函数,程序员可以在字符串内查找字符,提取连续字符序列(称为子串),以及在字符串中删除和添加。其中比较常用的查找和搜索函数是find()函数、find_first_not_of()函数、find_...
  • 有时候我们希望像Javascript一样通过字符串调用方法,这就需要用到java的反射机制了。 下面给出一个示例: 1、先写一个测试的被调用方法(在 com.test 包下的 MyTest 方法,故全类名就是 com.test.MyTest) ...
  • python字符串逆序输出的6种方法

    万次阅读 2019-04-25 19:30:44
    对于一个给定的字符串,逆序输出,这个任务对于python来说是一种很简单的操作,毕竟强大的列表和字符串处理的一些列函数足以应付这些问题 了,今天总结了一下python对于字符串的逆序输出的几种常用的方法,一共...
  • 题目:写一个函数,使输入的一个字符串按反序存放,在主函数输入和输出字符串

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,935,886
精华内容 774,354
关键字:

怎么调用类中字符串