1、强制类型转换
在实际工程中几乎是不可避免的,为此C++将强制类型转换分为4种不同的类型,以提供更加安全可靠的转换。
强制类型转换 | 说 明 |
---|---|
static_cast | 用于基本类型之间、有继承关系的类对象之间、类指针之间的转换 不能用于基本类型指针之间的转换 |
const_cast | 用于去除变量的只读属性 强制转换的目标类型必须是指针或引用 |
reinterpret_cast | 用于指针类型之间、整数和指针类型之间的转换 |
dynamic_cast | 用于有继承关系的类指针之间、有交叉关系的类指针之间的转换 具有类型检查的功能 需要虚函数的支持 |
C++提供的4种强制类型转换以关键字的方式出现,使用语法为:xxx_cast<Target Type>(Expression)
。
#include <stdio.h>
void static_cast_demo()
{
int i = 0x12345;
char c = 'c';
int *pi = &i;
char *pc = &c;
c = static_cast<char>(i);
pc = static_cast<char *>(pi); // Error,static_cast不能用于基本类型指针间的转换
}
void const_cast_demo()
{
const int &j = 1;
int &k = const_cast<int &>(j);
const int x = 2;
int &y = const_cast<int &>(x);
int z = const_cast<int>(x); // Error,const_cast的目标类型必须是指针或引用
}
void reinterpret_cast_demo()
{
int i = 0;
char c = 'c';
int *pi = &i;
char *pc = &c;
pc = reinterpret_cast<char *>(pi);
pi = reinterpret_cast<int *>(pc);
pi = reinterpret_cast<int *>(i);
c = reinterpret_cast<char>(i); // Error,reinterpret_cast不能用于基本类型间的转换
}
void dynamic_cast_demo()
{
int i = 0;
int *pi = &i;
char *pc = dynamic_cast<char *>(pi); // Error,dynamic_cast只能用于有继承关系或交叉关系的类指针间的转换,且类中必须有虚函数
}
int main()
{
static_cast_demo();
const_cast_demo();
reinterpret_cast_demo();
dynamic_cast_demo();
return 0;
}
2、字符与数字之间相互转换
atoi、atof、atol、atoll等c++11标准函数将字符串转换成int、double、long、long long等
strtol、strtod、strtof、strtoll、strtold 函数将字符串转换成int、double、float、long long、long double等
其中atof函数使用例程如下:
/* atof example: sine calculator */
#include <stdio.h> /* printf, fgets */
#include <stdlib.h> /* atof */
#include <math.h> /* sin */
int main ()
{
double n,m;
double pi=3.1415926535;
char buffer[256];
printf ("Enter degrees: ");
fgets (buffer,256,stdin);
n = atof (buffer);
m = sin (n*pi/180);
printf ("The sine of %f degrees is %f\n" , n, m);
return 0;
}
Enter degrees: 45
The sine of 45.000000 degrees is 0.707101
strtol、strtod、strtof、strtoll、strtold 函数使用例程:
long strtol(const char * str,char ** str_end,int base);
long strtol(const char * restrict str,char ** restrict str_end,int base);
long long strtoll(const char * restrict str,char ** restrict str_end,int base);
str指向要解释的以空字符结尾的字节字符串,str_end指向的指针设置为指向经过最后解释的字符的字符。
其中参数base的范围为2~36,和0,它决定了字符串以被转换为整数的权值,可以被转换的合法字符依据base而定。当base为2时合法字符为‘0’,‘1’;base为8时合法字符为‘0’,‘1’,……‘7’;base为10时合法字符为‘0’,‘1’,……‘9’;base 为16时合法字符为‘0’,‘1’,……‘9’,‘a’,……‘f’;base为24时合法字符为‘0’,……‘9’,‘a’,……‘n’,base为36时,合法字符为‘0’,……‘9’,‘a’,……‘z’。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[30] = "2030300 This is test";
char *ptr;
long ret;
ret = strtol(str, &ptr, 10);
printf("数字(无符号长整数)是 %ld\n", ret);
printf("字符串部分是 |%s|", ptr);
return(0);
}
输出:
数字(无符号长整数)是 2030300
字符串部分是 | This is test|
float strtof(const char * restrict str,char ** restrict str_end);
double strtod(const char * str,char ** str_end);
double strtod(const char * restrict str,char ** restrict str_end);
long double strtold(const char * restrict str,char ** restrict str_end);
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main(void)
{
const char *p = "111.11 -2.22 Nan nan(2) inF 0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz";
printf("Parsing '%s':\n", p);
char *end;
for (double f = strtod(p, &end); p != end; f = strtod(p, &end))
{
printf("'%.*s' -> ", (int)(end-p), p);
p = end;
if (errno == ERANGE){
printf("range error, got ");
errno = 0;
}
printf("%f\n", f);
}
}
Parsing '111.11 -2.22 Nan nan(2) inF 0X1.BC70A3D70A3D7P+6 1.18973e+4932zzz':
'111.11' -> 111.110000
' -2.22' -> -2.220000
' Nan' -> nan
' nan(2)' -> nan
' inF' -> inf
' 0X1.BC70A3D70A3D7P+6' -> 111.110000
' 1.18973e+4932' -> range error, got inf
/* strtof example */
#include <stdio.h> /* printf, NULL */
#include <stdlib.h> /* strtof */
int main ()
{
char szOrbits[] = "686.97 365.24";
char* pEnd;
float f1, f2;
f1 = strtof (szOrbits, &pEnd);
f2 = strtof (pEnd, NULL);
printf ("f1 = %f\n", f1);
printf ("f1 = %f\n", f2);
printf ("One martian year takes %.2f Earth years.\n", f1/f2);
return 0;
}
输出:
f1 = 686.969971
f1 = 365.239990
One martian year takes 1.88 Earth years.
printf("%.*s\n",int,str) 的含义
// %.*s 其中的.*表示显示的精度 对字符串输出(s)类型来说就是宽度
// 这个*代表的值由后面的参数列表中的整数型(int)值给出
// 例如:
printf("%.*s\n", 1, "abc"); // 输出a
printf("%.*s\n", 2, "abc"); // 输出ab
printf("%.*s\n", 3, "abc"); // 输出abc >3是一样的效果 因为输出类型type = s,遇到'\0'会结束
3、把数字转换成字符串string,to_string函数
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
#include <iostream> // std::cout
#include <string> // std::string, std::to_string
int main ()
{
std::string pi = "pi is " + std::to_string(3.1415926);
std::string perfect = std::to_string(1+2+4+7+14) + " is a perfect number";
std::cout << pi << '\n';
std::cout << perfect << '\n';
return 0;
}
运行结果:
pi is 3.141593
28 is a perfect number
除了to_string函数外
sprintf 最常见的应用之一莫过于把整数打印到字符串中,所以spritnf 在大多数场合可以替代itoa例如:
//把整数123 打印成一个字符串保存在s 中。
sprintf(s, "%d", 123); //产生"123"
可以指定宽度,不足的左边补空格:
sprintf(s, "%8d%8d", 123, 4567); //产生:" 123 4567"
当然也可以左对齐:
sprintf(s, "%-8d%8d", 123, 4567); //产生:"123 4567"
也可以按照16 进制打印:
sprintf(s, "%8x", 4567); //小写16 进制,宽度占8 个位置,右对齐
sprintf(s, "%-8X", 4568); //大写16 进制,宽度占8 个位置,左对齐
/* sprintf example */
#include <stdio.h>
int main ()
{
char buffer [50];
int n, a=5, b=3;
n=sprintf (buffer, "%d plus %d is %d", a, b, a+b);
printf ("[%s] is a string %d chars long\n",buffer,n);
return 0;
}
[5 plus 3 is 8] is a string 13 chars long