🤖 作者:包瑞清(richie bao): lastmod: 2024-08-12T21:06:05+08:00

2.1 数据类型和变量赋值

数据类型(data type)是一种数据分类,计算机可以确定需要多少内存来存储数据(写入存储器的存储单元)和运行代码。并以此告诉编译器(compiler)或解释器(interpreter),程序员将如何使用该数据(程序可能执行的功能)。

变量是程序中用于存储数据的标识符,将一个(数据)值分配给变量的过程(用等号 = 连接)即为变量赋值。通过变量赋值将指定的数据与变量名关联起来,以便在后续程序中使用这个数据。变量赋值方式因所用语言是否为静态类型(Static Typing)和动态类型(Dynamic Typing)而有所差异。在静态类型语言中(C、C++、C#等),变量赋值需要先声明(declare)变量,指定数据类型,例如int year = 2024;,这意味着数据类型是已知的,在程序运行之前通常由编译器检查其正确性;而在动态类型中(Python等),变量赋值非常简单,不需要显示地声明变量类型,例如year = 2024,这意味着在程序运行时才知道数据类型。为了像动态类型一样可以自动推断数据类型,C++ 和 C# 分别引入了 autovar 数据类型。

变量名命名一般遵循如下规则:

  1. 变量名不能包含任何关键字;
  2. 变量名不能包含任何算数运算符;
  3. 变量名不能包含除下划线外的任何特殊字符;
  4. 变量名不能包含空格;
  5. 变量名不能以数字和特殊字符为开头;
  6. 大小写敏感,即变量名区分大小写。

变量名一般使用描述性的名称,而尽量避免用单字母名称,以增加代码的可读性,例如存储年龄的变量age,总数量totalAmount 和用户名userName等。变量名的组合形式常用驼峰型(Camel Case)和蛇型(Snake Case),例如 myVariableName为驼峰型,my_variable_name为蛇型。C/C++ 和 C# 常用驼峰型,Python 常用蛇型。

☑️:内置数据类型; ⭕:标准库可支持的数据类型; ❎:无该数据类型

基本数据类型 说明 Py C C++ C#

int(integer,整数型)

包括正整数、负整数和零(whole numbers)

☑️


  year = 2024
age = 22

print("Year:",year)
print("Age:", age)
  
  🡮
Year: 2024
Age: 22
  

☑️


  #include <stdio.h>

int main() {
	int year = 2024;
	int age = 22;

	printf("Year: %d\n", year);
	printf("Age: %d\n", age);

	return 0;
}
  
  🡮
Year: 2024
Age: 22
  

☑️


  #include <iostream>

int main()
{
	int year = 2024;
	int age = 22;

    std::cout << "Year: " << year << std::endl;
	std::cout << "Age: " << age << std::endl;
}
  
  🡮
Year: 2024
Age: 22
  

☑️


  using System;

class Program
{
    static void Main()
    {
        int year = 2024;
        int age = 22;

        Console.WriteLine("Year: " + year);
        Console.WriteLine("Age: " + age);
    }
}
  
  🡮
Year: 2024
Age: 22
  

float((单精度)浮点型)

C、C++ 和 C# 中,float 和 double 表示具有不同精度级别的浮点数。 float 是浮点数的单精度 32 位表示(4字节(bytes)内存),精度约为6 ~ 7位的小数;而 double 提供双精度,占用 64 位(8字节(bytes)内存),精度约为15 ~ 16位的小数。Python 则只有一种浮点类型,表示为 float,其精度相当于 C 系列语言中的 double,精度约为15位的小数。

在C、C++ 和 C# 中,可以使用后缀fF表示为 float 单精度浮点型,而 C# 中,有后缀 D 表示 double,但是因为默认情况下浮动数据类型是双精度类型,因此不必必需使用该后缀。Python 无后缀。

在右侧的试验中,对于 float 和 double 的浮点型均输入了数值 pi = 3.14159265358979323846,后小数点位数为20位,并格式化小数输出结果位数为20,可以发现结果中,对于 float 类型可以精确到 3.141592,为6位;对于 double 类型可以精确到 3.141592653589793,为15位。

Python 示例中的 `%.20f`,C 示例中的`%.20f`,C++ 示例中的`{:.20f}`,C# 示例中的`{0:F20}` 都是字符串格式化的方法。在 C++ 中格式化方法包含于`format`头文件中,为 C++20 的新特性,因此需要在 MSVS 中 `Project -> CPP Properties -> Configuration Properties -> General -> C++ Language Standard`,配置选项为 ISO C++20 Standard (/std:c++20)或更高版本,如图

PYC icon

☑️


  #include <stdio.h>

int main() {
	float pi = 3.14159265358979323846f;

	printf("Value of Pi: %.20f\n", pi);
}
  
  🡮
Value of Pi: 3.14159274101257324219
  

☑️


  #include <iostream>
#include <format>

int main()
{
	float pi = 3.14159265358979323846f;

	std::cout << std::format("Value of Pi: {:.20f}",pi) << std::endl;
}
  
  🡮
Value of Pi: 3.14159274101257324219
  

☑️


  using System;

class Program
{
    static void Main()
    {
        float pi = 3.14159265358979323846f;

        Console.WriteLine("Value of Pi: {0:F20}", pi);
    }
}
  
  🡮
Value of Pi: 3.14159274101257324219
  

double((双精度)浮点型)

☑️(float)


  pi = 3.14159265358979323846

print("Value of Pi: %.20f"%pi)
  
  🡮
Value of Pi: 3.14159265358979311600
  

☑️


  #include <stdio.h>

int main() {
	double pi = 3.14159265358979323846;

	printf("Value of Pi: %.20f\n", pi);
}
  
  🡮
Value of Pi: 3.14159265358979311600
  

☑️


  #include <iostream>
#include <format>

int main()
{
	double pi = 3.14159265358979323846;

	std::cout << std::format("Value of Pi: {:.20f}",pi) << std::endl;
}
  
  🡮
Value of Pi: 3.14159265358979311600
  

☑️


  using System;

class Program
{
    static void Main()
    {
        double pi = 3.14159265358979323846;

        Console.WriteLine("Value of Pi: {0:F20}", pi);
    }
}
  
  🡮
Value of Pi: 3.14159265358979311600
  

complex(Complex number,复数)

形如 a + bi(a、b均为实数)的数为复数,其中 a 称为实部,b 称为虚部,i 为虚数单位,是 -1 的一个平方根,即$i^2=-1$。

☑️


  z = 3 +4j

real_part = z.real
imaginary_part = z.imag

print(f"Complex number: {z}; Real part: {real_part}; Imaginary part: {imaginary_part}")
  
  🡮
Complex number: (3+4j); Real part: 3.0; Imaginary part: 4.0
  


虽然 MSVS (Microsoft Visual Studio)支持 complex.h头文件,但复数类型的实现是在内部使用了一个结构体,与标准 C 不兼容,因此在 MSVS 中double complex z = 3.0 + 4.0 * I;的 C 语句不能通过编译,但下述的示例 C 代码可以在Code::Blocks(GNU GCC Compiler)等 IDE 中实现

  #include <stdio.h>
#include <complex.h>

int main() {
    double complex z = 3.0 + 4.0 * I;

    double real_part = creal(z);
    double imaginary_part = cimag(z);

    printf("Complex number: %.2f + %.2fi; Real part: %f; Imaginary part: %f\n", z, real_part, imaginary_part);

    system("pause"); // 保持显示弹出的结果窗口
    return 0;
}
  
  🡮
Complex number: 3.00 + 4.00i; Real part: 3.000000; Imaginary part: 4.000000
  


与复数有关的函数和运算符通过 complex 类实现,并包含在 C++ 复数数学库中,其函数和操作符的声明包含于头文件 complex.h 中。提供的复数类型基于 double 类型,因此复数类型写作std::complex<double>

  #include <iostream>
#include <complex>

int main() {
    std::complex<double> z(3.0, 4.0);

    double real_part = z.real();
    double imaginary_part = z.imag();

    std::cout << "Complex number: " << z << "; " << "Real part: " << real_part << "; " << "Imaginary part: " << imaginary_part << std::endl;

    return 0;
}
  
  🡮
Complex number: (3,4); Real part: 3; Imaginary part: 4
  


在 C# 中,复数不是内置类型,但可以使用 System.Numerics 命名空间(namespace)中提供的System.Numerics.Complex结构

  using System;
using System.Numerics;

class Program
{
    static void Main()
    {
        Complex z = new Complex(3.0, 4.0);

        double real_part = z.Real;
        double imaginary_part = z.Imaginary;

        Console.WriteLine("Complex number: {0}; Real part: {1};  Imaginary part: {2}", z, real_part, imaginary_part);
    }
}
  
  🡮
Complex number: <3; 4>; Real part: 3;  Imaginary part: 4
  

char(single character,单字符)

char 数据类型存储单个字符(character)/字母(letter)/数字(number)或 ASCII 码。如果用 char 类型存储字符串,则需要配合数组,如语句写作char charArray[] = "Hello C World!";, 为 C 语言风格的字符串,在 C++ 中同。

在 Python 和 C# 中,都有 str(string) 数据类型,可以直接定义字符串;C++ 既可以使用 C 风格的字符串,也可以用string类实现字符串。Python 没有 char 数据类型,单个字符和字符串均由 str 实现

☑️


  #include <stdio.h>

int main() {
    char singleChar = 'A';
    char charArray[] = "Hello C World!";

    printf("Single char: %c\n", singleChar);
    printf("Char array: %s\n", charArray);

    return 0;
}
  
  🡮
Single char: A
Char array: Hello C World!
  

☑️


  #include <iostream>

int main() {
    char singleChar = 'B';
    char charArray[] = "Hello, C++ World!";

    std::cout << "Single char: " << singleChar << "\n" << "Char array: " << charArray << std::endl;

    return 0;
}
  
  🡮
Single char: B
Char array: Hello, C++ World!
  

☑️


  using System;

class Program
{
    static void Main()
    {
        char singleChar = 'C';
        char[] charArray = { 'H', 'e', 'l', 'l', 'o', ' ', 'C', '#', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
        string charArrayAsString = new string(charArray);

        Console.WriteLine("Single char: {0} \n Char array: {1}", singleChar, charArrayAsString);
    }
}
  
  🡮
Single char: C
 Char array: Hello C# World!
  

str (string,字符串)

☑️


  pyString = "Hello, Python World!"

print("String: ", pyString)
  
  🡮
String:  Hello, Python World!
  


在 C++ 中,字符串可以使用 C 风格的数组,和标准库中 std::string

  #include <iostream>
#include <string>

int main() {
    char cString[] = "Hello, C++ World!";
    std::string cppString = "Hello, C++ World!";

    std::cout << "C-style string: " << cString << "\n" << "std::string: " << cppString << std::endl;

    return 0;
}
  
  🡮
C-style string: Hello, C++ World!
std::string: Hello, C++ World!
  

☑️


  using System;

class Program
{
    static void Main()
    {
        string csString = "Hello, C# World!";

        Console.WriteLine("String: " + csString);
    }
}
  
  🡮
String: Hello, C# World!
  

bool(布尔)

为 true(True)或 false(False)。布尔数据类型通常配合条件语句使用,如示例代码。

示例中关键字 if 均为条件语句

☑️


  is_true = True
is_false = False

if is_true:
    print("The condition is true.")
if not is_false:
    print("The condition is false.")
  
  🡮
The condition is true.
The condition is false.
  


C 语言中,bool 类型在旧标准(C99之前)中不可用,通常用 int 表示,0 为假,而任何非0值为真。C99和更高版本,则可以使用<stdbool.h>,用 bool 关键字声明布尔类型的变量

  #include <stdio.h>
#include <stdbool.h>

int main() {
    bool isTrue = true;
    bool isFalse = false;

    if (isTrue) {
        printf("The condition is true.\n");
    }
    if (!isFalse) {
        printf("The condition is false.\n");
    }
    
    return 0;
}
  
  🡮
The condition is true.
The condition is false.
  

☑️


  #include <iostream>

int main() {
    bool isTrue = true;
    bool isFalse = false;

    if (isTrue) {
        std::cout << "The condition is true." << std::endl;
    }
    if (!isFalse) {
        std::cout << "The condition is false." << std::endl;
    }
        
    return 0;
}
  
  🡮
The condition is true.
The condition is false.
  

☑️


  using System;

class Program
{
    static void Main()
    {
        bool isTrue = true;
        bool isFalse = false;

        if (isTrue)
        {
            Console.WriteLine("The condition is true.");
        }
        if (!isFalse)
        {
            Console.WriteLine("The condition is false.");
        }
    }
}
  
  🡮
The condition is true.
The condition is false.
  

void(空值,无类型)

void 一般用于void myFunction(int),表示函数不返回任何对象;及int myFunction(void),函数不带任何参数,其同int myFunction(),因此通常并不显示的表示。

☑️


  #include <stdio.h>

void printMessage() {
    printf("Hello World!\n");
}

int main() {
    printMessage();

    return 0;
}
  
  🡮
Hello World!
  

☑️


  #include <iostream>

void printMessage() {
    std::cout << "Hello World!" << std::endl;
}

int main() {
    printMessage();
        
    return 0;
}
  
  🡮
Hello World!
  

☑️


  using System;

class Program
{
    static void printMessage()
    {
        Console.WriteLine("Hello, World!");
    }

    static void Main()
    {
        printMessage();
    }
}
  
  🡮
Hello World!
  

修饰符(modifiers):signed, unsigned, short, long

基本的数据类型可以通过使用修饰符修改数据类型的符号(正负)和值域区间(大小)。C/C++ 使用的修饰符为 signed, unsigned, short, long。C# 有预定义的修饰符,有 short, ushort, int, uint, long, ulong 等。Python 没有显式地修饰符,其动态处理,和支持任意大的整数


  a = -32768      
b = 65535               
c = -2147483648            
d = 4294967295            
e = -9223372036854775808  
f = 1000000000000000000001 # 仅受可用内存的约束

print(a,b,c,d,e,f)
  
  🡮
-32768 65535 -2147483648 4294967295 -9223372036854775808 1000000000000000000001
  

☑️


  #include <stdio.h>

int main() {
	signed int a = -10;
	unsigned int b = 10;
	short int c = 32767;
	long int d = 2147483647;
	unsigned long int e = 4294967295;

	printf("%d,%u,%d,%ld,%lu", a, b, c, d, e);

	return 0;
}
  
  🡮
-10,10,32767,2147483647,4294967295
  

☑️


  #include <iostream>
#include <format>

int main() {
	signed int a = -10;
	unsigned int b = 10;
	short int c = 32767;
	long int d = 2147483647;
	unsigned long int e = 4294967295;

	std::cout << std::format("{},{},{},{},{}", a,b,c,d,e) << std::endl;
        
    return 0;
}
  
  🡮
-10,10,32767,2147483647,4294967295
  

☑️


  using System;

class Program
{
    static void Main()
    {
        short a = -32768;               // short, 16-bit signed integer
        ushort b = 65535;               // ushort, 16-bit unsigned integer
        int c = -2147483648;            // int, 32-bit signed integer
        uint d = 4294967295;            // uint, 32-bit unsigned integer
        long e = -9223372036854775808;  // long, 64-bit signed integer
        ulong f = 18446744073709551615; // ulong, 64-bit unsigned integer

        Console.WriteLine("{0},{1},{2},{3},{4},{5}", a,b,c,d,e,f);
    }
}
  
  🡮
-32768,65535,-2147483648,4294967295,-9223372036854775808,18446744073709551615
  

auto,var(数据类型推断)

C++ 中的 auto 和 C# 中的 var 关键字,都允许编译器从赋值操作符的右侧表达式中推断变量的数据类型

示例中为了查看变量的数据类型,在 C++ 中包含了头文件 typeinfo,用 typeid()查看;在 C# 中,可以直接用 var.GetType() 方法查看

☑️(auto)


  #include <iostream>
#include <format>
#include <typeinfo>

int main()
{
	auto x = 3.14;
	auto y = 42;
	auto name = "Alice";

	std::cout << std::format("{}:{}\n{}:{};\n{}:{}", typeid(x).name(),x, typeid(y).name(),y, typeid(name).name(),name) << std::endl;
}
  
  🡮
double:3.14
int:42;
char const * __ptr64:Alice
  

☑️(var)


  using System;

class Program
{
    static void Main()
    {
        var x = 3.14;
        var y = 42;
        var name = "Alice";

        Console.WriteLine("{0}:{1}\n{2}:{3};\n{4}:{5}", x.GetType(),x,y.GetType(), y,name.GetType(), name);
    }
}
  
  🡮
System.Double:3.14
System.Int32:42;
System.String:Alice
  

object(对象类型)

object 类型是 C# 的统一类型系统(unified type system).NET 中 System.Object 的别名。所有类型,包括预定义类型(predefined)、自定义类型(user-defined)、引用类型(reference types)和值类型(value types),都直接或间接地继承于 System.Object,可以将任何类型的值赋给 object 类型地变量。 当一个值类型转换为 object 时,称为装箱(Boxing);反之,当 object 类型转换为值类型时,称为拆箱(Unboxing)

☑️


  using System;

class Program
{
    static void Main()
    {
        int x = 10;
        object obj = x;     // Boxing: x is boxed into obj
        int y = (int)obj;   // Unboxing: obj is unboxed back into an int

        object objStr = "Hello";
        object objDouble = 3.14;

        Console.WriteLine("{0}:{1}\n{2}:{3}\n{4}:{5}\n{6}:{7}\n{8}:{9}", 
            x.GetType(), x, obj.GetType(), obj, y.GetType(), y, objStr.GetType(), objStr, objDouble.GetType(), objDouble);
    }
}
  
  🡮
System.Int32:10
System.Int32:10
System.Int32:10
System.String:Hello
System.Double:3.14
  

2.2 字符串格式化和格式化说明符

字符串格式化是使用字符串插值(string interpolation)(变量替换(variable substitution))过程计算包含一个或多个占位符(placeholder)的字符串字面值,从而获得占位符被相应值替换的结果。字符串格式化通常是为了生成结构良好、具有可读性,且可自定义的文本输出,这在各种任务中都是必不可少的,例如以清晰易读的方式呈现信息,控制数据的显示方式,在字符串中插入变量或表达式以反映数据的变化,使字符串的格式适应于不同的语言和地区,保持应用程序不同部分之间或不同应用程序之间的一致性,以及以报告、图表或用户界面的结构化格式呈现数据等。

按主要特点分类 Py C C++ C#

% 风格

☑️


类似C-风格(C-style)的字符串格式化,'string'%value/(values)/{Ks:Vs}的格式化语句语法为%[(keyname)][flags][width][.precision]typecode, 如果格式化右侧提供的数据结构为字典形式,则keyname为字典键名索引;如果提供的为列表,则按顺序索引;也可以为单个值。flags标记包括:

-:在指定字符宽度时,当字符位数小于宽度则字符左对齐,末尾空格;

+:在数值前添加整数或负数符号;

0:在指定字符宽度时,当字符位数小于宽度则在字符前用0填充;

如果为空格,则在前添加空格符号位。width为字符宽度。.precision为数值精度(保留小数点位数)。typecode为格式化说明符(Format Specifier)/转换类型代码(conversion type codes),常用部分如表:

格式化符号 描述
%s 字符串,或将非字符类型对象用str()转换为字符串
%r s,不过用repr()函数转换非字符型对象为字符串
%c 参数为单个字符或者字符的Unicode码时,将Unicode码转换为对应的字符
%d 参数为数值时,转换为带有符号的十进制整数
%i d转换数值为整数
%u d转换数值为整数
%o 参数为数值时,转换为带有符号的八进制整数
%x 参数为数值时,转换为带有符号的十六进制整数,字母小写
%X 参数为数值时,转换为带有符号的十六进制整数,字母大写
%e 将数值转换为科学计数法格式,字母小写
%E 将数值转换为科学计数法格式,字母大写
%f 将数值转换为十进制浮点数
%F f,将数值转换为十进制浮点数
%g 浮点格式。如果指数小于-1或不小于精度(默认为6)使用指数格式,否则使用十进制格式
%G g
%% %%即为字符%
  print("%s says: %d/%d is %.3f." % ("John", 2, 3, 2/3))
print("Hex: %(hex)x, Octal: %(octal)7o" % {"hex":255,"octal":255})
  
  🡮
John says: 2/3 is 0.667.
Hex: ff, Octal:     377
  

☑️


C 语言中, printf格式化字符串的方法的格式化语句语法为%[flags][width][.precision]typecode,参数的具体含义同 Python 中 %的格式化方法参数说明。只是格式化时,格式化字符串和输入值间逗号(,)分割,而不用%。格式化说明符常用部分如表:

格式化符号 描述 数据类型 取值区间 大小(byte)
%d or %i 有符号十进制整数 int -2147483648 to 2147483647 4 bytes
%f 具有6位精度的浮点数 float 1.2E-38 to 3.4E+38 4 bytes
%lf 具有扩展精度的浮点数 long double 3.4E-4932 to 1.1E+4932 10 or 16 bytes
%c 单字符 char -128 to 127 1 byte
%s 字符串 char[] - -
%p 内存地址(指针) void * - 4 or 8 bytes
%ld 有符号长整型 signed long -2147483648 to 2147483647 4 bytes
%lu 无符号长整型 unsigned long 0 to 4294967295 4 bytes
%lld 有符号长长整型(Signed long long integer) long long -9223372036854775808 to 9223372036854775807 8 bytes
%llu 无符号长长整型(Unsigned long long integer) unsigned long long 0 to 18446744073709551615 8 bytes
%x 无符号十六进制 unsigned int 0 to 4294967295 4 bytes
%E 科学记数法中的浮点数 double 2.2E-308 to 1.8E+308 8 bytes
%o 无符号八进制 unsigned int 0 to 4294967295 4 bytes
%u 无符号十进制整数 unsigned int 0 to 4294967295 4 bytes
%hd 有符号短整型 short -32768 to 32767 2 bytes
%n 换行符 int * - -
%hu 无符号短整型 unsigned short 0 to 65535 2 bytes
  #include <stdio.h>

int main() {
	printf("%s says: %d/%d is %.3f.\n", "John", 2, 3, 2.0 / 3.0);
	printf("Hex: %x, Octal: %7o", 255, 255);

	return 0;
}
  
  🡮
John says: 2/3 is 0.667.
Hex: ff, Octal:     377
  

☑️


C++中,printf函数族继承自 C 语言,允许使用格式说明符进行格式化输出。

  #include <iostream>

int main()
{
	printf("%s says: %d/%d is %.3f.\n", "John", 2, 3, 2.0 / 3.0);
	printf("Hex: %x, Octal: %7o", 255, 255);

	return 0;
}
  
  🡮
John says: 2/3 is 0.667.
Hex: ff, Octal:     377
  

{placeholders}风格

☑️


str.format()支持位置索引和关键字,且可以自由搭配进行格式化,从而形成多种格式化方式。对str.format()格式化的字符串配置宽度和数值精度,一般语法为{index[keyname]:[witdh][.precision]typecode},中间由:分割,其右侧配置相关参数。如果格式化字符串中需要包含{}字符,则可以用{{}}转义。

绘制长虚线可以对-字符乘以一个倍数实现,如"-"*50

  print("{:s} says: {:d}/{:d} is {:.3f}.".format("John", 2, 3, 2/3))
print("Hex: {hex:x}, Octal: {octal:7o}".format(hex=255,octal=255))

print("-"*50)

template='{{name}}:{0},category:{1},score:{2}'
print(template.format('湘村菜馆','美食_中餐厅',4))

template='name:{},category:{},score:{}'
print(template.format('湘村菜馆','美食_中餐厅',4))

template='name:{name},category:{category},score:{score}'
print(template.format(name='湘村菜馆',category='美食_中餐厅',score=4))

info_dict={'name':'湘村菜馆','category':'美食_中餐厅','score':4}
template='name:{0[name]},category:{0[category]},score:{0[score]}'
print(template.format(info_dict))

template='name:%(name)s,category:%(category)s,score:%(score)s'
print(template%dict(name='湘村菜馆',category='美食_中餐厅',score=4))

template='name:{0},category:{category},score:{score}'
print(template.format('湘村菜馆',category='美食_中餐厅',score=4))

import sys
print('My {1[name]} runs {0.platform}.'.format(sys,{'name':'Omen'}))

info_lst=['湘村菜馆','美食_中餐厅']
print('name:{0[0]},category:{0[1]},score:{1}'.format(info_lst,4))
  
  🡮
John says: 2/3 is 0.667.
Hex: ff, Octal:     377
--------------------------------------------------
{name}:湘村菜馆,category:美食_中餐厅,score:4
name:湘村菜馆,category:美食_中餐厅,score:4
name:湘村菜馆,category:美食_中餐厅,score:4
name:湘村菜馆,category:美食_中餐厅,score:4
name:湘村菜馆,category:美食_中餐厅,score:4
name:湘村菜馆,category:美食_中餐厅,score:4
My Omen runs win32.
name:湘村菜馆,category:美食_中餐厅,score:4
  


C++20 中引入了格式化库format,其字符串格式化方法std::string()的基本语法为std::format(FormatString, Args),其中FormatString为格式化字符串,类似 Python 中str.format()格式化语法,为{[index]:[witdh][.precision]typecode}。如果格式化字符串中需要包含{}字符,则可以用{{}}转义。

绘制长虚线则使用了std::string(30, '-')方法,其std::string()为用于处理字符串的类,使用重复字符构造函数,指定重复次数和字符构造字符串对象。

  #include <iostream>
#include <format>

int main()
{
	std::cout << std::format("{:s} says: {:d} / {:d} is {:.3f}.", "John", 2, 3, 2.0 / 3.0) << std::endl;
	std::cout << std::format("Hex: {0:x}, Octal: {1:7o}",255, 255) << std::endl;

	std::cout << std::string(30, '-') << std::endl;

	std::cout << std::format("{} {}: {}!\n", "Hello", "World", 2024);
	std::cout << std::format("{1} {0}: {2}!\n", "World", "Hello", 2024);
	std::cout << std::format("{0} {1}: {0} {2}!\n", "Hello", "World", 2024);
	std::cout << std::format("{0} {2}!\n", "Hello", "World", 2024);

	return 0;
}
  
  🡮
John says: 2 / 3 is 0.667.
Hex: ff, Octal:     377
------------------------------
Hello World: 2024!
Hello World: 2024!
Hello World: Hello 2024!
Hello 2024!
  

☑️


String.Format()方法是根据指定的格式将对象的值转换为字符串,并将其插入另一个字符串,其一般常用重载(overload)语法为Format([IFormatProvider], String, Objects),将Objects(即一个或多个指定对象)转化为IFormatProvider提供的特定文化( culture-specific)格式化信息对象,例如"en-US", "fr-FR", "de-DE", "es-ES"等,并插入到String占位符中,其中IFormatProvider为可选项。

绘制长虚线则使用了new String('-', 50)方法,为String构造函数的一种重载方法,其语法为String(Char, Int32),是将String类实例化对象为指定重复次数重复给定字符的一个字符串。格式化说明符常用部分(标准数值格式说明符)如表:

格式化符号 描述 数据类型 示例
"B" ("b") 二进制字符串 Binary 42 (“B”)-> 101010
255 (“b16”) -> 0000000011111111
"C" ("c") 货币值 Currency 123.456 (“C”, en-US)-> $123.46
123.456 (“C”, fr-FR) -> 123,46 €
"D" ("d") 带可选负号的整型数字 Decimal 1234 (“D”) -> 1234
-1234 (“D6”) -> -001234
"E" ("e") 科学计数法格式(指数表示法) Exponential (scientific) 1052.0329112756 (“E”, en-US) -> 1.052033E+003
1052.0329112756 (“e”, fr-FR) -> 1,052033e+003
-1052.0329112756 (“e2”, en-US) -> -1.05e+003
-1052.0329112756 (“E2”, fr-FR) -> -1,05E+003
"F" ("f") 带有可选负号的整数和十进制数字 Fixed-point 1234.567 (“F”, en-US) -> 1234.57
-1234.56 (“F4”, en-US) -> -1234.5600
"G" ("g") Fixed-point 或 scientific (notation) General -123.456 (“G”, en-US) -> -123.456
-1.234567890e-25 (“G”, en-US) -> -1.23456789E-25
"N" ("n") 整数和十进制数字、组分隔符(group separators),和带可选负号的十进制分隔符 Number 1234.567 (“N”, en-US) -> 1,234.57
-1234.56 (“N3”, en-US) -> -1,234.560
"P" ("p") 数字乘以100,并以百分号显示 Percent 1 (“P”, en-US) -> 100.00 %
-0.39678 (“P1”, en-US) -> -39.7 %
"R" ("r") 一个可以往返( round-trip)到相同数字的字符串 Round-trip 123456789.12345678 (“R”) -> 123456789.12345678
"X" ("x") 十六进制字符串 Hexadecimal 255 (“X”) -> FF
255 (“x4”) -> 00ff
  using System;

class Program
{
    static void Main()
    {
        Console.WriteLine(String.Format("{0} says: {1:d} / {2:d} is {3:f3}.", "John", 2, 3, 2.0 / 3.0));
        Console.WriteLine(String.Format("Hex: {0:x}, Octal: {1:7d}", 255, Convert.ToString(255,8)));
        Console.WriteLine("Hex: {0:x}, Octal: {1:7d}", 255, Convert.ToString(255, 8));

        Console.WriteLine(new String('-', 50));
        Console.WriteLine(String.Format("Scientific: {0:E}", 157));        
        Console.WriteLine(String.Format("Percent: {0:P}", 0.157));
        Console.WriteLine(String.Format("Currency: {0:C}", 157));

        System.Globalization.CultureInfo culture = new System.Globalization.CultureInfo("en-US");
        Console.WriteLine(String.Format(culture,"Currency: {0:C}", 157));
    }
}
  
  🡮
John says: 2 / 3 is 0.667.
Hex: ff, Octal: 377
Hex: ff, Octal: 377
--------------------------------------------------
Scientific: 1.570000E+002
Percent: 15.70%
Currency: ¥157.00
Currency: $157.00
  

字面字符串插值(Literal String Interpolation)风格

☑️


PEP498 (Python Enhancement Proposal,Python改进提案)中引入了 f-string(formatted string literals),即添加了一个新的字符串格式化机制:字面字符串插值(Literal String Interpolation)。f-string()提供了一种使用最小语法将表达式嵌入字符串字面值的方法,为一个在运行时求值的表达式(函数),而不是一个常量值。下述示例中用关键字 def 定义了一个求平方的函数square

  def square(x):
    return x * x

num1 = 12.34567
num2 = 7
precision = 2

result = f"The sum of {num1:.2f} and {num2} is {(num1 + num2):.{precision}f}.\n The square of {num2} is {square(num2)}."

print(result)
  
  🡮
The sum of 12.35 and 7 is 19.35.
 The square of 7 is 49.
  

☑️


$ 符号将字符串字面值标识为插值字符串(interpolated string)。插值字符串是可能包含插值表达式的字符串字面值。当将插值字符串解析为结果字符串时,编译器将用表达式结果的字符串表示替换带有插值表达式的项。插值表达式的结构语法为{<interpolationExpression>[,<alignment>][:<formatString>]},其中interpolationExpression为要格式化的结果的表达式。当表达式为空时,则输出为空的字符串;alignment其值定义表达式结果字符串表示形式中的最小字符数。如果为正,则字符串表示为右对齐;如果为负,则左对齐;formatString为表达式结果类型支持的格式化字符串,例如数值格式化符号、精度(小数位数)等。

  using System;

class Program
{
    static double square(double x)
    {
        return x * x; 
    } 
    static void Main()
    {
        double num1 = 12.34567;
        double num2 = 7;

        string output = $"The sum of {num1:F2} and {num2} is {(num1 + num2):F2}.\n The square of {num2} is {square(num2)}.";
        Console.WriteLine(output);
    }
}
  
  🡮
The sum of 12.35 and 7 is 19.35.
 The square of 7 is 49.