赞
踩
基本数据类型的最主要特点是,其值不可以再分解为其它类型,也就是说,基本数据类型是自我说明的
构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说一个构造类型的值可以分解成若干个"成员"或"元素"。每个"成员"都是一个基本数据类型或又是一个构造类型
C语言中构造类型:
指针是一种特殊的,同时又是具有重要作用的数据类型。其值用来表示某个变量在内存储器中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同的量
在调用函数值时,通常应向调用者返回一个函数值。这个返回的哈桉树值时具有一定的数据类型的,应在函数定义及函数说明中给以说明,调用后并不需要向调用者返回函数值,这种函数可以定义为"空类型"。其类型说明符为void
#define PRICE 30
八进制数 0开头
十六进制 0X或0x开头
short int // short
int
long int // long
long long int // long long
C语言中以十进制表示
标准C允许浮点数使用后缀。后缀为"f"或"F"即表示该数为浮点数。356f和356.是等价的
float
double
long double
以下不是合法的实数
字符常量 使用单引号括起
每个字符常量 用8bit表示
char
signed char //-128 - 127
unsigned char // 0-255
#include<stdio.h>
void main() {
char a,b;
a = 120;
b = 121;
printf("%d, %d\n", a, b); // 120, 121
printf("%c, %c\n", a, b); // x, y
}
小写字母转换为大写字母
小写字母范围 97 - 122
大写字母范围 65 - 90
#include<stdio.h>
void main() {
char a = 'a';
char b = 'b';
a = a - 32;
b = b - 32;
printf("%d, %d", a, b)
printf("%c, %c", a, b)
}
用双引号括起来
所占内存为 字符串所占字节数+1(\0 ASCII 0 为字符串结束标志)
char name[5];
name[0] = 'z';
name[1] = 'z';
name[2] = 'e';
name[3] = 'r';
char name[6] = {'z','z','e','r','\0'};
char name[] = {'z','z','e','r','\0'};
char name[] = "zzer";
_Bool
enum
int k = 0;
sizeof(int); // 查看int的大小
sizeof(k);
sizeof k;
signed int i; //带符号的整数
unsigned int j; // 无符号整数
是临时的转换,并不改变参与运算的变量的类型
强制类型转换是通过类型转换运算实现的
类型转换运算:
(类型说明符) (表达式)
(float) a // 把a转换为实型
(int)(x+y) // 把x+y运算结果转换为整型
+ | 双目运算符 | 左结合 |
- | 减法时为双目运算符,负号时是单目运算符 | 减法时左结合,负号时右结合 |
* | 双目运算符 | 左结合 |
/ | 双目运算符 | 左结合 |
% | 双目运算符(只能操作整数) | 左结合 |
运算优先级共15级
初级运算符( )、[ ]、->、. 高于 单目运算符 高于 算数运算符(先乘除后加减) 高于 关系运算符 高于 逻辑运算符(不包括!) 高于 条件运算符 高于 赋值运算符 高于 逗号运算符。
位运算符的优先级比较分散。
除了赋值运算符、条件运算符、单目运算符三类的平级运算符之间的结合顺序是从右至左,其他都是从左至右。
优先级 | 运算符 | 名称或含义 | 使用形式 | 结合方向 | 说明 |
1 | [] | 数组下标 | 数组名[常量表达式] | 左到右 | -- |
() | 圆括号 | (表达式)/函数名(形参表) | -- | ||
. | 成员选择(对象) | 对象.成员名 | -- | ||
-> | 成员选择(指针) | 对象指针->成员名 | -- | ||
2 | - | 负号运算符 | -表达式 | 右到左 | 单目运算符 |
~ | 按位取反运算符 | ~表达式 | |||
++ | 自增运算符 | ++变量名/变量名++ | |||
-- | 自减运算符 | --变量名/变量名-- | |||
* | 取值运算符 | *指针变量 | |||
& | 取地址运算符 | &变量名 | |||
! | 逻辑非运算符 | !表达式 | |||
(类型) | 强制类型转换 | (数据类型)表达式 | -- | ||
sizeof | 长度运算符 | sizeof(表达式) | -- | ||
3 | / | 除 | 表达式/表达式 | 左到右 | 双目运算符 |
* | 乘 | 表达式*表达式 | |||
% | 余数(取模) | 整型表达式%整型表达式 | |||
4 | + | 加 | 表达式+表达式 | 左到右 | 双目运算符 |
- | 减 | 表达式-表达式 | |||
5 | << | 左移 | 变量<<表达式 | 左到右 | 双目运算符 |
>> | 右移 | 变量>>表达式 | |||
6 | > | 大于 | 表达式>表达式 | 左到右 | 双目运算符 |
>= | 大于等于 | 表达式>=表达式 | |||
< | 小于 | 表达式<表达式 | |||
<= | 小于等于 | 表达式<=表达式 | |||
7 | == | 等于 | 表达式==表达式 | 左到右 | 双目运算符 |
!= | 不等于 | 表达式!= 表达式 | |||
8 | & | 按位与 | 表达式&表达式 | 左到右 | 双目运算符 |
9 | ^ | 按位异或 | 表达式^表达式 | 左到右 | 双目运算符 |
10 | | | 按位或 | 表达式|表达式 | 左到右 | 双目运算符 |
11 | && | 逻辑与 | 表达式&&表达式 | 左到右 | 双目运算符 |
12 | || | 逻辑或 | 表达式||表达式 | 左到右 | 双目运算符 |
13 | ?: | 条件运算符 | 表达式1? 表达式2: 表达式3 | 右到左 | 三目运算符 |
14 | = | 赋值运算符 | 变量=表达式 | 右到左 | -- |
/= | 除后赋值 | 变量/=表达式 | -- | ||
*= | 乘后赋值 | 变量*=表达式 | -- | ||
%= | 取模后赋值 | 变量%=表达式 | -- | ||
+= | 加后赋值 | 变量+=表达式 | -- | ||
-= | 减后赋值 | 变量-=表达式 | -- | ||
<<= | 左移后赋值 | 变量<<=表达式 | -- | ||
>>= | 右移后赋值 | 变量>>=表达式 | -- | ||
&= | 按位与后赋值 | 变量&=表达式 | -- | ||
^= | 按位异或后赋值 | 变量^=表达式 | -- | ||
|= | 按位或后赋值 | 变量|=表达式 | -- | ||
15 | , | 逗号运算符 | 表达式,表达式,… | 左到右 | -- |
++,–
void main() {
int i = 1;
printf("%d", i++); // 返回i自增之前的值1 i = 2
printf("%d", ++i); // 返回i自增之后的值3 i = 3
}
+=
-=
*=
/=
%=
<<=
>>=
&=
^=
!=
其功能是把两个表达式连接起来组成一个表达式,称为逗号表达式
一般形式
表达式1,表达式2
其求值过程是分别求两个表达式的值,并返回表达式2的值
表达式1,(表达式2,表达式3),表达式4
先运算 逗号表达式 表达式2,表达式3 并返回 表达式3 的值
再运算逗号表达式 表达式1,表达式3,表达式4 返回表达式4的值
输出单个字符
putchar(‘字符’)
putchar('A');
putchar('a');
获取键盘输入的一个字符
char c;
c = getchar();
函数概要:
fgets 函数用于从指定文件中读取字符串。
fgets 函数最多可以读取 size - 1 个字符,因为结尾处会自动添加一个字符串结束符 ‘\0’。当读取到换行符(’\n’)或文件结束符(EOF)时,表示结束读取(’\n’ 会被作为一个合法的字符读取)。
函数原型:
#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);
参数解析:
参数 含义
s 字符型指针,指向用于存放读取字符串的位置
size 指定读取的字符数(包括最后自动添加的 ‘\0’)
stream 该参数是一个 FILE 对象的指针,指定一个待操作的数据流
返回值:
如果函数调用成功,返回 s 参数指向的地址。
如果在读取字符的过程中遇到 EOF,则 eof 指示器被设置;如果还没读入任何字符就遇到这种 EOF,则 s 参数指向的位置保持原来的内容,函数返回 NULL。
如果在读取的过程中发生错误,则 error 指示器被设置,函数返回 NULL,但 s 参数指向的内容可能被改变。
#include <stdio.h>
#define MAX 1024
int main()
{
char str[MAX];
printf("请输入一个字符串:");
fgets(str, MAX, stdin);
printf("您输入的内容是:%s", str);
return 0;
}
%[flags][width][.precision][length]specifier
转换字符
|
参数类型;转换结果
|
---|---|
c
| char;字符 |
d
| int;有符号十进制整数 |
i
| 同上 |
e
| double;以指数形式输出单、双精度浮点数(小写 e) |
E
| 同上(大写 E) |
f
| double;以小数形式输出单、双精度浮点数 |
g
| double;以 %f 或 %e 中较短的输出宽度输出单、双精度浮点数(指数显示小写 e) |
G
| 同上(指数显示大写 E) |
o
| unsigned int;无符号八进制(无前导 0) |
s
| char *;字符串 |
u
| int;无符号十进制 |
x
| unsigned int;无符号十六进制(无前导 0x) |
X
| 同上(无前导 0X) |
p
| void *;指针值 |
n
| int *;存放已写字符的个数 |
%
| 不进行参数转换;% 自身 |
标志
|
含义
|
-
| 指定被转换的参数在其字段内左对齐(默认是右对齐) |
+
| 指定在输出的数前面加上正负号 |
空格
| 如果第一个字符不是正负号,则在其前面加上一个空格 |
0
| 对于数值转换,当输出长度小于字段宽度时,添加前导 0 进行填充 |
#
| 指定另一种输出形式: 1. 如果转换字符为 o,则第一个数字为 0 2. 如果转换字符为 x 或 X,则指定在输出的非 0 值钱加 0x 或 0X 3. 对于转换字符为 e、E、f、g 或 G 的情况,指定输出总是包含一个小数点。另外,对于转换字符为 g 或 G,还指定输出值尾部无意义的 0 将被保留 |
即按用户指定的格式从键盘上把数据输入到指定的变量中
scanf是一个标准库函数,函数原型在stdio.h中,与printf相同,C语言也允许scanf函数之前不必包含stdio.h文件
scanf(“格式控制字符串”, 地址列表);
地址是由地址运算符"&"后跟变量名组成的
& 取址运算符
&a 表达式,求变量地址
符号"*"用以表示该输入项读入后不赋予相应的变量,即跳过该输入值
scanf("%d%*d%d", &a, %b);
// 输入 1 2 3 时,1 -> a, 2 x, 3-> b
注意
if (表达式)
printf("条件成立\n");
if (表达式) {
// 语句块
} else if (表达式) {
//语句块
} else {
//语句块
}
switch (表达式) {
case 常量表达式1: 语句或语句块1
case 常量表达式2: 语句或语句块2
case 常量表达式3: 语句或语句块3
default: 语句或语句块
}
switch (c) {
case 'A': printf("90-100\n"); break;
case 'B': printf("80-90\n"); break;
default: printf("no match\n");
}
入口条件循环
while (表达式) {
// 循环体
}
#include <stdio.h>
#include <stdlib.h>
int main() {
int count = 0;
printf("请输入一行字符:");
while (getchar() != '\n') {
count += 1;
}
printf("你总共输入了%d个字符\n", count);
}
出口条件循环
do {
// 循环体
} while (表达式);
for (初始化变量; 条件表达式; 操作表达式) {
// 循环体
}
C99 允许在 初始化变量中声明变量并赋初值,但声明变量的作用域只能在循环体内
表达式可按实际需要进行省略,但封号不能省略
for (; 条件表达式; 操作表达式)
for (; ; 操作表达式)
for (; ; )
初始化变量 和 操作表达式 可以为逗号表达式
for (int i = 0 , j = 0 ; i < 10; i++, j++) {
printf("current i = %d j = %d\n", i, j);
}
循环嵌套
#include <stdio.h>
#include <stdlib.h>
int main() {
for (int i = 1; i <= 9; i++) {
for (int j = 1; j <= i; j++) {
printf("%-2d * %-2d = %-2d ", i, j, i*j);
}
printf("\n");
}
return 0;
}
break; 退出循环体
continue; 跳过本轮循环
continue不会跳过for循环最后的操作表达式 i++,注意与while循环的区别
赋值语句容易和变量说明,赋值表达式混淆,赋值语句必须以;结尾
int a,b,c;
变量赋初值
int a = 5;
以下赋初值方式是错误的
int a=b=c=5;
if ((x=y+5)>0) z=x;
a = 1 // 返回 a 的值
exp1 ? exp2 : exp3
exp1 为真时执行 exp2
为假时执行 exp3
goto 标签名;
标签定义
标签名: 语句
数组声明时最好进行初始化,否则会出现随机的数值
int arr[5]; // 数组下表必须为常量
数组初始化
int arr[3] = {1, 2, 3};
int arr2[3] = {1, 2}; // 未赋值的元素为0
int arr3[] = {1, 2, 3, 4}; // 不指定下标,编译器会自动计算元素个数
int arr4[10] = {[3] = 3,[5] = 5}; // C99特性指定下标赋值
int arr5[10] = {0};
sizeof(arr4) // 计算数组元素占用的总内存大小
// C99 下
//数组下标可以是变量,数组越界修改和访问也不会报错
int n = 10;
int arr[n];
// 字符数组初始化
char str[] = "";
<string.h> 头文件中定义
量取字符从头开始到第一个\0为止,返回字符长度不包括\0
返回结果为无符号整型,无符号整型之间做减法是不会返回负值的
char arr[] = "zzer";
printf("%d", strlen(arr));
char str1[] = "this is string1";
char str2[] = "string2";
char str3[20];
strcpy(str1, str2); // 将str2的内容拷贝给str1,包括\0
// str1 的长度应大于str2 否则字符拷贝会出现错误
strncpy(str3, str1, 4); // 将str1拷贝给 str3指定字符长度
strncpy(str1, str2, sizeof(str1) - 1); // strncat 函数会在指定的最大长度之后一字节的位置写入字符串结束符
str1[sizeof(str1) - 1] = '\0';
char str1[] = "today is ";
strcat(str1, "saturday"); // 将 "saturday" 连接到 str1后面并自动加上 \0
// strncat(str1, "saturday", 3); // 后面不会自动加上\0
printf("str1 = %s", str1); // str1 = today is saturday
strcmp(str1, str2); // 若str1 与str2 相等 返回0,否则返回-1
strncmp(str1, str2, n) // 判断str1与str2 前n个字符是否相等,相等返回0,不相等返回-1
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char str1[30]; char str2[30]; int i; char c; while (1) { printf("请输入字符1:"); for (i = 0; (c = getchar()) != '\n';i++ ) { str1[i] = c; } str1[i+1] = '\0'; // getchar(); printf("请输入字符2:"); for (i = 0; (c = getchar()) != '\n'; i++) { str2[i] = c; } str2[i+1] = '\0'; printf("str1 = %s\nstr2 = %s\ncmp = %d\n", str1, str2, strcmp(str1, str2)); } }
int i[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
int i[3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
int i[3][4] = {{1},{5},{9}}; // 将每行第一个元素赋值为1,5,9 其余元素为0
int i[3][4] = {0};
int i[3][4] = {[0][0]=1, [1][1]=2,[2][2]=3};
int i[][4] = {1,2,3,4,5,6,7,8,9,10,11,12};
一
#include <stdio.h> #include <string.h> #define NUM 128 int main() { int ch, i, j = 0, max = 0; int input_num = 0; int ascii[NUM] = {0}; char count[NUM] = ""; printf("请输入英文文本:"); while ((ch = getchar()) != '\n') { ascii[ch]++; // 字符对应的ASCII码加1 input_num++; } for (i = 0; i < NUM; i++) { if (ascii[i]) { count[j++] = i; if (ascii[i] > ascii[max]) { max = i; } } } printf("你总共输入了%d个字符,其中不同的字符个数有%d个。\n", input_num, strlen(count)); printf("它们是:%s\n", count); printf("出现次数最多的字符是\'%c\',它总共出现了%d次。\n", max, ascii[max]); return 0; }
二
#include <stdio.h> #include <string.h> int main() { int counts[20] = {0}; char strs[20] = ""; char c; _Bool flag; int index; printf("请输入字符:"); for (; (c = getchar()) != '\n';) { flag = 0; for (int j = 0; j < strlen(strs); j++) { if (strs[j] == c) { counts[j]++; flag = 1; } } if (!flag) { index = strlen(strs); strs[index] = c; counts[index] = 1; } } for (int i = 0; i < strlen(strs); i++) { printf("字符 %c 出现的次数为:%d\n", strs[i], counts[i]); } }
char *pa; // 定义一个指向字符型的指针变量
int *pb; // 定义一个指向整型的指针变量
取址运算符,获取变量的地址
char *pa = &a;
int *pb = &b;
取值运算符,获取指针变量指向的地址的值
printf("%c, %d\n", *pa, *pb);
避免访问未初始化的指针
#include <stdio.h>
int main() {
char str[30];
printf("请输入字符串:");
scanf("%s", str);
printf("你输入的字符是:%s", str);
return 0;
}
指针是左值;
而数组名只是一个地址常量,它不可以被修改,所以数组名不是左值。
str1 和 &str1 的值相同,但含义是不一样的。str1 表示数组第一个元素的位置,而 &str1 表示的是整个数组的位置(这里将数组看做一个整体)
char str1 = "hello";
char *ps = str1;
printf("%c\n", ps[0]);
printf("%c, %c\n", *ps, *(ps+1)); // 声明指定指针类型,ps+1可直接移向下一个数组元素的地址
char *str = "hello";
printf("%c\n", str[0]); // "h"
指针数组是一个数组,每个数组元素存放一个指针变量。
int *p1[5];
char *p2[2] = {
"How are you!",
"I'm fine"
};
for (int i = 0; i < 2; i++) {
printf("%s\n", p2[i]);
}
#include <stdio.h>
int main()
{
char *array[5] = {"monday", "tuesday", "wednesday", "thursday", "friday"};
char *(*p)[5] = &array;
printf("%s\n", *array); // monday
printf("%s\n", **p); // monday
}
void指针称为通用指针,可以指向任意类型的数据
#include <stdio.h>
int main()
{
int i = 100;
char str[] = "monday";
int *pi = &i;
char *ps = str;
void *p;
p = pi;
printf("p = %d, pi = %d\n", p, pi);
p = ps;
printf("p = %s, ps = %s\n", p, ps);
return 0;
}
void指针转换为其它类型指针时,最好进行类型转换
#include <stdio.h>
int main()
{
int i = 100;
void *p = &i;
printf("p = %d, p+1 = %d, (int *)p+1 = %d\n", p, p+1, (int *)p+1); // p = 6422036, p+1 = 6422037, (int *)p+1 = 6422040
}
当不清楚指针、对象初始化为什么值时,将它初始化为NULL
void *p = NULL;
对NULL指针进行解引用时会抛出error
常量无法被修改
#define PRICE 520
const int price 520;
const int num = 100;
const int *p = #
int num = 100;
int * const p = #
const int num = 100;
const int * const p = #
// 二级指针
const int * const *pp = &p;
类型名 函数名(参数列表)
{
函数体
}
当函数定义在执行代码之后是,函数声明写在前面,让编译器不要报错
类型名 函数名(参数列表);
实现可变参数,需要包含一个头文件叫:<stdarg.h>。
这个头文件中有三个宏和一个类型是我们需要用到的,一个类型是 va_list,三个宏,一个是 va_start,一个是 va_arg,还有一个是 va_end。这里的 va就是 variable-argument(可变参数)的缩写。
注:va_start() 的第二个参数是函数的最后一个参数名,而不是参数的数量哦。详见下面代码注释。
#include <stdio.h> #include <stdarg.h> int sum(int n, ...); int sum(int n, ...) // 三个小点是占位符,表示参数个数不确定 { int i, sum = 0; va_list vap; // 定义参数列表 va_start(vap, n); // 初始化参数列表,如果是 int sum(int gg, ...); 则这里应该是 va_start(vap, gg); for (i = 0; i < n; i++) { sum += va_arg(vap, int); // 获取参数值 } va_end(vap); // 首尾工作,关闭参数列表 return sum; } int main() { int result; result = sum(3, 1, 2, 3); printf("result = %d\n", result); return 0; }
int *p();
使用指针变量作为函数的返回值
char *getChar(char c);
char *getChar(char c) {
// 函数定义
}
不要返回函数内局部变量的指针,局部变量在离开作用域时就被销毁
int (*p)();
#include <stdio.h> int squart(int n); int squart(int n) { return n * n; } int main() { int n; int (*p)(int); p = squart; // p = &squart printf("请输入一个整数:"); scanf("%d", &n); printf("%d * %d = %d\n", n, n, (*p)(n)); // p(n) return 0; }
#include <stdio.h> int add(int, int); int sub(int, int); int calc(int (*fp)(int, int), int, int); int (*select(char))(int, int); int add(int num1, int num2) { return num1 + num2; } int sub(int num1, int num2) { return num1 - num2; } int calc(int (*fp)(int, int), int num1, int num2) { return (*fp)(num1, num2); } int (*select(char op))(int, int) { switch (op) { case '+': return add; case '-': return sub; } } int main() { int num1, num2; char op; int (*p)(int, int); printf("请输入一个表达式<1+2>:"); scanf("%d%c%d", &num1, &op, &num2); p = select(op); printf("%d %c %d = %d\n", num1, op, num2, (*p)(num1, num2)); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。