简明C库Notes

一、输入输出

代码解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>

int main()
{
int a;
long long int b;
double f;
char ch;
char str[255];

// 输入
scanf("%d %c %s", &a, &ch, str); // 整型、字符、字符串
scanf("%lld", &b); // 长长整型
scanf("%f", &f);
getchar(ch); // 输入字符,只要是ASCII码表上有的,都会读入(不忽略任何字符)。返回值为int类型ASCII码值
gets(str); // 输入字符串,遇到换行符才为结束,读入后会吸收掉换行符。返回值为str首地址(文件尾返回值NULL)

// 输出
printf("%d %c %s", a, ch, str);
printf("%lld", b);
printf("%5.2f", &f); // 右对齐并占用宽度为 5,保留2位小数的浮点数
putchar(ch);
puts(str);

return 0;
}

二、内存分配

代码解释

1
2
3
4
5
6
7
8
9
10
// malloc
// 用于申请一片新的地址空间
// 例:顺序表新建InitList,直接申请新空间即可
L->elem = (ElemType*)malloc(LIST_INIT_SIZE * sizeof(ElemType));

// realloc
// 用于在已使用的内存进行分配,会帮你扩大连续的内存空间,连续的!
// 例:顺序表插入,已有空间不足够了,要扩大,同时还要保证扩大后的空间仍然和之前的连续!
ElemType* newbase;
newbase = (ElemType*)realloc(L->elem, (L->listsize + LISTINCREMENT) * sizeof(ElemType));

三、字符串处理C版

代码解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <string.h>

// 输入的字符串是否为insert
char option[255];
scanf("%s", option);
if(strcmp(option, "insert")==0) // 比较结果是0为相等,正数前者大,负数后者大
{
....
}

// 复制字符串
char str1[255], str2[255];
scanf("%s", str1);
strcpy(str2, str1); // 把str1复制到str2

// 字符串长度
char s1[255];
scanf("%s", s1);
int len = strlen(s1);

// 拼接字符串
char Str1[255], Str[255];
scanf("%s", Str1);
scanf("%s", Str2);
strcat(Str1, Str2); // 把Str2接在Str1末尾

// 查找字符串中含某字符
char STR[255] = "abcdef";
char ch = 'd';
char *ptr;
ptr = strchr(STR, ch);
if(ptr!=NULL)
{
printf("位置:%ld,输出:%s", ptr-str+1, ptr);
}
else
{
printf("没有找到");
}

四、字符串处理C++版

  • C++大大增强了对字符串的支持,除了可以使用C风格的字符串,还可以使用内置的 string 类。

    string 类处理起字符串来会方便很多,完全可以代替C语言中的字符数组或字符串指针。

初步认识

  • string 变量可以直接通过赋值操作符=进行赋值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <string>
using namespace std;

int main(){
string s1; //默认值是"",也即空字符串。
string s2 = "c plus plus"; // 初始化为"c plus plus"。与C风格的字符串不同,string 的结尾没有结束标志'\0'。
string s3 = s2; // s3 的内容也是"c plus plus"。
string s4 (5, 's'); // 由 5 个's'字符组成的字符串,也就是"sssss"。
// 输入输出
string s;
cin>>s; //输入字符串(cin遇到空格就认为结束!)
cout<<s<<endl; //输出字符串
return 0;
}

运行结果:

abcd efgh↙
abcd

虽然我们输入了两个由空格隔开的网址,但是只输出了一个,这是因为输入运算符>>默认会忽略空格,遇到空格就认为输入结束,所以最后输入的efgh没有被存储到变量 s。

代码解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 求长度 length()
string s = "abcd";
int len = s.length(); // 4 (由于 string 的末尾没有'\0'字符,所以 length() 返回的是字符串的真实长度,而不是长度 +1)

// 访问单个字符,从0开始计数
s[5] = '5';

// 拼接(很简单!怎么拼都行,且只需要写+即可)
string s1 = "first ";
string s2 = "second ";
char *s3 = "third ";
char s4[] = "fourth ";
char ch = '@';
string s5 = s1 + s2;
string s6 = s1 + s3;
string s7 = s1 + s4;
string s8 = s1 + ch;

// 增删改查
// [插入]
string s1, s2;
s1 = "1234567890";
s2 = "aaa";
s1.insert(5, s2); // 也可以直接插 s1.insert(5, "aaa");
// 结果:12345aaa67890

// [删除]
string s1, s2, s3;
s1 = s2 = "1234567890";
s1.erase(5); //12345
s2.erase(5, 3); //1234590

// [截取]
string s1 = "first second third";
string s2;
s2 = s1.substr(6, 6); //second

// [查找]
string s1 = "first second third";
string s2 = "second";
int index = s1.find(s2,5); // 表示在s1的第5个字符开始查找,默认0
// 结果:6

// 转换为C风格的字符串 c_str()
string path = "D:\\demo.txt"; // 有时候必须要使用C风格的字符串(例如打开文件时的路径)
FILE *fp = fopen(path.c_str(), "rt");

数字字符

1
2
3
4
5
// 数字转字符串
string s = to_string(200);

// 字符串转数字
int a = stoi(s);

五、C 标准库 <stdarg.h>

stdarg.h 头文件定义了一个变量类型 va_list 和三个宏,这三个宏可用于在参数个数未知(即参数个数可变)时获取函数中的参数。

可变参数的函数通在参数列表的末尾是使用省略号(,…)定义的。

库变量

变量 描述
va_list 这是一个适用于 va_start()、va_arg()va_end() 这三个宏存储信息的类型。

库宏

描述
void va_start(va_list ap, last_arg) 这个宏初始化 ap 变量,它与 va_argva_end 宏是一起使用的。last_arg 是最后一个传递给函数的已知的固定参数,即省略号之前的参数。
type va_arg(va_list ap, type) 这个宏检索函数参数列表中类型为 type 的下一个参数。
void va_end(va_list ap) 这个宏允许使用了 va_start 宏的带有可变参数的函数返回。如果在从函数返回之前没有调用 va_end,则结果为未定义。

va_start

1
2
3
4
5
6
7
8
9
10
1.描述
C 库宏 void va_start(va_list ap, last_arg) 初始化 ap 变量,它与 va_arg 和 va_end 宏是一起使用的。last_arg 是最后一个传递给函数的已知的固定参数,即省略号之前的参数。
这个宏必须在使用 va_arg 和 va_end 之前被调用。

2.声明
void va_start(va_list ap, last_arg);

3.参数
ap -- 这是一个 va_list 类型的对象,它用来存储通过 va_arg 获取额外参数时所必需的信息。
last_arg -- 最后一个传递给函数的已知的固定参数。

var_arg

1
2
3
4
5
6
7
8
9
10
11
12
1.描述
C 库宏 type va_arg(va_list ap, type) 检索函数参数列表中类型为 type 的下一个参数。它无法判断检索到的参数是否是传给函数的最后一个参数。

2.声明
type va_arg(va_list ap, type)

3.参数
ap -- 这是一个 va_list 类型的对象,存储了有关额外参数和检索状态的信息。该对象应在第一次调用 va_arg 之前通过调用 va_start 进行初始化。
type -- 这是一个类型名称。该类型名称是作为扩展自该宏的表达式的类型来使用的。

4.返回值
该宏返回下一个额外的参数,是一个类型为 type 的表达式。

var_end

1
2
3
4
5
6
7
8
1.描述
C 库宏 void va_end(va_list ap) 允许使用了 va_start 宏的带有可变参数的函数返回。如果在从函数返回之前没有调用 va_end,则结果为未定义。

2.声明
void va_end(va_list ap)

3.参数
ap -- 这是之前由同一函数中的 va_start 初始化的 va_list 对象。

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include<stdarg.h>
#include<stdio.h>

int sum(int, ...);

int main(void)
{
printf("10、20 和 30 的和 = %d\n", sum(3, 10, 20, 30) );
printf("4、20、25 和 30 的和 = %d\n", sum(4, 4, 20, 25, 30) );

return 0;
}

int sum(int num_args, ...)
{
int val = 0;
va_list ap;
int i;

va_start(ap, num_args);
for(i = 0; i < num_args; i++)
{
val += va_arg(ap, int);
}
va_end(ap);

return val;
}

运行结果:

1
2
10、20 和 30 的和 = 60
4、20、25 和 30 的和 = 79