数据类型

C\C++ 是一种强类型的语言。所谓强类型,就是说,C\C++ 中任意的一个变量都必须要确定其类型,没有确定类型的变量是不允许使用的。

C\C++ 中的常见类型有:int, char, float, double, long long, bool;

1 个字节(Byte) = 8 个二进制位(bit),\(2^{31}=2147483648\approx 2.1\times 10^9\),即 21 亿,\(2^{63}\approx 9\times 10^{18}\)

不同进制的占位符

对于int整型数据类型,除了正常的十进制占位符 %d 外,在输出数据时,还经常使用八进制占位符 %o,以及十六进制占位符 %x%X

变量使用规则:

  • 变量必须先声明,后使用
  • 所有变量必须在第一条可执行语句前声明,C++ 则中无此限制。

变量(标识符)命名规则:

  • 只能由英文字母、数字或下划线组成
  • 必须以英文字母或下划线开头
  • 不允许使用C关键字
  • 严格区分大小写

注意:变量名不能使用 C\C++ 中的保留字,如 int main include return 等等

unsigned 类型

注意:在 C\C++ 中还有一类 unsigned 类型,称为无符号整数类型,有:unsigned short, unsigned int, unsigned long, unsigned long long,如果只写 unsigned,则代表 unsigned int 类型;

所谓无符号类型,就是没有正负号的整数类型,因此,unsigned 类型的整数没有负数,例如有一个 unsigned a = -1; 的语句,输出的结果实际为 4294967295,即 \(2^{32}-1\),因为在 C\C++ 中使用补码表示。

char 字符类型

  1. 字符包含哪些?

大小写英文字母(A-Z,a-z)、数字(0-9)、标点符号、运算符号等等,键盘上用英文输入法能打出来的所有可见符号以及空格、换行等不可见符号,都是字符,总共有 \(128\) 个,称为 \(ASCII\) 码(\(American\ Standard\ Code\ for\ Information\ Interchange\),美国信息交换标准代码)。

\(ASCII\) 码有 \(33\) 个字符无法显示(一些终端提供了扩展,使得这些字符可显示为诸如笑脸、扑克牌花式等 \(8\ bits\) 符号),且这 \(33\) 个字符多数都已是弃用的控制字符。控制字符的用途主要是用来操控已经处理过的文字。在 \(33\) 个字符之外的,是 \(95\) 个可显示的字符。用键盘敲下空白键所产生的空白字符也算 \(1\) 个可显示字符(显示为空白)。

  • 可见字符

可见字符编号范围是 32-126(0x20-0x7E),共 \(95\) 个字符。例如:'A' 对应 $ 65$。

  • 控制字符

\(ASCII\) 控制字符的编号范围是 0-31127 ,共 \(33\) 个字符。

下面给出了 \(ASCII\) 码表,每个字符的编号分别用二进制、八进制和十六进制给出,方便程序员查看。

  1. \(ASCII\) 码的存放

你可能会以为,每个字符都是按照图片样式存放在计算机里的,例如 "Hello, World!",那么这些字符就会排列成这个样子存在计算机的某个位置。
其实并不是这样。

每个字符的样式只存放一份,在计算机的字模库文件里,我们保存的只是这些字符对应的 \(ASCII\) 号码而已。

\n\r 的区别:

  • Unix以及Linux系统里,每行结尾只有“<换行>”,即 \n

  • Windows系统里面,每行结尾是“<回车><换行>”,即 \r\n

  • Mac系统里,每行结尾是“<回车>”,即 \r

要求大家记住下面几个常见的 ASCII 码值:

  • '0' - 48
  • 'A' - 65
  • 'a' - 97

字符和字符串的区别:

  • 字符是指用单引号引起来的一个单个ASCII码字符,如:’A’,’1’,’+’等等。
  • 字符串则是用双引号引起来的多个ASCII码字符,如:”A”, “Hello”等。

’A’”A”有什么区别?

  • “A” 里包含了 2 个字符

双引号的末尾始终会包含一个 ASCII 码值为 0 的字符 ’\0’,表示字符串的结束

  • ’\0’ 表示八进制为 \(0\)\(ASCII\) 码值的字符

因为这个不可见字符在键盘上没有对应的按键,C\C++ 允许使用反斜杠+八进制的方式表示对应的字符。

因此,'A' 表示一个字符常量,仅包含一个字符;"A" 表示一个字符串常量,包含了两个字符。

‘0’’\0’’1’’\1’……的区别:

一定要注意这个细节’0’\(ASCII\) 值是 48’\0’\(ASCII\) 值是 0

转义符 '\':

\"——输出双引号", \'——输出单引号', \\——输出反斜杠\

另外,当输出时需要对内容在代码中排版时,\ 还用于连接双引号内的多行内容,例如:I love you!

'\' 还有一个作用,即表示后面 \(3\) 位八进制数对应的 \(ASCII\) 码字符,例如:'\141' 表示 'a'。

#include <stdio.h>
//'\'称为转义字符,它可以完成一些特殊字符的输出
// '\n'换行,'\a'响铃,'\t'制表符 ,'\\'输出\
//在双引号里,如果我们需要连接两行内容,需要使用'\'
int main() {
	printf("    ((`'-'``'''-'`)) \n\
     )   -    -  ( \n\
    (   (o _ o)   ) \n\
    (    ( 0 )    ) \n\
    _'-.._'='_..-'_ \n\
  )`;#'#'#.-.#'#'#;`( \n\
  (_))    '#'    ((_) \n\
    #.  ********   # \n\
    '#.I Love You.#'           \n\
    ( '#.      .#' ) \n\
   _(  ('#. .#')  )_ \n\
  (((___) '#' (___)");
	return 0;
}

注意:

空格也是一个字符,所以如果需要输入一个字符时,若前面的变量与该字符在输入的时候有空格隔开,则一定需要在scanf语句里把这个空格打出来,否则,就会把空格作为字符输入给变量,造成错误!

#include <stdio.h>
int main() {
	int a, b;
	char c;
	scanf("%d%c%d", &a, &c, &b);
	printf("%d%c%d", a, c, b);
	return 0;
}
/*
输入:3 + 5,输出:3 1,完全错误
*/
#include <stdio.h>
int main() {
	int a, b;
	char c;
	scanf("%d %c%d", &a, &c, &b);
	printf("%d%c%d", a, c, b);
	return 0;
}
//输出正确:3+5

一、赋值运算=

"="在 C\C++ 语言中,不是用于判断两个数相等的(“==”),而是用于赋值。

int a = 5;//将 5 赋值给变量 a
a = a + 8;//将 a+8 的值重新赋值给变量 a

二、加+、减-、乘*、除/

在 C\C++ 语言中,乘法一定要打出‘*’,否则会出错,如:\(5a\) 就会报错,应打成 \(5\ast a\)

//这里的所有计算结果都没有赋值保存,因此这些计算并没有修改任何数值
a + b, a - b, a * b, a / b;

三、类型转换

在 C\C++ 中,不同基本类型的数据可以混合运算。但这些数据首先要转换成同一类型,然后再运算

整数的除法,得到的结果只保留整数部分,不会出现小数部分。结果的数据类型与参与运算的数据的类型相同。
例如:两个 int 型的数相除,结果仍为 int 类型,即为相除得到的;如果其中有一个是小数,则商即是小数。
如果两个整数类型的数据相除,需要结果是小数,则需要将其中的一个数据进行类型转换

数据类型的转换包括:自动转换强制转换

自动转换由 C\C++ 语言编译系统自动完成
强制转换则通过特定的运算完成。

  1. 自动类型转换
  • 相同类型数据的运算结果,还是该类型
  • 不同类型数据的运算结果,是两种类型中取值范围大的那种

不同数据类型的范围从大到小如下:

long double > double > float > unsigned long long > long long > unsigned int > int > short > char

注意:自动类型转换只能将范围的向的转换

  • 取值范围的类型转换成取值范围的类型能够保证数据的准确度和精确度
  • 取值范围的类型转换成取值范围的类型,则需要强制类型转换
#include <stdio.h>
int main() {
    int a = 2147483647;
    long long b = a + 1;//int+int
    printf("%lld", b);
    return 0;
}
/*
结果仍是int,溢出
-2147483648
*/
#include <stdio.h>
int main() {
    int a = 2147483647;
	// 1LL 代表 long long 类型的 1
    long long b = a + 1LL;//int+long long
    printf("%lld", b);
    return 0;
}
/*
结果编程long long,正常显示
2147483648
*/
#include <iostream>
using namespace std;
int main() {
	cout << 8/3;
}
// 输出结果为 2
#include <iostream>
using namespace std;
int main() {
	cout << 1.0*8/3;
}
// 输出结果为 2.66667
  1. 强制类型转换

有时候,我们并不想将结果变为自动类型转换的数据类型,而是想要得到一个指定类型,这个时候,我们就需要进行强制类型转换。

4/3 结果为 1(double)4/3 结果为 1.333333

在整型变量前加 (double),可以将该变量在此处临时转为 double 类型并计算结果,例如:(double)a

关于乘法交换律的问题:

(1)正常数学计算的时候,交换律是满足的;

(2)当需要进行除法运算或 “强制类型转换” 时,常常不能随意做交换。

如:2/5*10010*2/54(double)2/5*104.000000

也可以通过强制类型转换,将 8 转为 double 类型。

#include <iostream>
using namespace std;
int main() {
	cout << (double)8/3;
}
// 输出结果为 2.66667

两种将 int 转为 long long 的方式:

  • (long long)a;//a可以是一个变量,或者是数字,如(long long)5

  • 1LL;//只能用于数字后

#include <stdio.h>
int main() {
	int n;
	scanf("%d", &n);
	printf("%lld", (long long)1<<n);
	return 0;
}
#include <iostream>
using namespace std;
int main() {
	int a;
	cin >> a;
	cout << ((long long)1<<a);
	return 0;
}
#include <stdio.h>
int main() {
	int n;
	scanf("%d", &n);
	printf("%lld", 1LL<<n);
	return 0;
}
#include <iostream>
using namespace std;
int main() {
	int a;
	cin >> a;
	cout << (1LL<<a);
	return 0;
}

对于第一种,有时候我们嫌 long long 太长,可以使用 typedef 语句重新定义一个 long long 的新名字

#include <stdio.h>
typedef long long LL;//type define,给long long另外起了个名字叫“LL”
int main() {
	int n;
	scanf("%d", &n);
	printf("%lld", (LL)1<<n);
	return 0;
}
  1. 按精度输出浮点数
//C\C++
double x = 1.2382421;
printf("%.3f", x);
//C++
double x = 1.2382421;
cout << fixed << setprecision(3) << x;

四、常见问题

  • 常见问题 0:变量一定要先声明再使用,不能直接使用。

  • 常见问题 1:并不是所有的变量都一定要输入值,有的只是存储中间计算的结果,有的是用来存储最终结果。

在选择变量时一定要小心,确保所有可能的结果都要在变量范围内才行。

例如,题目中描述变量的取值范围为 \(-10,000 < a,b,c < 10,000\),是给我们使用什么类型的变量做一个提示,要求你输出 (a+b)*c 的值。

在计算机中规定,所有 int 型整数在一起运算,结果必须也保持在 int 型整数的范围内。由于 \(-200,000,000 < (a+b)\ast c < 200,000,000\),依然在 int 表示范围内,所以可以将变量全部声明为 int 类型,否则,就需要考虑表示范围更大的 long long 类型。

  • 常见问题 2:变量声明时,里面存储的值是随机值,不是 \(0\)。可以通过对其输入值,或者通过赋值运算符对其赋值。
#include <stdio.h>
int main() {
    int a, b, c, d;
    printf("%d, %d, %d, %d", a, b, c, d);
    return 0;
}
/*
输出结果:(注意,结果为随机值,每次运行都可能有变化)
0, 16, 0, 7410592
*/

格式说明符的形式如下(方括号 [] 中的项为可选项):

%[flags][width][.prec] type

  1. 类型符(type)

它用以表示输出数据的类型,以下是常用类型的汇总:

%hd%d%ld 以十进制、有符号的形式输出 shortintlong 类型的整数。

%hu%u%lu 以十进制、无符号的形式输出 shortintlong 类型的整数

%c 输出字符。

%lf 以普通方式输出 double

%e 以科学计数法输出 double

%s 输出字符串。

2、宽度(width)

它用于控制输出内容的宽度。

printf("=%12s=\n", "abc"); // 输出: \(=\ \ \ \ \ \ \ \ \ abc=\)

printf("=%12d=\n", 123); // 输出: \(=\ \ \ \ \ \ \ \ \ 123=\)

printf("=%12lf=\n", 123.5); // 输出: \(=\ \ 123.500000=\)

3、对齐标志(flags)

它用于控制输出内容的对齐方式。

不填或填+:输出的内容右对齐,这是缺省的方式,上一小节就是右对齐的示例。

填-:输出的内容左对齐

printf("=%-12s=\n", "abc"); // 输出: \(=abc\ \ \ \ \ \ \ \ \ =\)

printf("=%-12d=\n", 123); // 输出: \(=123\ \ \ \ \ \ \ \ \ =\)

printf("=%-12f=\n", 123.5); // 输出: \(=123.500000\ \ =\)

如果输出的内容是整数或浮点数,并且对齐的方式是右对齐,可以加0填充,例如:

printf("=%012s=\n", "abc"); // 输出: =000000000abc=

printf("=%012d=\n", 123); // 输出: =000000000123=

printf("=%012f=\n", 123.5); // 输出: =00123.500000=

从上面第一行代码的结果看出,输出的内容不是整数或浮点数,是字符串,不能在前面填 \(0\)

左对齐的时候,能在整数或浮点数的后面补 \(0\) 吗?浮点数最多可以补到 \(6\) 位,整数不行,你的存款能在后面补 \(0\) 吗?

4、精度(prec)

如果输出的内容是浮点数,它用于控制输出内容的精度,也就是说小数点后面保留多少位,后面的数四舍五入。

printf("=%12.2lf=\n", 123.5); // 输出 = 123.50=

printf("=%.2lf=\n", 123.5); // 输出 =123.50=

printf("=%12.2e=\n", 123500000000.0); // 输出 = 1.24e+11=

printf("=%.2e=\n", 123500000000.0); // 输出 =1.24e+11=

变量的作用域

  1. 局部变量(在函数内声明的变量)

(1)局部变量的初值是随机的,不一定是 \(0\),在使用时需要先赋初值。

就好像我们去餐厅吃饭,前面有客人吃完离开了,桌子不一定是收拾好的。

(2)只能在本函数内使用,在函数外无法使用。

  1. 全局变量(声明在函数外,通常在 #include 那些语句的下面)

(1)全局变量的初值统一都会清 \(0\)

(2)可以在当前 C 文件的任何位置使用

  1. 静态局部变量(声明在函数内的 static 修饰的变量)

(1)可以理解为只能在该函数内使用的全局变量,初值统一都会清 \(0\)

(2)只能在本函数内使用,在函数外无法使用。

浮点数表示方法

IEEE 754浮点数标准详解

posted @ 2024-03-30 16:13  飞花阁  阅读(874)  评论(0)    收藏  举报
//雪花飘落效果