Huazie

一半诗意 一半烟火

总览

函数声明 函数功能
double tan(double x) 计算 以弧度 x 为单位的角度的正切值(double)
float tanf(float x) 计算 以弧度 x 为单位的角度的正切值(float)
long double tanl(long double x) 计算 以弧度 x 为单位的角度的正切值(long double)
double tanh(double x); 计算 x 的双曲正切值(double)
float tanhf(float x); 计算 x 的双曲正切值(float)
long double tanhl(long double x); 计算 x 的双曲正切值(long double)
off_t tell(int fd); 用于返回文件指针当前位置相对于文件开头的偏移量
long int telldir(DIR *dirp); 获取目录流的当前位置
int textheight(char *string); 用于获取当前文本模式下字符的高度
int textwidth(char *string); 用于获取当前文本模式下字符的宽度
time_t time(time_t *timer); 可以用于获取从 1970 年 1 月 1 日 00:00:00 UTC 到当前时间的秒数
FILE *tmpfile(void); 可以用于在临时目录中创建一个唯一的临时文件,并返回文件指针
char *tmpnam(char *s); 用于创建一个唯一的临时文件名
int toascii(int c); 将一个字符转换为其对应的 ASCII 码值
int tolower(int c); 可以用于将一个 ASCII 字符转换为小写字母
int toupper(int c); 可以用于将一个 ASCII 字符转换为大写字母
double trunc(double x); 截取 x 的小数部分,并返回整数部分(double)
float truncf(float x); 截取 x 的小数部分,并返回整数部分(float)
long double truncl(long double x); 截取 x 的小数部分,并返回整数部分(long double)
void tzset(void); 可以用于设置时区信息
double tgamma(double x); 用于计算 Gamma 函数(double)
float tgammaf(float x); 用于计算 Gamma 函数(float)
long double tgammal(long double x); 用于计算 Gamma 函数(long double)

1. tan,tanf,tanl

1.1 函数说明

函数声明 函数功能
double tan(double x) 计算 以弧度 x 为单位的角度的正切值(double)
float tanf(float x) 计算 以弧度 x 为单位的角度的正切值(float)
long double tanl(long double x) 计算 以弧度 x 为单位的角度的正切值(long double)

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <math.h>

int main()
{
double x = 45.0;
double tan_value = tan(x * M_PI / 180.0);
printf("The tangent of %lf degrees is %lf\n", x, tan_value);

float xf = 60.0f;
float tan_valuef = tanf(xf * M_PI / 180.0f);
printf("The tangent of %f degrees is %f\n", xf, tan_valuef);

long double xL = 30.0l;
long double tan_valueL = tanl(xL * M_PI / 180.0l);
printf("The tangent of %Lf degrees is %Lf\n", xL, tan_valueL);
return 0;
}

1.3 运行结果

2. tanh,tanhf,tanhl

2.1 函数说明

函数声明 函数功能
double tanh(double x); 计算 x 的双曲正切值(double)
float tanhf(float x); 计算 x 的双曲正切值(float)
long double tanhl(long double x); 计算 x 的双曲正切值(long double)

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <math.h>

int main()
{
double x = 1.0;
double tan_value = tanh(x);
printf("%lf 的双曲正切值是 %lf\n", x, tan_value);

float y = 2.0f;
float tanh_value = tanhf(y);
printf("%f 的双曲正切值是 %f\n", y, tanh_value);

long double z = 3.0l;
long double tanhl_value = tanhl(z);
printf("%Lf 的双曲正切值是 %Lf\n", z, tanhl_value);

return 0;
}

2.3 运行结果

3. tell

3.1 函数说明

函数声明 函数功能
off_t tell(int fd); 用于返回文件指针当前位置相对于文件开头的偏移量

参数:

  • fd : 是文件描述符,表示要查询的文件

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
char buf[100];
int fd = open("test.txt", O_RDONLY);
off_t offset = tell(fd);
printf("当前的文件偏移量是 %ld\n", offset);

int nread = read(fd, buf, sizeof(buf));
offset = tell(fd);
printf("读取了 %d 个字节后,文件偏移量是 %ld\n", nread, offset);

close(fd);
return 0;
}

在上面这个示例中,

  • 首先我们打开了一个名为 test.txt 的文件,并使用 tell() 函数获取了当前的文件偏移量。
  • 然后我们用 read() 函数读取了一些数据,并再次使用 tell() 函数来获取新的文件偏移量。
  • 最后我们使用 close() 函数关闭文件。

注意:tell() 函数和 lseek 函数的功能类似,但有一个重要的区别:tell() 函数只用于查询当前位置,而不能修改文件指针的位置。如果要修改文件指针的位置,请使用 lseek() 函数。

下面我们来看看,使用 lseek() 函数来演示上面的 tell() 函数的示例 :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

int main()
{
char buf[100];
int fd = open("test.txt", O_RDONLY);
off_t offset = lseek(fd, 0, SEEK_CUR);
printf("当前的文件偏移量是 %ld\n", offset);

int nread = read(fd, buf, sizeof(buf));
offset = lseek(fd, 0, SEEK_CUR);
printf("读取了 %d 个字节后,文件偏移量是 %ld\n", nread, offset);

close(fd);
return 0;
}

3.3 运行结果


4. telldir

4.1 函数说明

函数声明 函数功能
long int telldir(DIR *dirp); 获取目录流的当前位置

参数:

  • dirp : 指向 DIR 类型结构体的指针

4.2 演示示例

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
#include <stdio.h>
#include <dirent.h>

int main()
{
DIR *dirp;
struct dirent *direntp;

// 打开当前工作目录
dirp = opendir(".");

if (dirp == NULL)
{
printf("无法打开目录。\n");
return 1;
}

// 遍历目录下的所有文件和子目录
while ((direntp = readdir(dirp)) != NULL)
{
printf("%s\n", direntp->d_name);
}

closedir(dirp);

return 0;
}

4.3 运行结果

5. textheight,textwidth

5.1 函数说明

函数声明 函数功能
int textheight(char *string); 用于获取当前文本模式下字符的高度
int textwidth(char *string); 用于获取当前文本模式下字符的宽度

参数:

  • string : 要查询的字符串

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <graphics.h>

int main() {
initwindow(640, 480, "Example");
char str[] = "Hello, world!";
int height = textheight(str); // 当前文本模式下字符的高度
int width = textwidth(str); // 当前文本模式下字符的宽度
outtextxy(100, 100, str);
outtextxy(100, 120, "Height: ");
outtextxy(170, 120, itoa(height, str, 10));
outtextxy(100, 140, "Width: ");
outtextxy(170, 140, itoa(width, str, 10));
getch();
closegraph();
return 0;
}

5.3 运行结果

6. time

6.1 函数说明

函数声明 函数功能
time_t time(time_t *timer); 可以用于获取从 1970 年 1 月 1 日 00:00:00 UTC 到当前时间的秒数

参数:

  • timer : 一个指向 time_t 类型对象的指针,如果不想使用此参数,可以将它设置为 NULL

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <time.h>

int main()
{
time_t curtime;
time(&curtime);
printf("当前时间是 %s", ctime(&curtime));
return 0;
}

在上面的示例中,

  • 首先我们使用 time() 函数来获取当前时间的秒数;
  • 然后使用 ctime() 函数将其转换为可读的日期和时间格式;
  • 最后,再用将日期和时间字符串输出到标准输出流中。

6.3 运行结果

7. tmpfile

7.1 函数说明

函数声明 函数功能
FILE *tmpfile(void); 可以用于在临时目录中创建一个唯一的临时文件,并返回文件指针

7.2 演示示例

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

int main()
{
FILE *fp;
char str[60];

fp = tmpfile();
if (fp == NULL)
{
perror("打开临时文件失败");
return 1;
}

fputs("这是一个临时文件", fp);
rewind(fp);
fgets(str, sizeof(str), fp);
printf("从临时文件读取的内容是: %s", str);

fclose(fp);
return 0;
}

在上述的示例中,

  • 首先我们使用 tmpfile() 函数创建一个临时文件;
  • 接着使用 fputs() 函数将字符串 "这是一个临时文件" 写入该文件;
  • 然后,我们使用 rewind() 函数将文件指针移动到文件开始处;
  • 再接着,使用 fgets() 函数从临时文件中读取数据并将其存储到字符串数组 str 中;
  • 最后,我们输出从临时文件中读取的数据,并关闭临时文件。

注意: 使用 tmpfile() 创建的临时文件只在程序运行期间存在,并在程序终止时自动删除。如果需要在程序运行期间保留临时文件,请使用 tmpnam()mkstemp() 等函数来创建文件。

7.3 运行结果

8. tmpnam

8.1 函数说明

函数声明 函数功能
char *tmpnam(char *s); 用于创建一个唯一的临时文件名

参数:

  • s : 一个指向字符数组的指针,用于存储临时文件名。如果 s 等于 NULL,则函数会返回指向静态内存区的指针,该内存区包含了唯一的临时文件名

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>

int main()
{
char tmpname[L_tmpnam];
char *filename;

filename = tmpnam(tmpname);
printf("临时文件名是:%s\n", filename);

return 0;
}

在上面的示例中,

  • 我们首先使用 tmpnam() 函数创建一个唯一的临时文件名;
  • 然后将其存储到字符数组 tmpname 中;
  • 最后,我们输出该临时文件名。

注意: 使用 tmpnam() 创建的临时文件名只在程序运行期间存在,不具有真正唯一性,因此可能存在一定程度的风险。如果需要创建一个具有真正唯一性的临时文件,请考虑使用 mkstemp() 或类似的函数。

8.3 运行结果

9. toascii

9.1 函数说明

函数声明 函数功能
int toascii(int c); 将一个字符转换为其对应的 ASCII 码值

参数:

  • c : 要转换的字符

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <ctype.h>

int main()
{
char ch = 'A';

// 将字符转换为其对应的 ASCII 码值
int ascii_val = toascii(ch);

printf("字符 %c 的 ASCII 码值为 %d\n", ch, ascii_val);

return 0;
}

注意 : toascii() 函数已经过时,不建议在新代码中使用。在 C99 标准中,改用更安全的 isascii() 函数来检查字符是否为 7-bit ASCII 字符,并使用位掩码操作或其他算法来将非 ASCII 字符转换为相应的 7-bit ASCII 码值。

知识点: 7-bit ASCII,也称为美国信息交换标准代码 (American Standard Code for Information Interchange),是一种基于英语的字符编码系统,使用 7 个二进制位(即一个字节)表示每个字符。它涵盖了拉丁字母、数字、标点符号和一些特殊符号,共计 128 个字符。

9.3 运行结果

10. tolower

10.1 函数说明

函数声明 函数功能
int tolower(int c); 可以用于将一个 ASCII 字符转换为小写字母

参数:

  • c : 要转换的字符

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <ctype.h>

int main()
{
char str[] = "Hello, World!";
int i = 0;

printf("转换前字符串: %s\n", str);

printf("转换后字符串: ");
while (str[i]) {
putchar(tolower(str[i]));
i++;
}

return 0;
}

10.3 运行结果

11. toupper

11.1 函数说明

函数声明 函数功能
int toupper(int c); 可以用于将一个 ASCII 字符转换为大写字母

参数:

  • c : 要转换的字符

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <ctype.h>

int main()
{
char str[] = "Hello, World!";
int i = 0;

printf("转换前字符串: %s\n", str);

printf("转换后字符串: ");
while (str[i]) {
putchar(toupper(str[i]));
i++;
}

return 0;
}

11.3 运行结果

12. trunc,truncf,truncl

12.1 函数说明

函数声明 函数功能
double trunc(double x); 截取 x 的小数部分,并返回整数部分(double)
float truncf(float x); 截取 x 的小数部分,并返回整数部分(float)
long double truncl(long double x); 截取 x 的小数部分,并返回整数部分(long double)

12.2 演示示例

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

int main()
{
double x = 3.14159;
float y = 2.71828f;
long double z = 1.41421356L;

// 截去 double 类型浮点数的小数部分
double a = trunc(x);

// 截去 float 类型浮点数的小数部分
float b = truncf(y);

// 截去 long double 类型浮点数的小数部分
long double c = truncl(z);

printf("double 类型 %.5lf 的整数部分为 %.0lf\n", x, a);
printf("float 类型 %.5f 的整数部分为 %.0f\n", y, b);
printf("long double 类型 %.8Lf 的整数部分为 %.0Lf\n", z, c);

return 0;
}

12.3 运行结果

13. tzset

13.1 函数说明

函数声明 函数功能
void tzset(void); 可以用于设置时区信息

13.2 演示示例

UNIX/Linux 下示例:

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

#define _XOPEN_SOURCE 700

int main()
{
time_t rawtime;
struct tm *timeinfo;

// 设置时区为 UTC
setenv("TZ", "UTC", 1);
tzset();

time(&rawtime);
timeinfo = localtime(&rawtime);
printf("当前时间是:%s", asctime(timeinfo));

return 0;
}

windows 下示例:

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
#include <stdio.h>
#include <windows.h>
#include <time.h>

int main()
{
time_t rawtime;
struct tm *timeinfo;

TIME_ZONE_INFORMATION tzinfo;
GetTimeZoneInformation(&tzinfo);

// 将 WCHAR* 转换为 char*
int len = WideCharToMultiByte(CP_UTF8, 0, tzinfo.StandardName, -1, NULL, 0, NULL, NULL);
char* standard_name = (char*) malloc(len * sizeof(char));
WideCharToMultiByte(CP_UTF8, 0, tzinfo.StandardName, -1, standard_name, len, NULL, NULL);

_putenv_s("TZ", standard_name);
tzset();

time(&rawtime);
timeinfo = localtime(&rawtime);
printf("当前时间是:%s", asctime(timeinfo));

free(standard_name);
return 0;
}

在上述示例代码中,

  • 首先定义变量 rawtimetimeinfo,分别用于存储当前时间和时间结构体。
  • 接着使用 GetTimeZoneInformation() 函数获取当前系统时区信息,并将其存储在 tzinfo 变量中。
  • 然后使用 WideCharToMultiByte() 函数将 tzinfo.StandardName 转换为 UTF-8 编码的字符串,并将其存储在 standard_name 变量中。
  • 再接着使用 putenv_s() 函数将 standard_name 设置为环境变量 TZ 的值,并使用 tzset 函数更新本地时区信息。
  • 再然后使用 localtime() 函数将 rawtime 转换为时间结构体 timeinfo
  • 之后使用 asctime() 函数将时间结构体 timeinfo 转换为字符串格式,并输出到标准输出流中。
  • 最后释放 standard_name 分配的内存空间,并正常结束程序。

13.3 运行结果

14. tgamma,tgammaf,tgammal

14.1 函数说明

函数声明 函数功能
double tgamma(double x); 用于计算 Gamma 函数(double)
float tgammaf(float x); 用于计算 Gamma 函数(float)
long double tgammal(long double x); 用于计算 Gamma 函数(long double)

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <math.h>

int main()
{
double x = 5.0;
float y = 7.2f;
long double z = 2.5L;

double result1 = tgamma(x);
float result2 = tgammaf(y);
long double result3 = tgammal(z);

printf("tgamma(%lf) = %lf\n", x, result1);
printf("tgammaf(%f) = %f\n", y, result2);
printf("tgammal(%Lf) = %Lf\n", z, result3);

return 0;
}

知识点: 伽玛函数(Gamma 函数),也叫欧拉第二积分,是阶乘函数在实数与复数上扩展的一类函数。

14.3 运行结果

参考

  1. [API Reference Document]
  2. [ASCII]

总览

函数声明 函数功能
char * strdup(const char *s); 用于将一个以 NULL 结尾的字符串复制到新分配的内存空间中
int stricmp(const char *s1, const char *s2); 用于比较两个字符串的字母序是否相等,忽略大小写
char *strerror(int errnum); 用于将指定的错误码转换为相应的错误信息
int strcmpi(const char *s1, const char *s2); 用于比较两个字符串的字母序是否相等,忽略大小写
int strncmp(const char *s1, const char *s2, size_t n); 用于比较两个字符串的前n个字符是否相等
int strncmpi(const char *s1, const char *s2, size_t n); 用于比较两个字符串的前n个字符是否相等,忽略大小写
char *strncpy(char *dest, const char *src, size_t n); 用于将一个字符串的一部分拷贝到另一个字符串中
int strnicmp(const char *s1, const char *s2, size_t n); 用于比较两个字符串的前n个字符是否相等,忽略大小写
char *strnset(char *str, int c, size_t n); 用于将一个字符串的前n个字符都设置为指定的字符
char *strpbrk(const char *str1, const char *str2); 用于在一个字符串中查找任意给定字符集合中的字符的第一次出现位置
char *strrchr(const char *str, int character); 在给定的字符串中查找指定字符的最后一个匹配项
char *strrev(char *str); 将给定字符串中的所有字符顺序颠倒,并返回颠倒后的字符串
char *strset(char *str, int character); 用于设置给定字符串中的所有字符为指定的值,并返回修改后的字符串
size_t strspn(const char *str1, const char *str2); 计算字符串 str1 中包含在字符串 str2 中的前缀子字符串长度,并返回该长度值
char *strstr(const char *str1, const char *str2); 在字符串 str1 中查找第一个出现的字符串 str2,如果找到了,则返回指向该位置的指针;否则,返回 NULL
double strtod(const char *str, char **endptr); 将字符串 str 转换为一个浮点数(double 类型),并返回该浮点数。如果发生了转换错误,则返回 0.0,并且可以通过 endptr 指针返回指向第一个无法转换的字符的指针。
char *strtok(char *str, const char *delim); 用于将一个字符串分割成多个子字符串
long int strtol(const char *str, char **endptr, int base); 将字符串 str 转换为一个长整型数(long int 类型)
char *strupr(char *str); 将字符串 str 中的所有小写字母转换为大写字母,并返回指向该字符串的指针
void swab(const void *src, void *dest, ssize_t nbytes); 将源缓冲区中的每两个相邻字节进行互换,然后将结果存储到目标缓冲区中
int system(const char *command); 执行一个 shellcmd 命令,并等待命令的完成

1. strdup

1.1 函数说明

函数声明 函数功能
char * strdup(const char *s); 用于将一个以 NULL 结尾的字符串复制到新分配的内存空间中

注意: strdup() 函数返回指向新分配的内存空间的指针,如果空间不足则返回 NULL。调用者负责释放返回的指针所指向的内存空间。 strdup() 函数与strcpy() 函数类似,但是它会动态地分配内存空间,而 strcpy() 需要调用者提供足够大的目标缓冲区。

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
char *source = "Hello World!";
char *destination = strdup(source);

if(destination != NULL)
{
printf("Original string: %s\n", source);
printf("Duplicated string: %s\n", destination);
free(destination); // 释放内存,避免内存泄漏
}

return 0;
}

1.3 运行结果

2. stricmp

2.1 函数说明

函数声明 函数功能
int stricmp(const char *s1, const char *s2); 用于比较两个字符串的字母序是否相等,忽略大小写

返回值:

  • 如果 s1s2 代表的字符串相等(忽略大小写),则返回 0
  • 如果 s1s2 小,则返回负数;
  • 如果 s1s2 大,则返回正数。

2.2 演示示例

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
#include <stdio.h>
#include <string.h>

int main()
{
char *s1 = "Hello";
char *s2 = "hElLo";

int result = stricmp(s1, s2); // 忽略大小写比较

if(result == 0)
{
printf("The strings are equal.\n");
}
else if(result < 0)
{
printf("%s is less than %s.\n", s1, s2);
}
else
{
printf("%s is greater than %s.\n", s1, s2);
}

return 0;
}

2.3 运行结果

3. strerror

3.1 函数说明

函数声明 函数功能
char *strerror(int errnum); 用于将指定的错误码转换为相应的错误信息

参数:

  • errnum : 要转换为错误信息的错误码,通常是由系统调用或库函数返回的错误码。

返回值:
指向错误信息字符串的指针,该字符串描述了与错误码相关的错误

3.2 演示示例

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

int main()
{
FILE *file = fopen("nonexistent.txt", "r");

if(file == NULL)
{
int errcode = errno; // 获取发生的错误码
printf("Error opening file: %s\n", strerror(errcode)); // 将错误码转换为错误信息并打印
}
else
{
printf("File opened successfully.\n");
fclose(file);
}

return 0;
}

3.3 运行结果

4. strcmpi

4.1 函数说明

函数声明 函数功能
int strcmpi(const char *s1, const char *s2); 用于比较两个字符串的字母序是否相等,忽略大小写

返回值:

  • 如果 s1s2 代表的字符串相等(忽略大小写),则返回 0
  • 如果 s1s2 小,则返回负数;
  • 如果 s1s2 大,则返回正数。

4.2 演示示例

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
#include <stdio.h>
#include <string.h>

int main()
{
char *s1 = "Hello";
char *s2 = "hElLo";

int result = strcmpi(s1, s2); // 忽略大小写比较

if(result == 0)
{
printf("The strings are equal.\n");
}
else if(result < 0)
{
printf("%s is less than %s.\n", s1, s2);
}
else
{
printf("%s is greater than %s.\n", s1, s2);
}

return 0;
}

看到这里,可能会疑惑 上面不是已经有了 忽略大小写的字符串比较了嘛?

strcmpistricmp 有什么区别呢?

虽然它们的实现功能相同,但是不同的编译器或操作系统可能会提供其中一个或两个函数。在具备这两个函数的系统中,strcmpi 常常作为 VC(Visual C++)Borland C++ 的扩展库函数,而 stricmp 则是 POSIX 标准中定义的函数,在许多 类UNIX系统 上可用。因此,如果需要编写可移植的代码,则应该使用 stricmp 函数,而不是 strcmpi 函数。

4.3 运行结果

5. strncmp

5.1 函数说明

函数声明 函数功能
int strncmp(const char *s1, const char *s2, size_t n); 用于比较两个字符串的前n个字符是否相等

参数:

  • s1 : 待比较的第一个字符串
  • s2 : 待比较的第二个字符串
  • n : 要比较的字符数

返回值:

  • 如果 s1s2 代表的字符串相等(忽略大小写),则返回 0
  • 如果 s1s2 小,则返回负数;
  • 如果 s1s2 大,则返回正数。

5.2 演示示例

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
#include <stdio.h>
#include <string.h>

int main()
{
char *s1 = "Hello World";
char *s2 = "Hell!";

int result = strncmp(s1, s2, 4); // 比较前4个字符

if(result == 0)
{
printf("The first 4 characters are equal.\n");
}
else if(result < 0)
{
printf("The first 4 characters of %s are less than %s.\n", s1, s2);
}
else
{
printf("The first 4 characters of %s are greater than %s.\n", s1, s2);
}

return 0;
}

5.3 运行结果

6. strncmpi

6.1 函数说明

函数声明 函数功能
int strncmpi(const char *s1, const char *s2, size_t n); 用于比较两个字符串的前n个字符是否相等,忽略大小写

参数:

  • s1 : 待比较的第一个字符串
  • s2 : 待比较的第二个字符串
  • n : 要比较的字符数

返回值:

  • 如果 s1s2 代表的字符串相等(忽略大小写),则返回 0
  • 如果 s1s2 小,则返回负数;
  • 如果 s1s2 大,则返回正数。

6.2 演示示例

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
#include <stdio.h>
#include <string.h>

int main()
{
char *s1 = "Hello World";
char *s2 = "heLL!";

int result = strncmpi(s1, s2, 4); // 比较前4个字符,忽略大小写

if(result == 0)
{
printf("The first 4 characters are equal (case insensitive).\n");
}
else if(result < 0)
{
printf("The first 4 characters of %s are less than %s (case insensitive).\n", s1, s2);
}
else
{
printf("The first 4 characters of %s are greater than %s (case insensitive).\n", s1, s2);
}

return 0;
}

注意: strncmpi 函数不是 C 语言标准库中的函数,但在某些编译器或操作系统中可能会提供。

7. strncpy

7.1 函数说明

函数声明 函数功能
char *strncpy(char *dest, const char *src, size_t n); 用于将一个字符串的一部分拷贝到另一个字符串中

参数:

  • dest : 目标字符串
  • src : 源字符串
  • n : 要拷贝的字符数

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <string.h>

int main()
{
char dest[20];
const char *src = "Hello";

strncpy(dest, src, 8); // 拷贝前8个字符

printf("The copied string is: %s\n", dest);

return 0;
}

当源字符串长度小于 n 时,strncpy() 函数将在目标字符串的末尾填充 \0 字符以达到指定的拷贝长度 n

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <string.h>

int main()
{
char dest[6];
const char *src = "Hello World";

strncpy(dest, src, 5); // 拷贝前5个字符

dest[5] = '\0'; // 手动添加末尾的\0字符

printf("The copied string is: %s\n", dest);

return 0;
}

如果源字符串长度大于等于 n 个字符,strncpy() 函数将会拷贝源字符串的前 n 个字符到目标字符串中,并且不会自动添加末尾的 \0 字符。这种情况下,目标字符串可能不是以 \0 字符结尾,因此需要手动在拷贝后的目标字符串中添加 \0 字符。

7.3 运行结果

8. strnicmp

8.1 函数说明

函数声明 函数功能
int strnicmp(const char *s1, const char *s2, size_t n); 用于比较两个字符串的前n个字符是否相等,忽略大小写

参数:

  • s1 : 待比较的第一个字符串
  • s2 : 待比较的第二个字符串
  • n : 要比较的字符数

返回值:

  • 如果 s1s2 代表的字符串相等(忽略大小写),则返回 0
  • 如果 s1s2 小,则返回负数;
  • 如果 s1s2 大,则返回正数。

8.2 演示示例

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
#include <stdio.h>
#include <string.h>

int main()
{
const char *s1 = "Hello World";
const char *s2 = "heLL!";

int result = strnicmp(s1, s2, 4); // 比较前4个字符,忽略大小写

if(result == 0)
{
printf("The first 4 characters are equal (case insensitive).\n");
}
else if(result < 0)
{
printf("The first 4 characters of %s are less than %s (case insensitive).\n", s1, s2);
}
else
{
printf("The first 4 characters of %s are greater than %s (case insensitive).\n", s1, s2);
}

return 0;
}

8.3 运行结果

9. strnset

9.1 函数说明

函数声明 函数功能
char *strnset(char *str, int c, size_t n); 用于将一个字符串的前n个字符都设置为指定的字符

参数:

  • str: 要进行操作的字符串
  • c: 要设置的字符
  • n : 要设置的字符数

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <string.h>

int main() {
char str[20] = "Hello World";
printf("Before: %s\n", str);

strnset(str, '*', 5); // 将前5个字符都设置为*

printf("After: %s\n", str);

return 0;
}

注意: strnset() 函数是非标准函数,并不是所有的编译器和操作系统都支持该函数。如果需要跨平台兼容,请使用标准库函数 memset() 来实现类似的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <string.h>

int main()
{
char str[20] = "Hello World";
printf("Before: %s\n", str);

memset(str, '*', 5); // 将前5个字符都设置为*

printf("After: %s\n", str);

return 0;
}

上述示例使用了标准库函数 memset 来将 str 的前 5 个字符都设置为 *

9.3 运行结果

10. strpbrk

10.1 函数说明

函数声明 函数功能
char *strpbrk(const char *str1, const char *str2); 用于在一个字符串中查找任意给定字符集合中的字符的第一次出现位置

参数:

  • str1 : 要进行搜索的字符串
  • str2 : 要查找的字符集合

注意: 如果在str1中没有找到str2中的任何字符,则 strpbrk 函数返回NULL 指针

10.2 演示示例

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

int main()
{
char str[] = "Hello World";
char *ptr;

ptr = strpbrk(str, "aeiou"); // 查找元音字母

if (ptr != NULL)
{
printf("Found vowel '%c' at position: %lld\n", *ptr, ptr - str + 1);
}
else
{
printf("No vowel found.\n");
}

return 0;
}

10.3 运行结果

11. strrchr

11.1 函数说明

函数声明 函数功能
char *strrchr(const char *str, int character); 在给定的字符串中查找指定字符的最后一个匹配项

参数:

  • str : 要进行搜索的字符串
  • character : 要查找的字符,其 ASCII 值由整数表示

返回值:

  • 如果匹配到,返回匹配字符的地址;
  • 如果没有找到匹配项,则返回 NULL。

11.2 演示示例

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
#include <stdio.h>
#include <string.h>

int main ()
{
const char str[] = "Hello World!";

printf("在 '%s' 中查找字符 'o' 的最后一次出现:\n", str);
char *last_o = strrchr(str, 'o');

if (last_o)
printf("最后一个 'o' 的位置:%lld\n", last_o - str);
else
printf("未找到匹配的字符。\n");

printf("在 '%s' 中查找字符 'w' 的最后一次出现:\n", str);
char *last_w = strrchr(str, 'w');

if (last_w)
printf("最后一个 'w' 的位置:%lld\n", last_w - str);
else
printf("未找到匹配的字符。\n");

return 0;
}

11.3 运行结果

12. strrev

12.1 函数说明

函数声明 函数功能
char *strrev(char *str); 将给定字符串中的所有字符顺序颠倒,并返回颠倒后的字符串

参数:

  • str : 要反转的的字符串

注意:因为 strrev() 函数是一个非标准的库函数,许多编译器可能并不支持该函数,所以在使用该函数之前,请确保你的编译器支持它。

12.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>

int main ()
{
char str[50];

printf("输入一个字符串:");
scanf("%s", str);

printf("原始字符串:%s\n", str);
printf("反转后的字符串:%s\n", strrev(str));

return 0;
}

12.3 运行结果

13. strset

13.1 函数说明

函数声明 函数功能
char *strset(char *str, int character); 用于设置给定字符串中的所有字符为指定的值,并返回修改后的字符串

参数:

  • str : 要修改的字符串
  • character : 要设置的字符,其 ASCII 值由整数表示

13.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>

int main ()
{
char str[50];

printf("请输入一个字符串:");
scanf("%s", str);

printf("原始字符串:%s\n", str);
printf("将所有字符设置为 'X' 后的字符串:%s\n", strset(str, 'X'));

return 0;
}

13.3 运行结果

14. strspn

14.1 函数说明

函数声明 函数功能
size_t strspn(const char *str1, const char *str2); 计算字符串 str1 中包含在字符串 str2 中的前缀子字符串长度,并返回该长度值

参数:

  • str1 : 要搜索的字符串
  • str2 : 包含要搜索的字符集合的 字符串

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <string.h>

int main ()
{
const char str[] = "Hello World!";
const char charset[] = "lHeoWrd";

size_t length = strspn(str, charset);

printf("在 '%s' 中,最长的前缀子串 '%s' 包含于 '%s' 中。长度为 %zu\n",
str, strndup(str, length), charset, length);

return 0;
}

上述示例代码运行后,如果出现 error: 'strndup' was not declared in this scope ,说明当前的编译器不支持 strndup() 函数。

因为 strndup() 函数是 C11 新增的函数,因此可能不是所有编译器都支持。

那我们就用如下的方式来替换一下 :

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

int main ()
{
const char str[] = "Hello World!";
const char charset[] = "lHeoWrd";

size_t length = strspn(str, charset);

char *substr = (char *)malloc(length + 1);
memcpy(substr, str, length);
substr[length] = '\0';

printf("在 '%s' 中,最长的前缀子串 '%s' 包含于 '%s' 中。长度为 %zu\n",
str, substr, charset, length);

free(substr);
return 0;
}

14.3 运行结果

15. strstr

15.1 函数说明

函数声明 函数功能
char *strstr(const char *str1, const char *str2); 在字符串 str1 中查找第一个出现的字符串 str2,如果找到了,则返回指向该位置的指针;否则,返回 NULL

参数:

  • str1 : 源字符串
  • str2 : 要查找的子字符串

15.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <string.h>

int main ()
{
const char str[] = "Hello World!";
const char substr[] = "World";

char *result = strstr(str, substr);

if (result)
printf("在 '%s' 中找到了子串 '%s'。子串起始位置是 '%s'\n", str, substr, result);
else
printf("在 '%s' 中未找到子串 '%s'\n", str, substr);

return 0;
}

15.3 运行结果

16. strtod

16.1 函数说明

函数声明 函数功能
double strtod(const char *str, char **endptr); 将字符串 str 转换为一个浮点数(double 类型),并返回该浮点数。如果发生了转换错误,则返回 0.0,并且可以通过 endptr 指针返回指向第一个无法转换的字符的指针。
参数:
  • str : 要转换为浮点数的字符串
  • endptr : 可选参数,用于存储第一个无法转换的字符的指针地址

16.2 演示示例

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

int main ()
{
const char str[] = "3.14";
// const char str[] = "3.1a4";
// const char str[] = "a3.14";
char *endptr;

double num = strtod(str, &endptr);

printf("输入字符串为 '%s'\n", str);
printf("转换后的浮点数为 %f\n", num);

if (endptr == str)
printf("无法进行任何转换。\n");
else if (*endptr != '\0')
printf("字符串 '%s' 的末尾非法字符是 '%c'\n", str, *endptr);

return 0;
}

16.3 运行结果



17. strtok

17.1 函数说明

函数声明 函数功能
char *strtok(char *str, const char *delim); 用于将一个字符串分割成多个子字符串

参数:

  • str : 要被分割的 字符串。第一次调用时,应该将其设置为要被分割的字符串的地址;以后的调用中,该参数应该为 NULL
  • delim: 分隔符字符集合,用于指定子字符串的分割标准

返回值: 分割后的第一个子字符串,并在每次调用时修改传入的原始字符串 str,使其指向下一个要被分割的子字符串

17.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>

int main ()
{
const char str[] = "Hello,World!How are you?";
const char delim[] = ", !";
char *token;

token = strtok((char *)str, delim);

while (token != NULL)
{
printf("%s\n", token);
token = strtok(NULL, delim);
}

return 0;
}

在上述的示例中,

  • 我们首先定义了字符串 str 和 字符集合 delim
  • 然后使用 strtok() 函数将字符串 str 按照字符集合 delim 中的分隔符进行分割。每次调用 strtok() 函数时,它会返回分割出的第一个子字符串,并且会修改 str 指向下一个将要被分割的子字符串。
  • 最后我们不断循环调用 strtok() 函数,并输出返回的每个子字符串,直到没有更多的子字符串可以分割为止

17.3 运行结果

18. strtol

18.1 函数说明

函数声明 函数功能
long int strtol(const char *str, char **endptr, int base); 将字符串 str 转换为一个长整型数(long int 类型)

参数:

  • str : 要被转换为长整型数的字符串
  • endptr : 可选参数,用于存储第一个无法转换的字符的指针地址
  • base: 转换的进制数,必须是 236 之间的有效数字或者 0。为 0 表示采用默认的进制数,即可以解释成合法的整数的最大进制数(一般是 10

返回值:

  • 如果成功转换,返回一个长整型数;
  • 如果发生了转换错误,则返回 0,并且可以通过 endptr 指针返回指向第一个无法转换的字符的指针。

18.2 演示示例

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

int main ()
{
const char str[] = "101011";
// const char str[] = "10101a1";
// const char str[] = "a101011";
char *endptr;

long int num = strtol(str, &endptr, 2);

printf("输入字符串为 '%s'\n", str);
printf("转换后的十进制数为 %ld\n", num);

if (endptr == str)
printf("无法进行任何转换。\n");
else if (*endptr != '\0')
printf("字符串 '%s' 的末尾非法字符是 '%c'\n", str, *endptr);

return 0;
}

18.3 运行结果



19. strupr

19.1 函数说明

函数声明 函数功能
char *strupr(char *str); 将字符串 str 中的所有小写字母转换为大写字母,并返回指向该字符串的指针

参数:

  • str : 要进行大小写转换的字符串

19.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <string.h>

int main ()
{
char str[] = "Hello, World!";
printf("原始字符串为 '%s'\n", str);
strupr(str);
printf("转换后的字符串为 '%s'\n", str);
return 0;
}

19.3 运行结果

20. swab

20.1 函数说明

函数声明 函数功能
void swab(const void *src, void *dest, ssize_t nbytes); 将源缓冲区中的每两个相邻字节进行互换,然后将结果存储到目标缓冲区中

参数:

  • str : 源缓冲区的指针
  • dest : 目标缓冲区的指针
  • nbytes : 需要交换的字节数

20.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <string.h>
#include <unistd.h>

int main ()
{
char src[] = "Hello, World!";
char dest[15];
printf("原始字符串为 '%s'\n", src);
swab(src, dest, strlen(src));
printf("转换后的字符串为 '%s'\n", dest);
return 0;
}

上面示例中,我在一开始演示时,因为没有加上 #include <unistd.h> 这个头文件,导致出现如下错误:

20.3 运行结果

21. system

21.1 函数说明

函数声明 函数功能
int system(const char *command); 执行一个 shellcmd 命令,并等待命令的完成

参数:

  • command : 要执行的 shellcmd 命令。

21.2 演示示例

下面演示 执行 ls -lshell 命令,笔者是在 windows环境下运行,故会出错,详见运行结果那里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <stdlib.h>

int main ()
{
const char command[] = "ls -l";

printf("执行命令: '%s'\n", command);

int status = system(command);

if (status != 0)
printf("执行出错!\n");

return 0;
}

再来看下,演示使用 dir 命令,在 windows 下可以输出当前目录下的所有文件和子目录

1
2
3
4
5
6
7
8
#include <stdlib.h>

int main ()
{
const char command[] = "dir";
system(command);
return 0;
}

21.3 运行结果

总览

函数声明 函数功能
unsigned int sleep(unsigned int seconds); 它是 C 语言标准库中的函数,用于使当前进程挂起一定的时间。在挂起期间,操作系统会将该进程从调度队列中移除,直到指定的时间过去为止。
void Sleep(DWORD milliseconds); 它是 Windows API 中的一部分,与 sleep 函数类似,它可以使当前线程挂起一段时间。
int sopen(const char* filename, int access, int sharemode, int shflag, ...); 它是 Microsoft Visual C++ 中的一个函数,用于打开文件并返回文件句柄。与标准库中的 fopen 函数不同,sopen 函数支持以二进制方式打开文件,并且可以指定文件读写方式、共享模式和文件访问权限等参数。
void sound(int frequency); 用于发出声音,sound 函数会持续发出声音,直到调用 nosound 函数停止
int spawnl(int mode, const char *cmdname, const char *arg0, ..., NULL); 它是在 Windows 平台上使用的函数,用于启动另一个程序,并等待该程序运行结束后再继续执行本程序
int spawnle(int mode, const char *cmdname, const char *arg0, ..., const char *envp[]); 它是在 Windows 平台上使用的函数,可以启动另一个程序,并通过指定的环境变量传递参数
int sprintf(char *str, const char *format, ...); 用于将格式化的字符串输出到指定的缓冲区中
int snprintf(char *str, size_t size, const char *format, ...); 用于将格式化的字符串输出到指定的缓冲区中,类似于 sprintf 函数,但它可以限制输出字符串的长度,避免缓冲区溢出
double sqrt(double x); 计算 x 的平方根(double)
float sqrtf(float x); 计算 x 的平方根 (float)
long double sqrtl(long double x); 计算 x 的平方根 (long double)
void srand(unsigned int seed); 用于初始化伪随机数生成器
int sscanf(const char *str, const char *format, ...); 用于从字符串中读取数据并进行格式化转换
int stat(const char *path, struct stat *buf); 用于获取文件或目录的属性信息,例如文件大小、创建时间、修改时间等。这些属性信息都被保存在一个名为 struct stat 的结构体中。
int stime(const time_t *t); 它是是 Unix/Linux 系统中的一个系统调用函数,用于设置系统时间
char *stpcpy(char *dest, const char *src); 用于复制一个字符串到另一个字符串缓冲区,并返回目标字符串的结尾指针
char* strcat(char* dest, const char* src); 用于将一个字符串拼接到另一个字符串的末尾
char* strchr(const char* str, int c); 用于查找字符串中第一次出现指定字符的位置,并返回该位置的指针
int strcmp(const char* str1, const char* str2); 用于比较两个字符串是否相等
char* strcpy(char* dest, const char* src); 用于将一个字符串复制到另一个字符串缓冲区中
size_t strcspn(const char* str, const char* charset); 用于查找字符串中第一次出现指定字符集合中任何字符的位置,并返回该位置的索引

1. sleep

1.1 函数说明

函数声明 函数功能
unsigned int sleep(unsigned int seconds); 它是 C 语言标准库中的函数,用于使当前进程挂起一定的时间。在挂起期间,操作系统会将该进程从调度队列中移除,直到指定的时间过去为止。
void Sleep(DWORD milliseconds); 它是 Windows API 中的一部分,与 sleep 函数类似,它可以使当前线程挂起一段时间。

sleep 函数参数:

  • seconds : 要挂起的时间,单位为秒

Sleep 函数参数:

  • milliseconds: 要挂起的时间,单位为毫秒

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <unistd.h>

int main()
{
printf("Start sleeping...\n");
sleep(5);
printf("Wake up!\n");

return 0;
}

在使用 sleep() 函数时,将会使当前线程或者进程暂停指定的时间,以便给其他进程或线程执行机会,同时也可以用来控制程序的运行速度。

虽然 sleep() 函数很简单,但是需要注意以下几点:

  1. sleep() 的精度并不高,它所挂起的时间可能会略微超过要求的时间。
  2. sleep() 函数是阻塞式的,即在调用 sleep() 函数期间,该进程不能进行任何其他操作,包括响应信号等。
  3. 在使用 sleep() 函数期间,如果发生信号,那么 sleep() 函数将被中断,该进程将继续运行。
1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>
#include <Windows.h>

int main()
{
printf("Start sleeping...\n");
Sleep(5000); // 暂停 5 秒钟
printf("Wake up!\n");

return 0;
}

由于 Sleep() 函数是阻塞式的,因此该函数调用期间,当前线程将被阻塞。在函数调用结束后,该线程将恢复运行。

Windows 系统下使用 Sleep() 函数时,需要注意以下几点:

  1. Sleep() 函数以毫秒为单位指定时间,精度比 sleep() 函数更高。
  2. 在调用 Sleep() 函数期间,当前线程将被阻塞,不能进行任何其他操作,包括响应信号等。
  3. 在使用 Sleep() 函数期间,如果发生信号,那么 Sleep() 函数将被中断,该线程将继续运行。

1.3 运行结果

2. sopen

2.1 函数说明

函数声明 函数功能
int sopen(const char* filename, int access, int sharemode, int shflag, ...); 它是 Microsoft Visual C++ 中的一个函数,用于打开文件并返回文件句柄。与标准库中的 fopen 函数不同,sopen 函数支持以二进制方式打开文件,并且可以指定文件读写方式、共享模式和文件访问权限等参数。

参数:

  • filename : 要打开的文件名
  • access : 指定文件的访问方式,可以是以下值之一:
    • _O_RDONLY:只读方式打开文件
    • _O_WRONLY:只写方式打开文件
    • _O_RDWR:读写方式打开文件
    • _O_APPEND:在文件末尾追加数据
    • _O_CREAT:如果文件不存在,则创建文件
    • _O_TRUNC:如果文件已存在,清空文件内容
    • _O_EXCL:与 _O_CREAT 配合使用,如果文件已经存在则打开失败
  • sharemode : 指定文件共享模式,可以是以下值之一:
    • _SH_DENYRW:独占方式打开文件,其他进程不能读取或写入该文件
    • _SH_DENYWR:共享读取方式打开文件,其他进程不能写入该文件
    • _SH_DENYRD:共享写入方式打开文件,其他进程不能读取该文件
    • _SH_DENYNO:共享方式打开文件,其他进程可以读取和写入该文件
  • shflag : 指定文件属性标志,可以是以下值之一:
    • _S_IWRITE:文件可写
    • _S_IREAD:文件可读
  • … : 可选参数。如果指定了 _O_CREAT 参数,则需要指定文件的访问权限

2.2 演示示例

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
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <sys/stat.h>

#define _SH_DENYNO 0x40

int main()
{
int handle;
char buffer[1024];

// 打开文件并读取数据
handle = sopen("output.bin", _O_RDONLY, _SH_DENYNO, _S_IREAD);
if (handle == -1)
{
printf("Failed to open file!\n");
return 1;
}
read(handle, buffer, sizeof(buffer));
printf("File content: %s\n", buffer);

// 关闭文件句柄
close(handle);

return 0;
}

指定文件共享模式,如果没有对应的宏常量,则可以定义如下:

1
2
3
4
#define _SH_DENYRW 0x10
#define _SH_DENYWR 0x20
#define _SH_DENYRD 0x30
#define _SH_DENYNO 0x40

2.3 运行结果


3. sound

3.1 函数说明

函数声明 函数功能
void sound(int frequency); 用于发出声音
void nosound(void); sound 函数会持续发出声音,直到调用 nosound 函数停止

参数:

  • frequency : 要发出的声音的频率,单位为赫兹(Hz)

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <windows.h>

int main()
{
printf("Playing sound...\n");
sound(1000); // 发出 1000 Hz 音调
Sleep(5000); // 等待 5 秒钟
nosound(); // 停止发声
printf("Sound stopped.\n");
return 0;
}

Windows 下如果上述出现 error: 'sound' was not declared in this scope,可以使用如下:

1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include <windows.h>

int main()
{
printf("Playing sound...\n");
Beep(1000, 5000); // 发出 1000 Hz 音调,持续 5 秒钟
printf("Sound stopped.\n");
return 0;
}

注意:Windows 平台上建议使用 Beep() 函数代替 sound() 函数,因为 Beep() 函数不需要特殊的硬件支持,并且可移植性更好。

4. spawnl

4.1 函数说明

函数声明 函数功能
int spawnl(int mode, const char *cmdname, const char *arg0, ..., NULL); 它是在 Windows 平台上使用的函数,用于启动另一个程序,并等待该程序运行结束后再继续执行本程序

参数:

  • mode : 执行模式,可以为 P_WAITP_NOWAIT
  • cmdname : 要执行的程序名称
  • arg0: 要传递给程序的命令行参数,以 NULL 结尾

4.2 演示示例

4.2.1 test.c

1
2
3
4
5
6
7
#include <stdio.h>

int main()
{
printf("Hello World\n");
return 0;
}

4.2.2 spawnl 演示

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

int main(void)
{
int result;

// 要执行的程序名和参数列表
const char* cmdname = "test.exe";
const char* arg0 = NULL;

// 执行程序
result = spawnl(P_WAIT, cmdname, cmdname, arg0, NULL);
if (result == -1)
{
perror("Error from spawnl");
exit(1);
}
return 0;
}

如果在使用 spawnl() 函数时遇到了 "Error from spawnl: Invalid argument" 错误,有可能是由于参数传递不正确或要执行的程序不存在等原因导致的。

以下是一些可能导致该错误的情况:

  1. 要执行的程序不存在或路径不正确。
  2. cmdname 参数包含非法字符或格式不正确。
  3. 参数列表没有以 NULL 结尾。
  4. 要执行的程序需要管理员权限,但当前用户没有足够的权限。

4.3 运行结果

5. spawnle

5.1 函数说明

函数声明 函数功能
int spawnle(int mode, const char *cmdname, const char *arg0, ..., const char *envp[]); 它是在 Windows 平台上使用的函数,可以启动另一个程序,并通过指定的环境变量传递参数

参数:

  • mode : 执行模式,可以为 P_WAITP_NOWAIT
  • cmdname : 要执行的程序名称
  • arg0 : 要传递给程序的命令行参数,以 NULL 结尾
  • envp : 要传递给程序的环境变量

5.2 演示示例

5.2.1 SubEnvTest.c

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <process.h>
#include <processenv.h>
#include <stdio.h>

int main(int argc, char *argv[], char **envp)
{
printf("SubEnvTest Command line arguments:\n");
for (int i=0; i<argc; i++)
printf("[%d] : %s\n", i, argv[i]);
printf("exec %s, Hello, %s\n", argv[0], argv[1]);

for (int i = 0; envp[i] != NULL; i++)
{
printf("%s\n", envp[i]);
}
return 0;
}

5.2.2 spawnle 演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
#include <process.h>

int main(int argc, char *argv[], char *envp[])
{
int result;

// 启动 SubEnvTest.exe,并传递当前环境变量
result = spawnle(P_WAIT, "SubEnvTest.exe", "SubEnvTest.exe", NULL, envp);
if (result == -1)
{
printf("Error: %d\n", errno);
return 1;
}

return 0;
}

5.3 运行结果

6. sprintf

6.1 函数说明

函数声明 函数功能
int sprintf(char *str, const char *format, ...); 用于将格式化的字符串输出到指定的缓冲区中

参数:

  • str : 指向字符数组(缓冲区)的指针,用于存储生成的格式化字符串
  • format : 用于指定要生成的格式化文本
  • … : 用于填充格式化字符串中的占位符

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main()
{
char buffer[128];
int value = 123;

// 将整数转换为字符串并保存到 buffer 中
sprintf(buffer, "The value is %d.", value);
printf("%s\n", buffer);

return 0;
}

6.3 运行结果

7. snprintf

7.1 函数说明

函数声明 函数功能
int snprintf(char *str, size_t size, const char *format, ...); 用于将格式化的字符串输出到指定的缓冲区中,类似于 sprintf 函数,但它可以限制输出字符串的长度,避免缓冲区溢出

参数:

  • str : 指向字符数组(缓冲区)的指针,用于存储生成的格式化字符串
  • size : 指定缓冲区可写入的最大字节数
  • format : 用于指定要生成的格式化文本
  • … : 用于填充格式化字符串中的占位符

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>

int main()
{
char buffer[5];
int value = 123456;

// 将整数转换为字符串并保存到 buffer 中,最大可写入长度为 sizeof(buffer) - 1
snprintf(buffer, sizeof(buffer), "%d", value);
printf("%s\n", buffer); // 输出 "1234"

return 0;
}

7.3 运行结果

8. sqrt,sqrtf,sqrtl

8.1 函数说明

函数声明 函数功能
double sqrt(double x); 计算 x 的平方根(double)
float sqrtf(float x); 计算 x 的平方根 (float)
long double sqrtl(long double x); 计算 x 的平方根 (long double)

参数:

  • x : 要计算平方根的数

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <math.h>

int main()
{
double x = 2.0;
float y = 3.0f;
long double z = 4.0L;

printf("sqrt(%.1f) = %.2f\n", x, sqrt(x));
printf("sqrtf(%.1f) = %.2f\n", y, sqrtf(y));
printf("sqrtl(%.1Lf) = %.2Lf\n", z, sqrtl(z));

return 0;
}

8.3 运行结果

9. srand

9.1 函数说明

函数声明 函数功能
void srand(unsigned int seed); 用于初始化伪随机数生成器

参数:

  • seed : 用于设置伪随机数生成器的种子值。不同的种子值会产生不同的随机数序列。

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main()
{
int i;

// 使用当前时间作为种子值
srand(time(NULL));

// 生成 10 个随机数并输出到控制台
for (i = 0; i < 10; i++)
{
printf("%d ", rand());
}
printf("\n");

return 0;
}

注意: 如果不设置种子值,则每次程序运行时都会得到相同的随机数序列。因此,我们在实际开发中,常常使用时间戳或其他随机值来作为种子值,以确保生成的随机数具有更好的随机性。

9.3 运行结果

10. sscanf

10.1 函数说明

函数声明 函数功能
int sscanf(const char *str, const char *format, ...); 用于从字符串中读取数据并进行格式化转换

参数:

  • str : 要读取数据的字符串
  • format : 格式字符串,用于指定要读取的数据的类型、数量和顺序
  • … : 指向要写入的变量的指针

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main()
{
char str[] = "hello world 123";
char buf[16];
int num;

// 从字符串中读取一个字符串和一个整数
if (sscanf(str, "%s %*s %d", buf, &num) == 2)
{
printf("String: %s\n", buf);
printf("Number: %d\n", num);
}

return 0;
}

在上述的示例代码中,我们使用 sscanf() 函数从字符串 "hello world 123" 中读取一个字符串和一个整数,并输出到控制台。

注意: 在格式字符串中,%s 表示读取一个字符串,%d 表示读取一个整数。另外,%*s 表示读取并忽略一个字符串。

10.3 运行结果

11. stat

11.1 函数说明

函数声明 函数功能
int stat(const char *path, struct stat *buf); 用于获取文件或目录的属性信息,例如文件大小、创建时间、修改时间等。这些属性信息都被保存在一个名为 struct stat 的结构体中。

参数:

  • path : 要获取属性信息的文件或目录路径
  • buf : 指向 struct stat 结构体的指针,用于存储获取到的属性信息

返回值:

  • 如果执行成功,则返回 0
  • 否则返回 -1 并设置相应的错误码(存储在 errno 变量中)

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <sys/stat.h>

int main()
{
struct stat file_stat;

// 获取文件属性信息
if (stat("test.txt", &file_stat) == 0) {
printf("File size: %ld bytes\n", file_stat.st_size);
printf("Creation time: %ld\n", file_stat.st_ctime);
printf("Modification time: %ld\n", file_stat.st_mtime);
}

return 0;
}

11.3 运行结果

12. stime

12.1 函数说明

函数声明 函数功能
int stime(const time_t *t); 它是是 Unix/Linux 系统中的一个系统调用函数,用于设置系统时间

参数:

  • t: 指向一个 time_t 类型变量的指针,表示要设置的系统时间

返回值:

  • 如果执行成功,则返回 0
  • 否则返回 -1 并设置相应的错误码(存储在 errno 变量中)

12.2 演示示例

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
#include <stdio.h>
#include <time.h>
#include <unistd.h>

int main()
{
time_t t;

// 获取当前时间
time(&t);

// 输出当前时间
printf("Current time: %s", ctime(&t));

// 设置系统时间为 2022 年 1 月 1 日
struct tm new_time;
new_time.tm_sec = 0;
new_time.tm_min = 0;
new_time.tm_hour = 0;
new_time.tm_mday = 1;
new_time.tm_mon = 0;
new_time.tm_year = 122;
new_time.tm_wday = 6;
new_time.tm_yday = 0;
new_time.tm_isdst = -1;

t = mktime(&new_time);
stime(&t);

// 短暂等待,确保时间设置完成
sleep(1);

// 再次输出当前时间
time(&t);
printf("New time: %s", ctime(&t));

return 0;
}

在如上的示例代码中,

  • 我们首先使用 time() 函数获取当前时间,并输出到控制台;
  • 然后,我们设置系统时间为 2022 年 1 月 1 日,并等待一秒钟以确保时间设置完成。
  • 最后,我们再次输出当前时间,以验证时间设置是否成功。

注意: stime() 函数只能在 Linux/Unix 系统上使用,并且需要 root 权限才能调用。另外,在修改系统时间时应谨慎行事,以避免对系统和应用程序造成不可预料的影响。

13. stpcpy

13.1 函数说明

函数声明 函数功能
char *stpcpy(char *dest, const char *src); 用于复制一个字符串到另一个字符串缓冲区,并返回目标字符串的结尾指针

参数:

  • dest : 目标字符串的缓冲区,必须具有足够的空间来存储源字符串
  • src : 要复制的源字符串。

返回值: 一个指向目标字符串结尾的指针

13.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <string.h>

int main()
{
char src[] = "Hello world";
char dest[32];

char *end = stpcpy(dest, src);

printf("Source string: %s\n", src);
printf("Destination string: %s\n", dest);
printf("End pointer: %p\n", end);

return 0;
}

在上述的示例代码中,我们使用 stpcpy() 函数将源字符串 "Hello world" 复制到目标字符串 dest 中,并输出两个字符串以及目标字符串的结尾指针。

注意: stpcpy() 函数只能在支持 ISO C99POSIX.1-2001 标准的系统上使用,对于其他系统,可能需要使用 strcpy() 函数代替。此外,应始终确保目标字符串缓冲区具有足够的空间来存储源字符串,以避免发生缓冲区溢出。

14. strcat

14.1 函数说明

函数声明 函数功能
char* strcat(char* dest, const char* src); 用于将一个字符串拼接到另一个字符串的末尾

参数:

  • dest : 目标字符串的缓冲区,必须具有足够的空间来存储源字符串
  • src : 要拼接的源字符串

返回值: 一个指向目标字符串结尾的指针

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <string.h>

int main()
{
char str1[32] = "Hello";
char str2[] = " world!";

printf("Before: str1=%s str2=%s\n", str1, str2);

strcat(str1, str2);

printf("After: str1=%s\n", str1);

return 0;
}

14.3 运行结果

15. strchr

15.1 函数说明

函数声明 函数功能
char* strchr(const char* str, int c); 用于查找字符串中第一次出现指定字符的位置,并返回该位置的指针

参数:

  • src : 要查找的字符串
  • c: 要查找的字符,是一个整数值

15.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <string.h>

int main()
{
char str[] = "Hello world";
char* p;

p = strchr(str, 'o');

if (p != NULL) {
printf("Found character '%c' at position %ld\n", *p, p - str);
}
else {
printf("Character not found.\n");
}

return 0;
}

注意: strchr() 函数只能查找单个字符,如果要查找一个子字符串,应使用 strstr() 函数代替。另外,在查找字符时,需要将字符转换为整数值传递给 strchr() 函数,以避免发生类型错误。

15.3 运行结果

16. strcmp

16.1 函数说明

函数声明 函数功能
int strcmp(const char* str1, const char* str2); 用于比较两个字符串是否相等

参数:

  • str1 : 要比较的第一个字符串
  • str2 : 要比较的第二个字符串

返回值: 一个整数,表示两个字符串之间的大小关系

  • 如果 str1 小于 str2,则返回负整数;
  • 如果 str1 大于 str2,则返回正整数;
  • 如果 str1 等于 str2,则返回 0。

16.2 演示示例

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

int main()
{
char str1[] = "hello World";
char str2[] = "hello world";

int result = strcmp(str1, str2);

if (result < 0) {
printf("'%s' is less than '%s'\n", str1, str2);
}
else if (result 0) {
printf("'%s' is greater than '%s'\n", str1, str2);
}
else {
printf("'%s' is equal to '%s'\n", str1, str2);
}

return 0;
}

16.3 运行结果

17. strcpy

17.1 函数说明

函数声明 函数功能
char* strcpy(char* dest, const char* src); 用于将一个字符串复制到另一个字符串缓冲区中

参数:

  • dest : 目标字符串的缓冲区,必须具有足够的空间来存储源字符串
  • src : 要复制的源字符串

返回值: 一个指向目标字符串结尾的指针

17.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <string.h>

int main() {
char src[] = "Hello world";
char dest[32];

strcpy(dest, src);

printf("Source string: %s\n", src);
printf("Destination string: %s\n", dest);

return 0;
}

注意: strcpy() 函数只能用于复制以 \0 结尾的字符串,否则可能导致未定义的行为或内存损坏。在调用 strcpy() 函数之前,应确保目标字符串缓冲区具有足够的空间来容纳源字符串,以避免发生缓冲区溢出。

17.3 运行结果

18. strcspn

18.1 函数说明

函数声明 函数功能
size_t strcspn(const char* str, const char* charset); 用于查找字符串中第一次出现指定字符集合中任何字符的位置,并返回该位置的索引

参数:

  • src : 要查找的字符串
  • charset : 要查找的字符集合

18.2 演示示例

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

int main()
{
char str[] = "Hello world";
char charset[] = "owd";

size_t index = strcspn(str, charset);

if (index != strlen(str))
{
printf("Found character '%c' at position %ld\n", str[index], index);
}
else
{
printf("No matching characters found.\n");
}

return 0;
}

在上述的示例代码中,我们使用 strcspn() 函数在字符串 "Hello world" 中查找字符集合 "owd" 中的任何字符,并输出找到的字符及其在字符串中的位置索引。

18.3 运行结果

总览

函数声明 函数功能
void setlinestyle( int linestyle, unsigned upattern, int thickness ); 设置当前绘图窗口的线条样式、线型模式和线条宽度
void *setmem(void *dest, size_t n, int c); 用于将指定内存区域的每个字节都设置为指定的值
int setmode(int fd, int mode); 它是 Windows 系统下的特定库函数,用于将指定文件的 I/O 模式设置为文本模式或二进制模式
void setpalette(int colornum, int color); 设置调色板的颜色
void setrgbpalette(int colornum, int red, int green, int blue); 用于设置当前绘图窗口的调色板中某个颜色的 RGB
void settextjustify(int horiz, int vert); 用于设置文本输出的对齐方式
void settextstyle(int font, int direction, int charsize); 用于设置当前文本输出的字体、方向和大小
void settime(struct time *timep); 设置当前系统时间
void setusercharsize(int multx, int dirx, int multy, int diry); 用于设置用户定义的字符大小
int setvbuf(FILE *stream, char *buf, int type, unsigned size); 用于设置文件流的缓冲方式
void setviewport(int left, int top, int right, int bottom, int clipflag); 用于设置绘图窗口的视口范围
void setvisualpage(int pagenum); 用于设置图形窗口中用户可见的页面
void setwritemode(int mode); 用于设置绘画操作的写入模式
void (*signal(int signum, void (*handler)(int)))(int); 用于设置指定信号的处理方式。当系统接收到某个信号时,会调用相应的信号处理函数来处理该信号。在调用 signal 函数时,需要指定要处理的信号以及相应的信号处理函数。
double sin(double x); 用于计算一个角度(以弧度为单位)的正弦值(double)
float sinf(float x); 用于计算一个角度(以弧度为单位)的正弦值(float)
long double sinl(long double x); 用于计算一个角度(以弧度为单位)的正弦值(long double)
void sincos(double x, double* sinVal, double* cosVal); 用于同时计算一个角度(以弧度为单位)的正弦值和余弦值
void sincosf(float x, float* sinVal, float* cosVal); 用于同时计算一个角度(以弧度为单位)的正弦值和余弦值
void sincosl(long double x, long double* sinVal, long double* cosVal); 用于同时计算一个角度(以弧度为单位)的正弦值和余弦值
double sinh(double x); 用于计算一个数的双曲正弦值
float sinhf(float x); 用于计算一个数的双曲正弦值
long double sinhl(long double x); 用于计算一个数的双曲正弦值

1. setlinestyle

1.1 函数说明

函数声明 函数功能
void setlinestyle( int linestyle, unsigned upattern, int thickness ); 设置当前绘图窗口的线条样式、线型模式和线条宽度

参数:

  • linestyle : 线条样式,取值范围为 0 到 4,不同的值对应着不同的线条样式,详见如下表格
  • upattern : 线型模式,它是一个 16 位的无符号整数,用二进制位表示线型模式,其中 1 表示绘制线条,0 表示空白。例如,如果 upattern 的值是 0x00FF,则表示绘制一段线条,然后空白一段,重复这个过程直到结束。如果 upattern 的值是 0x5555,则表示绘制一段虚线。
  • thickness : 线条宽度,取值范围为 1 到 10,表示线条的像素宽度
线条样式 描述
SOLID_LINE 0 实线
DOTTED_LINE 1 虚线
CENTER_LINE 2 点线
DASHED_LINE 3 长短线
USERBIT_LINE 4 双点线

1.2 演示示例

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
#include <graphics.h>
#include <string.h>

/* the names of the line styles supported */
char *lname[] = {
"SOLID_LINE",
"DOTTED_LINE",
"CENTER_LINE",
"DASHED_LINE",
"USERBIT_LINE"
};

int main(void)
{
int gdriver = DETECT, gmode;

int style, midx, midy, userpat;
char stylestr[40];

initgraph(&gdriver, &gmode, "");

midx = getmaxx() / 2;
midy = getmaxy() / 2;

userpat = 1;

for (style=SOLID_LINE; style<=USERBIT_LINE; style++)
{
setlinestyle(style, userpat, 1);

strcpy(stylestr, lname[style]);

line(0, 0, midx-10, midy);

rectangle(100, 100, getmaxx() - 100, getmaxy() - 100);

outtextxy(midx, midy, stylestr);

getch();
cleardevice();
}

closegraph();
return 0;
}

1.3 运行结果

2. setmem

2.1 函数说明

函数声明 函数功能
void *setmem(void *dest, size_t n, int c); 用于将指定内存区域的每个字节都设置为指定的值

参数:

  • dest : 要设置的内存区域的指针
  • n : 要设置的字节数
  • c : 要设置的值

·注意: setmem() 并不是标准 C 函数,而是 POSIX 标准库函数,因此可能并不被所有平台所支持。如果您的编译器或操作系统不支持 setmem() 函数,可以使用标准 C 库函数 memset() 来代替

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
char *str = (char *)malloc(10); // 分配 10 字节的内存空间

// 将 str 中的每个字节都设置为 'A'
setmem(str, 10, 'A');

printf("%s\n", str);

free(str);

return 0;
}

在上面的示例程序中,

  • 我们首先使用 malloc() 函数分配了 10 字节的内存空间,并将其赋值给指针变量 str。
  • 然后,我们使用 setmem() 函数将 str 指向的内存区域的每个字节都设置为 'A'
  • 最后,我们输出 str 的内容并使用 free() 函数释放了分配的内存空间。

3. setmode

3.1 函数说明

函数声明 函数功能
int setmode(int fd, int mode); 它是 Windows 系统下的特定库函数,用于将指定文件的 I/O 模式设置为文本模式或二进制模式

参数:

  • fd : 要设置模式的文件描述符,通常使用 fileno() 函数将文件指针转换为文件描述符
  • mode : 要设置的模式,它可以取以下两个值中的一个:
    • _O_BINARY:二进制模式
    • _O_TEXT:文本模式

注意:Windows 系统中,文本模式和二进制模式之间的区别在于换行符的处理方式。在文本模式下,Windows 将回车符(\r)和换行符(\n)组成的字符序列映射为单个换行符(\n),因此在读取文本文件时可以正确处理换行符。在二进制模式下,Windows 不对回车符和换行符做任何转换,因此在读取文本文件时可能会出现问题。

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <fcntl.h>

int main()
{
int result;
result = setmode(fileno(stdin), O_TEXT);
if (result == -1)
perror("Mode not available\n");
else
printf("Mode successfully switched\n");
return 0;
}

在上面的示例程序中,我们首先使用 setmode() 函数将标准输入流的模式从二进制模式切换到文本模式;如果调用成功,则返回 0,否则返回 -1,并将错误信息存储在全局变量 errno 中。在程序中,我们使用 perror() 函数来输出错误信息。如果调用成功,则输出一条提示信息。

注意: setmode() 函数只适用于 Windows 系统下的 C/C++ 编程,并且不是标准库函数,因此在跨平台编程时应该避免使用它。在 Unix/Linux 系统下,也可以使用 fcntl() 函数来设置文件描述符的模式。

3.3 运行结果

4. setpalette

4.1 函数说明

函数声明 函数功能
void setpalette(int colornum, int color); 设置调色板的颜色

参数:

  • colornum : 要设置的调色板中的颜色数量
  • color : 是一个整数类型的值,用于表示调色板中的颜色。这个参数可以是一个 RGB 值,也可以是一个预定义颜色名称,例如 REDBLUE

4.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 将第 5 种颜色设置为红色
setpalette(5, RED);

// 绘制一条红色的直线
setcolor(5);
line(100, 100, 200, 100);

getch();
closegraph();
return 0;
}

4.3 运行结果

5. setrgbpalette

5.1 函数说明

函数声明 函数功能
void setrgbpalette(int colornum, int red, int green, int blue); 用于设置当前绘图窗口的调色板中某个颜色的 RGB

参数:

  • colornum : 要修改的颜色索引,取值范围为 0~255
  • red、green 和 blue 要设置的 RGB 值,取值范围为 0~255

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

setbkcolor(WHITE);
cleardevice();

// 将第 5 种颜色设置为蓝绿色
setrgbpalette(5, 0, 128, 128);

// 绘制一条蓝绿色的斜线
setcolor(5);
line(100, 100, 200, 200);

getch();
closegraph();
return 0;
}

在上述的这个示例程序中,

  • 我们首先使用 setbkcolor() 函数设置背景颜色为白色,然后清除原有屏幕使前面设置生效。
  • 接着我们使用 setrgbpalette() 函数将第 5 种颜色设置为蓝绿色,并使用 setcolor() 函数将绘图颜色设为索引值 5(即蓝绿色);
  • 最后使用 line() 函数绘制了一条斜线。

5.3 运行结果

6. settextjustify

6.1 函数说明

函数声明 函数功能
void settextjustify(int horiz, int vert); 用于设置文本输出的对齐方式

参数:

  • horiz : 水平对齐方式,可以取以下值:
    • LEFT_TEXT:左对齐
    • CENTER_TEXT:居中对齐
    • RIGHT_TEXT:右对齐
  • vert : 垂直对齐方式,可以取以下值:
    • TOP_TEXT:顶部对齐
    • CENTER_TEXT:居中对齐
    • BOTTOM_TEXT:底部对齐

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 设置文本输出的对齐方式为居中对齐
settextjustify(CENTER_TEXT, CENTER_TEXT);

// 输出一行居中对齐的文本
outtextxy(getmaxx() / 2, getmaxy() / 2, "Hello, world!");

getch();
closegraph();
return 0;
}

在上述的示例程序中,我们使用 settextjustify() 函数将文本输出的对齐方式设置为居中对齐,然后使用 outtextxy() 函数在窗口的中心输出一行文本。

注意: 在使用 settextjustify() 函数设置对齐方式时,必须指定正确的参数值,并且同时考虑水平和垂直方向的对齐方式,否则可能会导致文本输出位置错误。

6.3 运行结果

7. settextstyle

7.1 函数说明

函数声明 函数功能
void settextstyle(int font, int direction, int charsize); 用于设置当前文本输出的字体、方向和大小

参数:

  • font : 要使用的字体编号,可以取以下值:
    • DEFAULT_FONT:默认字体
    • TRIPLEX_FONT:粗体三线字体
    • SMALL_FONT:小号字体
    • SANS_SERIF_FONT:无衬线字体
    • GOTHIC_FONT:哥特式字体
    • SCRIPT_FONT:手写字体
  • direction : 文本输出的方向,可以取以下值:
    • HORIZ_DIR:水平方向(从左到右)
    • VERT_DIR:垂直方向(从下到上)
  • horiz : 水平对齐方式,可以取以下值:
    • DEFAULT_WIDTHDEFAULT_HEIGHT:默认大小
    • TRIPLEX_WIDTHTRIPLEX_HEIGHT:大号尺寸
    • SMALL_WIDTHSMALL_HEIGHT:小号尺寸

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 设置文本输出的字体、方向和大小
settextstyle(TRIPLEX_FONT, HORIZ_DIR, 4);

// 输出一行文本
outtextxy(100, 100, "Hello, world!");

getch();
closegraph();
return 0;
}

在上述的示例程序中,我们使用 settextstyle() 函数将文本输出的字体设置为粗体三线字体、方向设置为水平方向、大小设置为大号尺寸,然后使用 outtextxy() 函数在窗口的指定位置输出一行文本。

注意: 在使用 settextstyle() 函数设置文本样式时,必须指定正确的参数值,并且根据具体需求灵活选择字体、方向和大小,否则可能会导致文本输出不符合预期。

7.3 运行结果

8. settime

8.1 函数说明

函数声明 函数功能
void settime(struct time *timep); 设置当前系统时间
参数:
  • timep : 用于存储当前系统时间的结构体变量

8.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <dos.h>

int main(void)
{
struct time t;

gettime(&t);
printf("The current minute is: %d\n", t.ti_min);
printf("The current hour is: %d\n", t.ti_hour);
printf("The current hundredth of a second is: %d\n", t.ti_hund);
printf("The current second is: %d\n", t.ti_sec);

t.ti_min++;
settime(&t);

return 0;
}

在上述的程序中,

  • 我们首先定义了一个 struct time 类型的变量 t,用于存储当前系统时间。然后使用 gettime() 函数获取当前时间,并将小时、分钟、秒和百分之一秒等信息存储到 t 变量的对应成员变量中。
  • 接着,程序使用 printf() 函数输出了当前的分钟数、小时数、百分之一秒数和秒数。这里使用了 %d 占位符来指定输出整数类型的值。
  • 最后,程序将 t 变量的分钟数加上了 1,然后使用 settime() 函数将修改后的时间写入系统时钟中。

注意 : 这个程序依赖于 DOS 系统提供的日期和时间相关函数,可能无法在其他操作系统或环境下运行。此外,直接修改系统时间可能会对计算机的正常运行产生影响,因此应该谨慎使用。
在现代的 Windows 操作系统中,DOS 环境已经被废弃,因此这个程序可能无法正常工作。如果要获取和修改当前系统时间,可以使用操作系统提供的相关 API 或系统调用接口实现。例如,在 Windows 平台上,可以使用 GetSystemTime()SetSystemTime() 等函数来获取和设置系统时间。

9. setusercharsize

9.1 函数说明

函数声明 函数功能
void setusercharsize(int multx, int dirx, int multy, int diry); 用于设置用户定义的字符大小

参数:

  • multx : 水平放大倍数,取值为正整数
  • dirx : 水平方向,取值为 1-1。当 dirx 的值为 1 时,字符不进行左右翻转;当 dirx 的值为 -1 时,字符进行左右翻转
  • multy : 垂直放大倍数,取值为正整数
  • diry : 垂直方向,取值为 1-1。当 diry 的值为 1 时,字符不进行上下翻转;当 diry 的值为 -1 时,字符进行上下翻转。

9.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 设置字符的大小为水平方向放大 2 倍、垂直方向放大 3 倍
setusercharsize(2, 1, 3, 1);

// 输出一行文本
outtextxy(100, 100, "Hello, world!");

getch();
closegraph();
return 0;
}

在上述这个示例程序中,我们使用 setusercharsize() 函数将当前字符的大小设置为水平方向放大 2 倍、垂直方向放大 3 倍,然后使用 outtextxy() 函数在窗口的指定位置输出一行文本。

注意: 在使用 setusercharsize() 函数设置字符大小时,必须指定正确的参数值,并且考虑到水平和垂直方向的缩放倍数,否则可能会导致字符输出不符合预期。

9.3 运行结果

10. setvbuf

10.1 函数说明

函数声明 函数功能
int setvbuf(FILE *stream, char *buf, int type, unsigned size); 用于设置文件流的缓冲方式

参数:

  • stream : 要设置缓冲方式的文件指针,可以是标准输入流(stdin)、标准输出流(stdout)或标准错误流(stderr),也可以是通过 fopen() 函数打开的文件指针
  • buf : 缓冲区指针,可以是一个已经分配好的缓冲区,也可以是 NULL。如果 buf 参数为 NULL,则 setvbuf() 函数将自动为文件流分配一块缓冲区
  • type : 缓冲类型,可以取以下值:
    • _IONBF:不使用缓冲区,直接从或向设备读写数据
    • _IOLBF:行缓冲,每行数据结束后刷新缓冲区
    • _IOFBF:全缓冲,填满缓冲区后才进行读写操作
  • size: 缓冲区大小,如果 buf 参数不为 NULL,则 size 参数指定了缓冲区大小;如果 buf 参数为 NULL,则 size 参数指定了系统为缓冲区分配的大小。size 参数只对全缓冲方式有效,行缓冲和无缓存方式忽略该参数

10.2 演示示例

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

int main(void)
{
FILE *input, *output;
char bufr[512];

input = fopen("file.in", "r+b");
output = fopen("file.out", "w");

if (setvbuf(input, bufr, _IOFBF, 512) != 0)
printf("failed to set up buffer for input file\n");
else
printf("buffer set up for input file\n");

if (setvbuf(output, NULL, _IOLBF, 132) != 0)
printf("failed to set up buffer for output file\n");
else
printf("buffer set up for output file\n");

fclose(input);
fclose(output);
return 0;
}

在上述的示例程序中,

  • 我们首先定义了两个文件指针变量 inputoutput,分别表示输入文件和输出文件。
  • 然后调用 fopen() 函数打开输入文件和输出文件,并将返回的文件指针保存到对应的变量中。
  • 接着,程序使用 setvbuf() 函数分别为输入文件和输出文件设置缓冲方式。对于输入文件,使用 _IOFBF 缓冲类型和大小为 512 字节的缓冲区;对于输出文件,使用 _IOLBF 缓冲类型和大小为 132 字节的缓冲区(此处 bufr 缓冲区为空指针)。在设置完缓冲方式后,程序根据 setvbuf() 函数的返回值判断是否设置成功,如果返回值不为 0,则说明设置失败,否则说明设置成功,并输出相应的提示信息。
  • 最后,程序使用 fclose() 函数关闭输入文件和输出文件。

注意: 在使用文件流进行读写操作时,必须在适当的时候进行缓冲区清理操作,以避免数据丢失或者读取到过期数据等问题。另外,需要根据具体需求选择合适的缓冲方式和缓冲区大小,以实现最优的性能和稳定性。

10.3 运行结果

11. setviewport

11.1 函数说明

函数声明 函数功能
void setviewport(int left, int top, int right, int bottom, int clipflag); 用于设置绘图窗口的视口范围

参数:

  • left : 视口矩形的左上角横坐标,取值为正整数或 0
  • top: 视口矩形的左上角纵坐标,取值为正整数或 0
  • right: 视口矩形的右下角横坐标,取值为正整数
  • bottom: 视口矩形的右下角纵坐标,取值为正整数
  • clipflag: 裁剪标志,可以取以下值:
    • CLIP_ON:开启裁剪模式,只显示视口内的图形;
    • CLIP_OFF:关闭裁剪模式,显示整个画面。

11.2 演示示例

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

#define CLIP_ON 1

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

setcolor(RED);
rectangle(100, 100, 300, 200);

// 将视口范围设置为矩形 (150, 150) - (250, 250)
setviewport(150, 150, 250, 250, CLIP_ON);

setcolor(GREEN);
rectangle(0, 0, 400, 300);

getch();
closegraph();
return 0;
}

在上面的示例程序中,

  • 我们首先使用 rectangle() 函数绘制了一个红色的矩形;
  • 然后使用 setviewport() 函数将视口范围设置为矩形 (150, 150) - (250, 250);
  • 最后使用 rectangle() 函数绘制了一个绿色的矩形,但这里只有在视口范围的矩形才显示出来。

注意: 在使用 setviewport() 函数设置视口范围时,必须指定正确的参数值,并考虑到裁剪模式的影响,否则可能会导致图形显示不符合预期。

11.3 运行结果

12. setvisualpage

12.1 函数说明

函数声明 函数功能
void setvisualpage(int pagenum); 用于设置图形窗口中用户可见的页面

参数:

  • pagenum : 要设置的可视化页面页码,整数类型。

在双缓冲绘图中,我们通常会使用两个页面来绘制图像,一个是前台页面,另一个是后台页面。当我们绘制完一个完整的画面时,可以通过调用 setactivepage() 函数将后台页面切换到前台页面以显示出来。而 setvisualpage() 函数则用于设置用户当前看到的页面,它实际上是将指定的页面置于前台,从而更新屏幕上显示的内容。

12.2 演示示例

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
#include <graphics.h>

int main(void)
{
int gdriver = EGA, gmode = EGAHI;
int x, y, ht;

initgraph(&gdriver, &gmode, "");

x = getmaxx() / 2;
y = getmaxy() / 2;
ht = textheight("W");

setactivepage(1);

line(0, 0, getmaxx(), getmaxy());

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "This is page #1:");
outtextxy(x, y+ht, "Press any key to halt:");

setactivepage(0);

outtextxy(x, y, "This is page #0.");
outtextxy(x, y+ht, "Press any key to view page #1:");
getch();

setvisualpage(1);

getch();
closegraph();
return 0;
}

上述示例将在屏幕上绘制两个页面,并允许用户通过按任意键查看第二个页面。

注意: setvisualpage() 函数只能用于已经创建的图形窗口,且参数 pagenum 必须在 0getmaxpages() 函数返回值之间。

12.3 运行结果

13. setwritemode

13.1 函数说明

函数声明 函数功能
void setwritemode(int mode); 用于设置绘画操作的写入模式

参数:

  • mode: 要设置的写入模式,整数类型。常用的写入模式有以下三种:
    • COPY_PUT:0,复制模式(默认),新绘制的图形将完全覆盖旧图形
    • XOR_PUT:1,异或模式,新绘制的图形将与旧图形进行异或运算后显示。在这种模式下,如果一个像素既在新图形中出现过,也在旧图形中出现过,则它最终不会被显示出来;如果一个像素只在新图形中出现过,或者只在旧图形中出现过,则它将会被显示出来。
    • OR_PUT:2,或模式,新绘制的图形将与旧图形进行或运算后显示。在这种模式下,如果一个像素既在新图形中出现过,也在旧图形中出现过,则它最终会被显示出来;如果一个像素只在新图形中出现过,或者只在旧图形中出现过,则它将会被显示出来。

13.2 演示示例

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 <graphics.h>

int main()
{
int gdriver = DETECT, gmode;
int xmax, ymax;

initgraph(&gdriver, &gmode, "");

xmax = getmaxx();
ymax = getmaxy();

setwritemode(XOR_PUT);

line(0, 0, xmax, ymax);
getch();

line(0, 0, xmax, ymax);
getch();

setwritemode(COPY_PUT);

line(0, 0, xmax, ymax);

getch();
closegraph();
return 0;
}

注意: setwritemode() 函数只对紧随其后的绘画操作生效,它不会影响之前已经绘制的图形。因此,在更改写入模式之前,必须先完成之前的绘画操作。

13.3 运行结果

14. signal

14.1 函数说明

函数声明 函数功能
void (*signal(int signum, void (*handler)(int)))(int); 用于设置指定信号的处理方式。当系统接收到某个信号时,会调用相应的信号处理函数来处理该信号。在调用 signal 函数时,需要指定要处理的信号以及相应的信号处理函数。

参数:

  • signum : 要设置的信号编号,整数类型。常见的信号有很多种,如:
    • SIGINT(中断信号):通常由用户按下 “Ctrl + C“ 产生,用于中断正在运行的程序。
    • SIGALRM(闹钟信号):用于在指定的时间后向进程发送信号,可以用于实现定时器等功能。
    • SIGFPE(浮点异常信号):在发生浮点运算异常时发送该信号。
    • SIGSEGV(段错误信号):在访问非法的内存地址时发送该信号。
  • handler : 要设置的信号处理函数,是一个指向函数的指针,其形式为 void handler(int)

返回值:

  • 如果调用成功,返回之前对信号的处理方式(通常是一个函数指针)。如果之前没有设置过该信号的处理方式,返回默认的处理方式(通常是 SIG_DFLSIG_IGN)。
  • 如果调用失败,返回 SIG_ERR

14.2 演示示例

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

void sigint_handler(int sig) {
printf("Caught signal %d\n", sig);
exit(0);
}

int main() {
signal(SIGINT, sigint_handler);

while (1) {
printf("Doing something...\n");
getchar();
// check for interrupt signal
raise(SIGINT);
}

return 0;
}

在上面的示例中,

  • 我们首先使用 signal() 函数设置了一个处理 SIGINT 信号的处理程序 sigint_handler()
  • 然后,在主循环中,我们随意输入一个字符后,就使用 raise() 函数向当前正在运行的进程发送 SIGINT 信号。当收到 SIGINT 信号时,程序将打印一条消息并退出。

14.3 运行结果

15. significand,significandf

15.1 函数说明

函数声明 函数功能
double significand(double x); 用于分离浮点数 x 的尾数部分(double)
float significandf(float x); 用于分离浮点数 x 的尾数部分(float)

参数:

  • x : 要求尾数的浮点数。

15.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <math.h>

int main()
{
double x = 123.456789;
float y = -2.5;

printf("The significand of %lf is %lf\n", x, significand(x));
printf("The significand of %f is %f\n", y, significandf(y));

return 0;
}

注意: 在某些旧版本的编译器中,可能没有实现 significand 函数。这个时候可以考虑使用其他类似的函数来替代,如 frexpmodf 等。

16. sin,sinf,sinl

16.1 函数说明

函数声明 函数功能
double sin(double x); 用于计算一个角度(以弧度为单位)的正弦值(double)
float sinf(float x); 用于计算一个角度(以弧度为单位)的正弦值(float)
long double sinl(long double x); 用于计算一个角度(以弧度为单位)的正弦值(long double)

参数:

  • x : 要求正弦值的角度,以弧度为单位

16.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <math.h>

int main()
{
double x = M_PI / 6.0; // M_PI 圆周率
float y = M_PI / 4.0L;
long double z = M_PI / 3.0L;

printf("sin(%lf) = %lf\n", x, sin(x));
printf("sinf(%f) = %f\n", y, sinf(y));
printf("sinl(%Lf) = %Lf\n", z, sinl(z));

return 0;
}

16.3 运行结果

17. sincos,sincosf,sincosl

17.1 函数说明

函数声明 函数功能
void sincos(double x, double* sinVal, double* cosVal); 用于同时计算一个角度(以弧度为单位)的正弦值和余弦值
void sincosf(float x, float* sinVal, float* cosVal); 用于同时计算一个角度(以弧度为单位)的正弦值和余弦值
void sincosl(long double x, long double* sinVal, long double* cosVal); 用于同时计算一个角度(以弧度为单位)的正弦值和余弦值

参数:

  • x : 要求正弦值和余弦值的角度,以弧度为单位
  • sinVal : 存放计算得到的正弦值的指针
  • cosVal : 存放计算得到的余弦值的指针

17.2 演示示例

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

int main()
{
double x = M_PI / 6.0;
float y = M_PI / 4.0L;
long double z = M_PI / 3.0L;

double sinVal, cosVal;
float sinfVal, cosfVal;
long double sinlVal, coslVal;

sincos(x, &sinVal, &cosVal);
sincosf(y, &sinfVal, &cosfVal);
sincosl(z, &sinlVal, &coslVal);

printf("sincos(%lf) = (%lf, %lf)\n", x, sinVal, cosVal);
printf("sincosf(%f) = (%f, %f)\n", y, sinfVal, cosfVal);
printf("sincosl(%Lf) = (%Lf, %Lf)\n", z, sinlVal, coslVal);

return 0;
}

17.3 运行结果

18. sinh,sinhf,sinhl

18.1 函数说明

函数声明 函数功能
double sinh(double x); 用于计算一个数的双曲正弦值
float sinhf(float x); 用于计算一个数的双曲正弦值
long double sinhl(long double x); 用于计算一个数的双曲正弦值

参数:

  • x : 要求双曲正弦值的数,以弧度为单位

18.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <math.h>

int main()
{
double x = 1.0;
float y = 2.0;
long double z = 3.0;

printf("sinh(%lf) = %lf\n", x, sinh(x));
printf("sinhf(%f) = %f\n", y, sinhf(y));
printf("sinhl(%Lf) = %Lf\n", z, sinhl(z));

return 0;
}

18.3 运行结果

总览

函数声明 函数功能
void *sbrk(intptr_t increment); 它是一个 Unix 系统的函数,用于调整程序的堆空间。
double scalb(double x, double n); 计算 x 乘以 2 的 n 次幂(double)
float scalbf(float x, float n); 计算 x 乘以 2 的 n 次幂(float)
long double scalbl(long double x, double n); 计算 x 乘以 2 的 n 次幂(long double)
double scalbln(double x, long int n); 计算 x 乘以 2 的指定长整数 n 次幂(double)
float scalblnf(float x, long int n); 计算 x 乘以 2 的指定长整数 n 次幂(float)
long double scalblnl(long double x, long int n); 计算 x 乘以 2 的指定长整数 n 次幂(long double)
double scalbn(double x, int n); 计算 x 乘以 2 的指定整数 n 次幂(double)
float scalbnf(float x, int n); 计算 x 乘以 2 的指定整数 n 次幂(float)
long double scalbnl(long double x, int n); 计算 x 乘以 2 的指定整数 n 次幂(long double)
int scanf(const char *format, ...); 从标准输入中读取指定格式的数据
void sector( int x, int y, int stangle, int endangle, int xradius, int yradius ); 画并填充椭圆扇区(Windows BGI)
void segread(struct SREGS *sregs); 它是一个 DOS 函数,用于从内存段(segment)中读取内容。
void setactivepage(int pagenum); 用于切换当前显示的页面
void setallpalette(struct palettetype *palette); 用于设置图形界面的整个调色板
void setaspectratio( int xasp, int yasp ); 设置图形纵横比
void setbkcolor(int color); 用于设置当前绘图窗口的背景色
void setbuf(FILE *stream, char *buffer); 用于设置标准输入流、标准输出流或标准错误流的缓冲方式
void setcolor(int color); 设置当前绘图颜色
void setfillpattern(char *upattern, int color); 用于设置当前绘图窗口的填充图案
void setfillstyle(int pattern, int color); 用于设置当前绘图窗口的填充样式,即用什么颜色或图案来填充绘制的图形
void setgraphmode(int mode); 设置当前的图形模式
int setjmp(jmp_buf env); 用于在程序执行过程中设置跳转点,并将当前程序状态保存到一个缓冲区中。当程序需要从该跳转点继续执行时,可以使用 longjmp() 函数恢复之前保存的程序状态并返回到该跳转点。

1. sbrk

1.1 函数说明

函数声明 函数功能
void *sbrk(intptr_t increment); 它是一个 Unix 系统的函数,用于调整程序的堆空间。

参数:

  • increment : 增加的堆空间的大小

返回值:

  • 如果调用成功,返回值即为增加空间前的原始堆顶指针;
  • 如果出错,则返回 (void *)-1

1.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <unistd.h>
#include <stdio.h>

int main() {
void *mem = sbrk(64);

if (mem == (void *)-1) {
perror("sbrk");
return 1;
}

printf("Allocated 64 bytes at address %p\n", mem);

return 0;
}

在上述示例中,

  • 首先调用 sbrk() 函数将堆顶位置向上移动 64 字节;
  • 然后将返回的指针保存在变量 mem 中;如果 sbrk 调用失败(即返回值等于 (void *)-1),则程序通过 perror() 函数输出错误信息并返回 1
  • 最后,程序打印出分配的内存地址,并返回 0 表示程序成功运行。

2. scalb,scalbf,scalbl

2.1 函数说明

函数声明 函数功能
double scalb(double x, double n); 计算 x 乘以 2 的 n 次幂(double)
float scalbf(float x, float n); 计算 x 乘以 2 的 n 次幂(float)
long double scalbl(long double x, double n); 计算 x 乘以 2 的 n 次幂(long double)

注意:如果 n 超过了可表示的范围,或者结果溢出,则函数可能返回正无穷大、负无穷大或 NaN

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <math.h>

int main() {
double x = 3.14159265359;
double y = scalb(x, 10);

printf("Before: %lf\n", x);
printf("After: %lf\n", y);

return 0;
}

3. scalbln,scalblnf,scalblnl

3.1 函数说明

函数声明 函数功能
double scalbln(double x, long int n); 计算 x 乘以 2 的指定长整数 n 次幂(double)
float scalblnf(float x, long int n); 计算 x 乘以 2 的指定长整数 n 次幂(float)
long double scalblnl(long double x, long int n); 计算 x 乘以 2 的指定长整数 n 次幂(long double)

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
#include <math.h>

int main() {
double x = 1.5;
float y = 2.25f;
long double z = 3.75l;
long int n = 3;
// 将x乘以2的3次幂
double result = scalbln(x, n);
printf("scalbln(%lf, %ld) = %lf\n", x, n, result);

float resultf = scalblnf(y, n);
printf("scalblnf(%f, %ld) = %f\n", y, n, resultf);

long double resultL = scalblnl(z, n);
printf("scalblnl(%Lf, %ld) = %Lf", z, n, resultL);

return 0;
}

3.3 运行结果

4. scalbn,scalbnf,scalbnl

4.1 函数说明

函数声明 函数功能
double scalbn(double x, int n); 计算 x 乘以 2 的指定整数 n 次幂(double)
float scalbnf(float x, int n); 计算 x 乘以 2 的指定整数 n 次幂(float)
long double scalbnl(long double x, int n); 计算 x 乘以 2 的指定整数 n 次幂(long double)

4.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>

int main()
{
double x = 3.1415926;
float y = 3.1415926f;
long double z = 3.1415926L;
int n = 5;

printf("scalbn(%lf, %d) = %.20lf\n", x, n, scalbn(x, n));
printf("scalbnf(%f, %d) = %.20f\n", y, n, scalbnf(y, n));
printf("scalbnl(%Lf, %d) = %.20Lf\n", z, n, scalbnl(z, n));

return 0;
}

4.3 运行结果

5. scanf

5.1 函数说明

函数声明 函数功能
int scanf(const char *format, ...); 从标准输入中读取指定格式的数据

详细内容 可参考 《scanf》

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
#include <stdio.h>
#include <math.h>

int main()
{
char name[20];

scanf("%s", name);

printf("Welcome, %s", name);

return 0;
}

在上述示例中,实现了从标准输入中读取一个字符串,并输出欢迎消息。

  • 我们首先定义一个名为 name 的字符数组,长度为 20;
  • 然后使用 scanf() 函数从标准输入中读取一个字符串,存储到 name 数组中;
  • 最后使用 printf() 函数输出欢迎消息,其中 %s 表示字符串格式化符号,会被 name 所代替。

5.3 运行结果

6. sector

6.1 函数说明

函数声明 函数功能
void sector( int x, int y, int stangle, int endangle, int xradius, int yradius ); 画并填充椭圆扇区(Windows BGI)

参数:

  • x : 扇形的圆心坐标的 x 轴
  • y : 扇形的圆心坐标的 y 轴
  • stangle : 起始角度(以度数为单位)
  • endangle : 结束角度(以度数为单位)
  • xradius : 横向半径
  • yradius : 纵向半径

6.2 演示示例

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 <graphics.h>

int main(void)
{
int gdriver = DETECT, gmode;
int midx, midy, i;
int stangle = 45, endangle = 135;
int xrad = 100, yrad = 50;

initgraph(&gdriver, &gmode, "");

midx = getmaxx() / 2;
midy = getmaxy() / 2;

for (i=EMPTY_FILL; i<USER_FILL; i++)
{
setfillstyle(i, getmaxcolor());

sector(midx, midy, stangle, endangle, xrad, yrad);

getch();
}

closegraph();
return 0;
}

6.3 运行结果

7. segread

7.1 函数说明

函数声明 函数功能
void segread(struct SREGS *sregs); 它是一个 DOS 函数,用于从内存段(segment)中读取内容。

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
#include <dos.h>
#include <stdio.h>

int main() {
struct SREGS regs;
segread(&regs); // 读取段寄存器的值
printf("Data segment: %04X\n", regs.ds);
printf("Code segment: %04X\n", regs.cs);
printf("Stack segment: %04X\n", regs.ss);
return 0;
}

上述的这个示例程序,使用了 <dos.h> 头文件中的 segread() 函数和 struct SREGS 结构体,并打印出数据段(DS)、代码段(CS)和堆栈段(SS)的值。

8. setactivepage

8.1 函数说明

函数声明 函数功能
void setactivepage(int pagenum); 用于切换当前显示的页面

8.2 演示示例

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
#include <graphics.h>

int main(void)
{
int gdriver = EGA, gmode = EGAHI;
int x, y, ht;

initgraph(&gdriver, &gmode, "");

x = getmaxx() / 2;
y = getmaxy() / 2;
ht = textheight("W");

setactivepage(1);

line(0, 0, getmaxx(), getmaxy());

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "This is page #1:");
outtextxy(x, y+ht, "Press any key to halt:");

setactivepage(0);

outtextxy(x, y, "This is page #0.");
outtextxy(x, y+ht, "Press any key to view page #1:");
getch();

setvisualpage(1);

getch();
closegraph();
return 0;
}

上述示例将在屏幕上绘制两个页面,并允许用户通过按任意键查看第二个页面。

8.3 运行结果

9. setallpallette

9.1 函数说明

函数声明 函数功能
void setallpalette(struct palettetype *palette); 用于设置图形界面的整个调色板

参数:

  • palette : 调色版结构体

9.2 演示示例

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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>

int main(void)
{
int gdriver = DETECT, gmode;
struct palettetype pal, copypal;
int color, ht;
int y = 10;
char msg[80];

initgraph(&gdriver, &gmode, "");

ht = 2 * textheight("W");

getpalette(&pal);

for (color = 1; color <= MAXCOLORS; color++)
{
sprintf(msg, "old colors[%d]: %d", color, pal.colors[color]);
outtextxy(1, y, msg);
y += ht;
}

for (color = 1; color <= MAXCOLORS; color++)
{
setpalette(color, BLACK);
}

getpalette(&copypal);

getch();

y = 10;
for (color = 1; color <= MAXCOLORS; color++)
{
sprintf(msg, "new colors[%d]: %d", color, copypal.colors[color]);
outtextxy(150, y, msg);
y += ht;
}

getch();
// 重置调色板
setallpalette(&pal);

getpalette(&pal);

y = 10;
for (color = 1; color <= MAXCOLORS; color++)
{
sprintf(msg, "old colors[%d]: %d", color, pal.colors[color]);
outtextxy(300, y, msg);
y += ht;
}

getch();
closegraph();
return 0;
}

9.3 运行结果

10. setaspectratio

10.1 函数说明

函数声明 函数功能
void setaspectratio( int xasp, int yasp ); 设置图形纵横比

参数:

  • xasp : 水平缩放比例
  • yasp : 垂直缩放比例

10.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 设置水平和垂直缩放比例为 2:1
setaspectratio(2, 1);

// 在图形窗口中绘制一个正方形
rectangle(100, 100, 200, 200);

getch();
closegraph();
return 0;
}

注意: 因为 BGI 图形库在 Windows 上的实现是基于 Win32 API 的简单封装,并且没有提供缩放功能,所以上述程序在 Windows BGI 下不支持缩放功能,也就是 setaspectratio 没有效果。

11. setbkcolor

11.1 函数说明

函数声明 函数功能
void setbkcolor(int color); 用于设置当前绘图窗口的背景色

参数:

  • color : 要设置的颜色,预定义颜色有如下:
颜色值 英文枚举 中文描述
0 BLACK
1 BLUE
2 GREEN 绿
3 CYAN
4 RED
5 MAGENTA 洋红
6 BROWN
7 LIGHTGRAY 淡灰
8 DARKGRAY 深灰
9 LIGHTBLUE 淡兰
10 LIGHTGREEN 淡绿
11 LIGHTCYAN 淡青
12 LIGHTRED 淡红
13 LIGHTMAGENTA 淡洋红
14 YELLOW
15 WHITE

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 设置背景色为蓝色
setbkcolor(BLUE);

// 清除先前绘制的图形
cleardevice();

// 在图形窗口中绘制一条线段
line(100, 100, 200, 200);

getch();
closegraph();
return 0;
}

注意: 在修改背景颜色后,需要使用 cleardevice() 函数清除先前绘制的图形并更新背景颜色,不然背景颜色的修改不会生效。

11.3 运行结果

12. setbuf

12.1 函数说明

函数声明 函数功能
void setbuf(FILE *stream, char *buffer); 用于设置标准输入流、标准输出流或标准错误流的缓冲方式

参数:

  • FILE *stream : 目标文件流指针(如 stdin, stdout, stderr 或 fopen() 返回的指针)。必须指向已打开的文件流。
  • char *buffer : 缓冲区指针。
    • 若传递有效缓冲区地址:使用该缓冲区作为流的缓存
    • 若传递 NULL:禁用缓冲

12.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main()
{
FILE *fp;

// 打开文件,并设置为不带缓冲
fp = fopen("test.txt","w");
setbuf(fp, NULL);

// 写入数据到文件中
fprintf(fp, "This is a line of text.");

// 关闭文件
fclose(fp);

return 0;
}

在上述这个示例程序中,我们打开了一个名为 test.txt 的文件,并使用 setbuf() 函数将其设置为不带缓冲。然后,我们向文件中写入一行文本,关闭文件并退出程序。

由于我们已经将文件设置为不带缓冲,因此写入的数据将直接写入磁盘,而不会在内存中留下缓冲区。

12.3 运行结果

13. setcolor

13.1 函数说明

函数声明 函数功能
void setcolor(int color); 设置当前绘图颜色

参数:

  • color : 要设置的颜色,预定义颜色有如下:
颜色值 英文枚举 中文描述
0 BLACK
1 BLUE
2 GREEN 绿
3 CYAN
4 RED
5 MAGENTA 洋红
6 BROWN
7 LIGHTGRAY 淡灰
8 DARKGRAY 深灰
9 LIGHTBLUE 淡兰
10 LIGHTGREEN 淡绿
11 LIGHTCYAN 淡青
12 LIGHTRED 淡红
13 LIGHTMAGENTA 淡洋红
14 YELLOW
15 WHITE

13.2 演示示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

setbkcolor(WHITE);

cleardevice();

// 设置绘画颜色为红色
setcolor(RED);

// 在图形窗口中绘制一条直线
line(100, 100, 200, 200);

getch();
closegraph();
return 0;
}

13.3 运行结果

14. setfillpattern

14.1 函数说明

函数声明 函数功能
void setfillpattern(char *upattern, int color); 用于设置当前绘图窗口的填充图案

参数:

  • upattern : 填充图案
  • color : 填充颜色

在调用 setfillpattern() 函数之前,需要先定义一个名为 upattern 的字符数组,并将其用作填充图案。这个图案通常使用一个 8 字节的字节数组表示,每个元素包含一个 8 比特位的掩码,用于表示该位置是否应该被绘制斜线或其他样式。

14.2 演示示例

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
#include <graphics.h>

int main(void)
{
int gdriver = DETECT, gmode;
int maxx, maxy;

char pattern[8] = {0x00, 0x70, 0x20, 0x27, 0x24, 0x24, 0x07, 0x00};

// 初始化图形模式
initgraph(&gdriver, &gmode, "");

// 获取屏幕的最大 X 和 Y 坐标
maxx = getmaxx();
maxy = getmaxy();

// 设置当前颜色为最大颜色值
setcolor(getmaxcolor());

// 设置填充图案
setfillpattern(pattern, getmaxcolor());

// 用填充图案填满整个窗口
bar(0, 0, maxx, maxy);

// 等待用户按下任意键后关闭窗口
getch();
closegraph();

return 0;
}

上述程序使用了 Windows BGI 图形库来创建一个空白的图形窗口,并在其中填充一种斜线筛子图案。

何为斜线筛子图案,参考如下程序打印:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>

int main() {
char pattern[8] = {0x00, 0x70, 0x20, 0x27, 0x24, 0x24, 0x07, 0x00};

for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (pattern[i] & (1 << (7 - j))) {
printf("*");
} else {
printf(" ");
}
}
printf("\n");
}

return 0;
}

14.3 运行结果

15. setfillstyle

15.1 函数说明

函数声明 函数功能
void setfillstyle(int pattern, int color); 用于设置当前绘图窗口的填充样式,即用什么颜色或图案来填充绘制的图形

参数:

  • pattern : 填充样式
  • color : 填充颜色

如下是支持的填充样式:

填充样式值 英文枚举 中文描述
0 EMPTY_FILL 空填充(无填充)
1 SOLID_FILL 实心填充
2 LINE_FILL 横线填充
3 LTSLASH_FILL 细斜线填充(左斜)
4 SLASH_FILL 粗斜线填充(左斜)
5 BKSLASH_FILL 粗反斜线填充(右斜)
6 LTBKSLASH_FILL 细反斜线填充(右斜)
7 HATCH_FILL 网格阴影填充
8 XHATCH_FILL 交叉网格填充
9 INTERLEAVE_FILL 交错线填充
10 WIDE_DOT_FILL 稀疏点状填充
11 CLOSE_DOT_FILL 密集点状填充
12 USER_FILL 用户自定义填充模式

setfillstyle() 函数还支持使用用户自定义的填充样式。如果要使用用户自定义的填充样式,需要调用 setuserchars() 函数来设置填充字形,然后将填充样式参数设置为 USER_FILL

15.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");

// 设置填充样式为斜线筛子图案,颜色为红色
setfillstyle(SLASH_FILL, RED);

// 在图形窗口中填充一个矩形
rectangle(100, 100, 200, 200);
floodfill(150, 150, getmaxcolor());

getch();
closegraph();
return 0;
}

在上述的示例程序中,

  • 我们首先使用 setfillstyle() 函数将填充样式设置为斜线筛子图案(即 SLASH_FILL 样式),颜色设置为红色。
  • 然后,我们使用 rectangle() 函数在图形窗口中绘制一个矩形,并使用 floodfill() 函数将该矩形填充为红色的斜线筛子图案。
  • 最后按任意键退出图形模式。

15.3 运行结果

16. setgraphmode

16.1 函数说明

函数声明 函数功能
void setgraphmode(int mode); 设置当前的图形模式

16.2 演示示例

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
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int gdriver = DETECT, gmode;
int x, y;

initgraph(&gdriver, &gmode, "");

x = getmaxx() / 2;
y = getmaxy() / 2;

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "Press any key to exit graphics:");
getch();

// 将图形模式恢复到文本模式
restorecrtmode();
printf("We're now in text mode.\n");
printf("Press any key to return to graphics mode:");
getch();

// 返回图形模式
setgraphmode(getgraphmode());

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "We're back in graphics mode.");
outtextxy(x, y+textheight("W"), "Press any key to halt:");

getch();
closegraph();
return 0;
}

16.3 运行结果

17. setjmp

17.1 函数说明

函数声明 函数功能
int setjmp(jmp_buf env); 用于在程序执行过程中设置跳转点,并将当前程序状态保存到一个缓冲区中。当程序需要从该跳转点继续执行时,可以使用 longjmp() 函数恢复之前保存的程序状态并返回到该跳转点。

参数:

  • env : 要保存程序状态的缓冲区,通常声明为 jmp_buf 类型

返回值:
setjmp() 函数返回 0,除非它是从 longjmp() 函数调用返回的,这种情况下,它返回非零值。

17.2 演示示例

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
#include <stdio.h>
#include <setjmp.h>

jmp_buf buf;

void foo()
{
printf("foo() before longjmp()\n");
longjmp(buf, 1);
printf("foo() after longjmp()\n");
}

int main()
{
int ret = setjmp(buf);

if (ret == 0) {
printf("main() before foo()\n");
foo();
} else {
printf("main() after longjmp()\n");
}

return 0;
}

在上述的示例程序中,

  • 我们首先定义了一个名为 bufjmp_buf 类型的缓冲区,并将其作为参数传递给 setjmp() 函数,当前程序状态将保存到 buf 缓冲区中,并返回一个整形,用 ret 变量存储;此时 ret 的值为 0,则说明是第一次调用 setjmp() 函数,主函数内打印输出 ”main() before foo()“
  • 然后我们调用 foo() 函数,打印输出 ”foo() before longjmp()“
  • 接着调用 longjmp() 函数,将会返回到 setjmp() 函数调用的位置,并传递了一个值 1。因为 longjmp() 调用一定会返回 setjmp() 函数调用的位置,因此 foo() 函数的后面一行代码永远不会被执行。
  • 最后 setjmp() 函数返回 ret 的值为 1,则说明是从 longjmp() 函数中返回的,主函数内打印输出 ”main() after longjmp()“

17.3 运行结果

参考

  1. [API Reference Document]

总览

函数声明 函数功能
int raise(int sig); 用于向当前进程发送指定的信号。
int rand(void); 用于生成伪随机数
ssize_t read(int fd, void *buf, size_t count); 用于从文件描述符读取数据的函数。
void *realloc(void *ptr, size_t size); 用于重新分配已经分配过内存的空间大小。
void rectangle( int left, int top, int right, int bottom); 画一个矩形
int registerbgidriver(void(*driver)(void)); 用于将BGI(Borland Graphics Interface)驱动程序注册到系统中
int remove(char *filename); 用于删除指定的文件
int rename(char *oldname, char *newname); 用于重命名或移动文件。
void restorecrtmode(void); 将图形模式恢复到文本模式
void rewind(FILE *stream); 将文件指针 stream 指向的文件位置重置为文件开头,同时清除任何错误或文件结束标志。
int rmdir(const char *path); 用于删除一个空目录,即该目录必须为空。
double round(double x); 将传入的实数参数 x 四舍五入为最接近的整数(double)
float roundf(float x); 将传入的实数参数 x 四舍五入为最接近的整数(float)
long double roundl(long double x); 将传入的实数参数 x 四舍五入为最接近的整数(long double)
double remainder(double x, double y); 用于计算两个浮点数的余数(即模运算结果)(double)
float remainderf (float x, float y ); 用于计算两个浮点数的余数(即模运算结果)(float)
long double remainderl (long double x, long double y); 用于计算两个浮点数的余数(即模运算结果)(long double)
double remquo(double x, double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
float remquof(float x, float y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
long double remquol(long double x, long double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
double rint(double x); 将 x 四舍五入到最接近的整数(double)
float rintf(float x); 将 x 四舍五入到最接近的整数(float)
long double rintl(long double x); 将 x 四舍五入到最接近的整数(long double)

1. raise

1.1 函数说明

函数声明 函数功能
int raise(int sig); 用于向当前进程发送指定的信号。

参数:

  • sig : 指定要发送的信号编号

返回值:

  • 如果调用成功,raise() 函数将返回 0
  • 否则,它将返回一个非零值。

1.2 演示示例

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

void sigint_handler(int sig) {
printf("Caught signal %d\n", sig);
exit(0);
}

int main() {
signal(SIGINT, sigint_handler);

while (1) {
printf("Doing something...\n");
getchar();
// check for interrupt signal
raise(SIGINT);
}

return 0;
}

在上面的示例中,

  • 我们首先使用 signal() 函数设置了一个处理 SIGINT 信号的处理程序 sigint_handler()
  • 然后,在主循环中,我们随意输入一个字符后,就使用 raise() 函数向当前正在运行的进程发送 SIGINT 信号。当收到 SIGINT 信号时,程序将打印一条消息并退出。

注意: raise() 函数只能向当前进程发送信号,不能向其他进程发送信号。如果要向其他进程发送信号,可以使用 kill() 函数。

1.3 运行结果

2. rand

2.1 函数说明

函数声明 函数功能
int rand(void); 用于生成伪随机数

返回值:
每次调用它时会返回一个介于 0RAND_MAX 之间的伪随机整数。其中,RAND_MAX 是一个常量,表示返回值的最大值,通常为 32767

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main() {
// 使用系统时间作为随机数种子初始化
srand(time(NULL));

// 生成并输出 10 个随机数
for (int i = 0; i < 10; i++) {
printf("%d\n", rand());
}

return 0;
}

注意:

  • 每次程序运行时,rand() 函数返回的随机数序列都是相同的。如果要生成不同的随机数序列,可以使用 srand() 函数提供的种子来初始化随机数发生器。
  • 由于 rand() 函数只能生成伪随机数,不能保证其真正的随机性。因此,在需要高度安全性的应用程序中,建议使用更加安全的随机数生成器,如 /dev/random/dev/urandom 等系统提供的硬件随机数生成器。

2.3 运行结果

3. read

3.1 函数说明

函数声明 函数功能
ssize_t read(int fd, void *buf, size_t count); 用于从文件描述符读取数据的函数。

参数:

  • fd : 要读取的文件描述符
  • buf : 存储读取数据的缓冲区
  • count : 要读取的字节数。

3.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <unistd.h>

#define BUFFER_SIZE 1024

int main() {
char buffer[BUFFER_SIZE];
ssize_t num_read;

num_read = read(STDIN_FILENO, buffer, BUFFER_SIZE);
if (num_read == -1) {
perror("read");
return 1;
}

printf("Read %ld bytes from standard input: %.*s", num_read, (int)num_read, buffer);

return 0;
}

在上述的示例中,

  • 我们首先定义了一个大小为 BUFFER_SIZE 的字符数组 buffer
  • 然后使用 read() 函数读取标准输入【STDIN_FILENO 表示标准输入的文件描述符】中的数据到 buffer 中;
  • 最后将读取的结果输出到控制台上。

3.3 运行结果

4. realloc

4.1 函数说明

函数声明 函数功能
void *realloc(void *ptr, size_t size); 用于重新分配已经分配过内存的空间大小。

参数:

  • ptr : 指向已分配内存区域的指针
  • size : 需要分配的新内存大小

返回值:

  • 它会尝试重新调整已经分配给 ptr 指向的内存区域大小,并返回一个指向新内存起始地址的指针。
  • 如果无法分配新的内存,则返回空指针 NULL

注意: realloc() 函数并不保证原有的内存区域内容会被完全保留。当内存大小增加时,可能会分配新的内存并将原有的数据复制到新内存区域中;当内存大小减小时,则可能截断部分原有的数据。因此,在使用 realloc() 函数时,需要注意备份原有的数据,以免出现数据丢失的情况。

4.2 演示示例

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>
#include <stdlib.h>

int main() {
// 分配 10 个整型变量的内存空间
int *p = (int*) malloc(10 * sizeof(int));
if (p == NULL) {
printf("内存分配失败\n");
exit(1);
}

// 更改为 20 个整型变量的内存空间
int *q = (int*) realloc(p, 20 * sizeof(int));
if (q == NULL) {
printf("内存分配失败\n");
exit(1);
}

// 输出新的内存地址
printf("原内存地址:%p,新内存地址:%p\n", p, q);

// 释放新分配的内存空间
free(q);

return 0;
}

在上面的示例中,

  • 我们首先使用 malloc() 函数分配了 10 个整型变量的内存空间,并判断是否分配成功。
  • 接着,我们使用 realloc() 函数将分配的内存空间大小扩充为 20 个整型变量,并判断是否分配成功。
  • 最后,我们输出了原有的内存地址和新的内存地址,并释放了新分配的内存空间。

注意: 在使用 realloc() 函数时,应该始终检查返回值,以确保分配内存空间成功,避免因内存不足或其他原因导致程序崩溃。另外,也应该避免过度使用 realloc() 函数,因为频繁地重新分配内存会影响程序性能。

5. rectangle

5.1 函数说明

函数声明 函数功能
void rectangle( int left, int top, int right, int bottom); 画一个矩形

参数:
left, top, right, bottom,它们分别表示矩形左上角和右下角的坐标。

5.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <graphics.h>

int main(void)
{
int gdriver = DETECT, gmode;
int left, top, right, bottom;

initgraph(&gdriver, &gmode, "");

left = getmaxx() / 2 - 50;
top = getmaxy() / 2 - 50;
right = getmaxx() / 2 + 50;
bottom = getmaxy() / 2 + 50;

rectangle(left,top,right,bottom);

getch();
closegraph();
return 0;
}

5.3 运行结果

6. registerbgidriver

6.1 函数说明

函数声明 函数功能
int registerbgidriver(void(*driver)(void)); 用于将BGI(Borland Graphics Interface)驱动程序注册到系统中

注意:
它必须在使用任何 BGI 图形函数之前调用。该函数接受一个指向驱动程序结构的指针作为参数,并返回一个整数值以指示是否成功注册了驱动程序。BGI 驱动程序主要用于支持 Borland C++IDE 环境下的图形绘制和显示操作,它们通常存储在一个单独的库文件中,例如 graphics.h 头文件需要使用的 BGI driver 位于 libbgi.a 文件中。

6.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
#include <graphics.h>

int main()
{
int gd = DETECT, gm;
initgraph(&gd, &gm, "");
registerbgidriver(EGAVGA_driver); // 注册EGAVGA驱动程序
circle(100, 100, 50); // 绘制圆形
getch(); // 等待用户输入
closegraph(); // 关闭图形界面
return 0;
}

7. remove

7.1 函数说明

函数声明 函数功能
int remove(char *filename); 用于删除指定的文件

参数:

  • filename : 一个指向要删除文件的文件名的字符串指针

返回值:
返回一个整数表示操作是否成功

  • 如果文件成功删除,则返回 0
  • 否则,返回非零值以指示发生错误。

7.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>

int main()
{
int result;
char filename[] = "example.txt";
result = remove(filename);
if (result == 0)
{
printf("The file %s has been removed.\n", filename);
}
else
{
printf("Error deleting the file %s.\n", filename);
}
return 0;
}

7.3 运行结果


8. rename

8.1 函数说明

函数声明 函数功能
int rename(char *oldname, char *newname); 用于重命名或移动文件。

参数:

  • oldname : 指定要更改的文件名
  • newname : 指定新文件名或包含新路径的新文件名

返回值:

  • 在执行成功时,该函数返回 0
  • 否则返回非零值以指示发生错误。

8.2 演示示例

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

int main()
{
char oldname[] = "temp.txt";
char newname[] = "tempnew.txt";
int result;

result = rename(oldname, newname);

if (result == 0)
{
printf("The file has been renamed.\n");
}
else
{
printf("Error renaming the file.\n");
}

return 0;
}

8.3 运行结果

9. restorecrtmode

9.1 函数说明

函数声明 函数功能
void restorecrtmode(void); 将图形模式恢复到文本模式

9.2 演示示例

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
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>

int main(void)
{
int gdriver = DETECT, gmode;
int x, y;

initgraph(&gdriver, &gmode, "");

x = getmaxx() / 2;
y = getmaxy() / 2;

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "Press any key to exit graphics:");
getch();

// 将图形模式恢复到文本模式
restorecrtmode();
printf("We're now in text mode.\n");
printf("Press any key to return to graphics mode:");
getch();

// 返回图形模式
setgraphmode(getgraphmode());

settextjustify(CENTER_TEXT, CENTER_TEXT);
outtextxy(x, y, "We're back in graphics mode.");
outtextxy(x, y+textheight("W"), "Press any key to halt:");

getch();
closegraph();
return 0;
}

9.3 运行结果

10. rewind

10.1 函数说明

函数声明 函数功能
void rewind(FILE *stream); 将文件指针 stream 指向的文件位置重置为文件开头,同时清除任何错误或文件结束标志。

10.2 演示示例

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 <stdio.h>

int main() {
FILE *fp = fopen("tempnew.txt", "r");
if (fp == NULL) {
perror("Failed to open file");
return 1;
}

// 读取文件内容
char buffer[1024];
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}

printf("\n");

// 将文件指针重置到开头
rewind(fp);

// 再次读取文件内容
while (fgets(buffer, sizeof(buffer), fp)) {
printf("%s", buffer);
}

fclose(fp);
return 0;
}

在上述的示例中,

  • 我们首先打开一个名为 tempnew.txt 的文件;
  • 然后使用 fgets() 函数从文件中读取文本行,并输出内容;
  • 接着使用 rewind() 函数将文件指针重置到文件开头,并再次读取文件内容并输出;
  • 最后关闭文件,退出程序。

10.3 运行结果

11. rmdir

11.1 函数说明

函数声明 函数功能
int rmdir(const char *path); 用于删除一个空目录,即该目录必须为空。

参数:

  • path : 待删除的空目录路径

返回值:

  • 如果成功,则返回 0
  • 否则返回 -1,并设置 errno 错误码。

11.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <stdio.h>
#include <stdlib.h>
int main() {
const char *dir_name = "test";
if (mkdir(dir_name) I= 0) {
perror("Failed to create directory");
return 1;
}

//在目录中创建一些文件
FILE *fp1 = fopen("test/file1.txt","w");
FILE *fp2 = fopen("test/file2.txt","w");
fclose(fp1);
fclose(fp2);

//尝试刪除非空目录
if (rmdir(dir name) |= 0) {
perror("Failed to remove directory");
return 1;
}
printf("Directory removed successfullyIn");
return 0;
}

在上述的示例中,

  • 我们首先创建一个名为 test 的目录;
  • 然后在其中创建两个文件 file1.txtfile2.txt
  • 接着使用 rmdir() 函数尝试删除该目录,但会失败,因为该目录不是空的。

注意: 如果要删除非空目录,可以使用上面的 remove() 函数来删除目录及其所有内容。

11.3 运行结果

12. round,roundf,roundl

12.1 函数说明

函数声明 函数功能
double round(double x); 将传入的实数参数 x 四舍五入为最接近的整数(double)
float roundf(float x); 将传入的实数参数 x 四舍五入为最接近的整数(float)
long double roundl(long double x); 将传入的实数参数 x 四舍五入为最接近的整数(long double)

12.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <math.h>
#include <stdio.h>

int main() {
double x = 3.14159265;

double rounded1 = round(x); // 将 x 四舍五入为整数,结果为 3
double rounded2 = round(x * 100) / 100; // 将 x 精确到小数点后两位,结果为 3.14

printf("rounded1: %lf\n", rounded1);
printf("rounded2: %lf\n", rounded2);

float xf = 2.5;
printf("rountf(%f) = %f\n", xf, roundf(xf)); // 将 xf 四舍五入为整数,结果为 3

long double xL = 2.4;
printf("rountl(%Lf) = %Lf", xL, roundl(xL)); // 将 xL 四舍五入为整数,结果为 2
return 0;
}

12.3 运行结果

13. remainder,remainderf,remainderl

13.1 函数说明

函数声明 函数功能
double remainder(double x, double y); 用于计算两个浮点数的余数(即模运算结果)(double)
float remainderf (float x, float y ); 用于计算两个浮点数的余数(即模运算结果)(float)
long double remainderl (long double x, long double y); 用于计算两个浮点数的余数(即模运算结果)(long double)

参数:

  • x : 被除数
  • y : 除数

返回值: x/y 的余数

13.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <stdio.h>
#include <math.h>

int main() {
double x = 10.5, y = 3.2;
printf("remainder(%lf, %lf) = %.20lf\n", x, y, remainder(x, y));


float xf = 10.5f, yf = 3.2f;
printf("remainder(%f, %f) = %.20f\n", xf, yf, remainderf(xf, yf));


long double xL = 10.5L, yL = 3.2L;
printf("remainder(%Lf, %Lf) = %.20Lf\n", xL, yL, remainderl(xL, yL));
return 0;
}

13.3 运行结果

14. remquo,remquof,remquol

14.1 函数说明

函数声明 函数功能
double remquo(double x, double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
float remquof(float x, float y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。
long double remquol(long double x, long double y, int *quo); 用于计算两个浮点数的余数,并返回商和余数。

参数:

  • x : 被除数
  • y : 除数
  • quo : 返回商的指针。如果不需要返回商,则可以传递 NULL

返回值: 返回 x/y 的余数,并通过 quo 指针返回商。

14.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <math.h>

int main() {
int quo;
double x = 10.5, y = 3.2;
double rem = remquo(x, y, &quo);
printf("remquo(%lf, %lf, quo) = %.20lf, quo = %d\n", x, y, rem, quo);

float xf = 10.5f, yf = 3.2f;
float remf = remquof(xf, yf, &quo);
printf("remquof(%f, %f, quo) = %.20f, quo = %d\n", xf, yf, remf, quo);

long double xL = 10.5L, yL = 3.2L;
long double remL = remquol(xL, yL, &quo);
printf("remquol(%Lf, %Lf, quo) = %.20Lf, quo = %d\n", xL, yL, remL, quo);

return 0;
}

14.3 运行结果

15. rint,rintf,rintl

15.1 函数说明

函数声明 函数功能
double rint(double x); 将 x 四舍五入到最接近的整数(double)
float rintf(float x); 将 x 四舍五入到最接近的整数(float)
long double rintl(long double x); 将 x 四舍五入到最接近的整数(long double)

15.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>
#include <math.h>

int main() {
double d = 3.7;
float f = 2.4f;
long double ld = 5.9L;

printf("rint(%f) = %.1f\n", d, rint(d)); // Output: rint(3.700000) = 4.0
printf("rintf(%f) = %.1f\n", f, rintf(f)); // Output: rintf(2.400000) = 2.0
printf("rintl(%Lf) = %.1Lf\n", ld, rintl(ld)); // Output: rintl(5.900000) = 6.0

return 0;
}

15.3 运行结果

参考

  1. [API Reference Document]

总览

函数声明 函数功能
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 用于将指定数组按指定顺序进行排序
void quick_exit(int status); 它是 C11 标准中新增的函数,用于快速退出程序并执行一些清理操作。它类似于 exit() 函数,但不会调用 atexit() 注册的函数,并且不会刷新标准 I/O 流(例如 stdoutstderr)。
int qunsetenv(const char *name); 用于从进程环境中移除指定的环境变量。该函数在某些操作系统上可能不可用,因为它并非标准的 C 语言函数,而是 POSIX 标准中定义的函数。
QuRT相关的函数 详见 4.1 所示

1. qsort

1.1 函数说明

函数声明 函数功能
void qsort(void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *)); 用于将指定数组按指定顺序进行排序
参数:
  • base : 指向要排序的数组的第一个元素的指针
  • nmemb : 表示数组中元素的数量
  • size : 表示每个元素的大小(以字节为单位)
  • compar : 指向一个函数,用于比较两个元素的值。该函数需要接受两个 const void* 类型的参数,分别指向要比较的两个元素,并返回一个整数值,表示它们的相对顺序。

1.2 演示示例

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
#include <stdio.h>
#include <stdlib.h>

int compare(const void* a, const void* b) {
return (*(int*)a - *(int*)b);
}

int main() {
int arr[] = { 5, 2, 8, 4, 1, 9, 3, 6, 7 };
size_t n = sizeof(arr) / sizeof(int);

printf("Before sorting:");
for (int i = 0; i < n; i++) {
printf(" %d", arr[i]);
}
printf("\n");

qsort(arr, n, sizeof(int), compare);

printf("After sorting:");
for (int i = 0; i < n; i++) {
printf(" %d", arr[i]);
}
printf("\n");

return 0;
}

在上述的示例中,

  • 我们首先定义了一个整数数组 arr,并计算出数组的长度,赋值给 n
  • 接着我们输出原始数组 "Before sorting: 5 2 8 4 1 9 3 6 7"
  • 然后我们使用 qsort() 函数将其按照升序排列。qsort() 函数中传入一个比较函数 compare(),用于比较两个元素的值。
  • 最后我们再次输出排序后的结果 ”After sorting: 1 2 3 4 5 6 7 8 9“

注意: 在编写比较函数时,需要根据元素的实际类型进行转换,并确保返回值符合要求(小于零表示第一个元素小于第二个元素,等于零表示两个元素相等,大于零表示第一个元素大于第二个元素)。此外,还需要特别注意参数类型和返回值类型的 const 限定符。

1.3 运行结果

2. quick_exit

2.1 函数说明

函数声明 函数功能
void quick_exit(int status); 它是 C11 标准中新增的函数,用于快速退出程序并执行一些清理操作。它类似于 exit() 函数,但不会调用 atexit() 注册的函数,并且不会刷新标准 I/O 流(例如 stdoutstderr)。
参数:
  • status :程序退出时返回的状态码,0 表示程序正常退出,非零值表示出现了异常情况。

2.2 演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <stdlib.h>

void cleanup() {
printf("Cleaning up...\n");
}

int main() {
if (at_quick_exit(cleanup) != 0) {
fprintf(stderr, "Failed to register cleanup function\n");
exit(EXIT_FAILURE);
}

printf("Running...\n");

quick_exit(EXIT_SUCCESS);
}

在如上的示例中,

  • 我们首先使用 at_quick_exit() 函数注册一个清理函数 cleanup(),当程序使用 quick_exit() 函数退出时,该函数会自动执行。
  • 然后,我们调用 quick_exit() 函数并传入状态码 EXIT_SUCCESS 表示程序正常退出。

注意: 在使用 quick_exit() 函数时需要特别小心,因为它不会调用 atexit() 注册的函数,并且可能导致一些资源泄漏或未完成的操作。只有在必须立即结束程序并执行清理操作时,才应该使用该函数。

3. qunsetenv

3.1 函数说明

函数声明 函数功能
int qunsetenv(const char *name); 用于从进程环境中移除指定的环境变量。该函数在某些操作系统上可能不可用,因为它并非标准的 C 语言函数,而是 POSIX 标准中定义的函数。
参数:
  • name : 要移除的环境变量的名称

返回值:

  • 如果环境变量不存在,则不进行任何操作,并返回 0
  • 否则将其移除,并返回一个非零值。

3.2 演示示例

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

int main() {
// 设置一个环境变量
setenv("MY_VAR", "hello world", 1);

// 移除这个环境变量
if (qunsetenv("MY_VAR") != 0) {
perror("qunsetenv() failed");
exit(EXIT_FAILURE);
}

// 尝试访问这个环境变量
char *val = getenv("MY_VAR");
if (val == NULL) {
printf("Environment variable MY_VAR has been removed.\n");
} else {
printf("Unexpected value: %s\n", val);
}

return EXIT_SUCCESS;
}

在上述这个示例程序中,

  • 我们首先使用 setenv() 函数设置了一个名为 MY_VAR 的环境变量;
  • 然后使用 qunsetenv() 函数移除了这个环境变量;
  • 最后再次尝试访问这个环境变量,如果返回值为 NULL,则说明环境变量已经被成功移除了。

注意: 使用 qunsetenv() 函数可以修改当前进程的环境变量,但是对于其他进程或子进程来说,它们的环境变量不受影响。此外,一些操作系统可能不支持对环境变量进行动态修改,因此无法保证 qunsetenv() 函数在所有平台上都能正常工作。

4. QuRT

4.1 函数说明

函数声明 函数功能
void *qurt_sysenv_getvirtaddr(void *phys_addr, unsigned int size); 将物理地址转换为虚拟地址。
void *qurt_malloc(unsigned int size); 动态分配内存
void *qurt_calloc(unsigned int nmemb, unsigned int size); 动态分配内存,并初始化为零。
void qurt_free(void *ptr); 释放动态分配的内存。
int qurt_thread_create(qurt_thread_t *tid, const qurt_thread_attr_t *attr, void (*start)(void *), void *arg); 创建新线程。
int qurt_thread_join(qurt_thread_t tid, int *status); 等待线程结束并释放其资源。
unsigned int qurt_thread_get_priority(qurt_thread_t thread); 用于获取指定线程的优先级。其中参数 thread 是要获取优先级的线程的句柄。返回一个无符号整数,表示线程的优先级。
void qurt_thread_set_priority(qurt_thread_t thread, unsigned int priority); 用于设置指定线程的优先级。其中参数 thread 是要设置优先级的线程的句柄,而参数 priority 是要设置的优先级值。
char *qurt_thread_get_name(char *name, qurt_thread_t thread); 用于获取指定线程的名称。其中参数 name 是一个指向存储线程名称的缓冲区的指针,而参数 thread 是要获取名称的线程的句柄。返回一个指向缓冲区中存储线程名称的指针。
void qurt_thread_set_name(qurt_thread_t thread, const char *name); 用于设置指定线程的名称。其中参数 thread 是要设置名称的线程的句柄,而参数 name 是要设置的线程名称。
int qurt_thread_stop(qurt_thread_t thread); 用于停止指定线程的执行,即立即终止线程的运行。其中参数 thread 是要停止执行的线程的句柄。返回一个整数值,表示是否成功停止线程。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_thread_resume(qurt_thread_t thread); 用于恢复指定线程的执行,即让线程从上次暂停处继续运行。其中参数 thread 是要恢复执行的线程的句柄。返回一个整数值,表示是否成功恢复线程。如果成功,则返回 0;否则返回一个负数错误代码。
void qurt_mutex_init(qurt_mutex_t *mutex); 用于初始化一个互斥锁,即在使用之前必须进行初始化。其中参数 mutex 是指向要初始化的互斥锁对象的指针。
void qurt_mutex_lock(qurt_mutex_t *mutex); 用于以阻塞方式获取一个互斥锁。如果该互斥锁已被其他线程锁定,则当前线程将一直等待,直到可以获取该锁。其中参数 mutex 是指向要获取的互斥锁对象的指针。
void qurt_mutex_unlock(qurt_mutex_t *mutex); 用于释放一个互斥锁,即解除对该互斥锁的占用。其中参数 mutex 是指向要释放的互斥锁对象的指针。
void qurt_timer_sleep(unsigned int ticks); 用于让当前线程进入休眠状态,休眠时间由参数 ticks 指定(每个 tick 的长度取决于系统时钟频率)。在休眠期间,该线程将不会被调度执行。注意,该函数可能会提前唤醒线程,因此休眠时间并不精确。
void qurt_signal_init(qurt_signal_t *signal); 用于初始化一个信号量,即在使用之前必须进行初始化。其中参数 signal 是指向要初始化的信号量对象的指针。
unsigned int qurt_signal_wait(qurt_signal_t *signal, unsigned int mask, unsigned int option, unsigned int *ret_signal); 用于等待一个或多个信号量的触发。其中参数 signal 是指向要等待的信号量对象的指针,参数 mask 表示要等待哪些信号量,参数 option 用于指定等待的行为选项,参数 ret_signal 用于返回实际触发的信号量。
void qurt_signal_set(qurt_signal_t *signal, unsigned int mask); 用于触发一个或多个信号量。其中参数 signal 是指向要触发的信号量对象的指针,参数 mask 表示要触发哪些信号量。
void qurt_signal2_init(qurt_signal2_t *signal); 用于初始化一个带有两个信号量的信号量对象。其中参数 signal 是指向要初始化的信号量对象的指针。
void qurt_signal2_destroy(qurt_signal2_t *signal); 用于销毁带有两个信号量的信号量对象,并释放其占用的内存空间。其中参数 signal 是要销毁的信号量对象的指针。
void qurt_signal2_set(qurt_signal2_t *signal, unsigned int mask); 用于设置带有两个信号量的信号量对象中的一个或多个信号量。其中参数 signal 是要设置信号量的信号量对象的指针,而参数 mask 是一个 32 位无符号整数,表示要设置的信号量掩码。掩码中每个位代表一个信号量,如果该位为 1,则表示相应的信号量被设置;如果该位为 0,则表示相应的信号量未被设置。
unsigned int qurt_signal2_wait(qurt_signal2_t *signal, unsigned int mask, unsigned int options); 用于等待带有两个信号量的信号量对象中指定的信号量被触发。其中参数 signal 是要等待的信号量对象的指针,而参数 mask 是一个 32 位无符号整数,表示要等待的信号量掩码。掩码中每个位代表一个信号量,如果该位为 1,则表示相应的信号量需要被触发;如果该位为 0,则表示相应的信号量不需要被触发。参数 options 则指定等待信号量的选项,例如是否超时等。它返回一个 32 位无符号整数,表示哪些信号量已被触发。返回值中每个位代表一个信号量,如果该位为 1,则表示相应的信号量已被触发;如果该位为 0,则表示相应的信号量未被触发。
void qurt_timer_create(qurt_timer_t *timer, const char *name); 用于创建一个新的定时器。其中参数 timer 是指向要创建的定时器对象的指针,参数 name 是定时器的名称(可以为 NULL)。
void qurt_timer_delete(qurt_timer_t timer); 用于删除一个已经创建的定时器。其中参数 timer 是要删除的定时器对象。
void qurt_timer_start(qurt_timer_t timer, uint32_t duration); 用于启动一个定时器,并指定定时器的超时时间。其中参数 timer 是要启动的定时器对象,参数 duration 是定时器的超时时间(以 tick 为单位)。
void qurt_timer_stop(qurt_timer_t timer); 用于停止一个已经运行的定时器。其中参数 timer 是要停止的定时器对象。
qurt_thread_t qurt_thread_get_id(void); 用于获取当前线程的 ID
int qurt_mem_region_create(qurt_mem_region_t *region, unsigned int size, qurt_mem_cache_mode_t cache_attrib, qurt_mem_region_type_t type); 用于创建一个内存区域对象,并分配指定大小的内存空间。其中参数 region 是指向要创建的内存区域对象的指针,参数 size 指定内存区域的大小,而 cache_attribtype 分别指定内存区域的缓存属性和类型。返回一个整数值,表示是否成功创建内存区域。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_mem_region_delete(qurt_mem_region_t region); 用于删除指定的内存区域对象,并释放其占用的内存空间。其中参数 region 是要删除的内存区域对象的句柄。返回一个整数值,表示是否成功删除内存区域。如果成功,则返回 0;否则返回一个负数错误代码。
void qurt_mem_region_attr_init(qurt_mem_region_attr_t *attr); 用于初始化一个内存区域属性对象。其中参数 attr 是指向要初始化的内存区域属性对象的指针。
int qurt_mem_pool_create(qurt_mem_pool_t *pool, void *baseaddr, unsigned int size, qurt_mem_cache_mode_t cache_attrib); 用于创建一个内存池对象,并分配指定大小的内存空间。其中参数 pool 是指向要创建的内存池对象的指针,参数 baseaddr 指定内存池的起始地址,而 sizecache_attrib 分别指定内存池的大小和缓存属性。返回一个整数值,表示是否成功创建内存池。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_mem_pool_delete(qurt_mem_pool_t pool); 用于删除指定的内存池对象,并释放其占用的内存空间。其中参数 pool 是要删除的内存池对象的句柄。返回一个整数值,表示是否成功删除内存池。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_create(qurt_pipe_t *pipe, unsigned int pipe_type, unsigned int pipe_elements, unsigned int elem_size); 用于创建一个管道对象,并分配指定大小的内存空间。其中参数 pipe 是指向要创建的管道对象的指针,参数 pipe_type 指定管道类型,参数 pipe_elements 指定管道元素个数,而 elem_size 指定每个管道元素的大小。 返回一个整数值,表示是否成功创建管道。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_delete(qurt_pipe_t pipe); 用于删除指定的管道对象,并释放其占用的内存空间。其中参数 pipe 是要删除的管道对象的句柄。返回一个整数值,表示是否成功删除管道。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_send(qurt_pipe_t pipe_id, void *buf, unsigned int size, unsigned int timeout); 用于向指定的管道发送数据。其中参数 pipe_id 是要发送数据的管道对象的句柄,参数 buf 指向要发送的数据缓冲区,参数 size 指定要发送的数据大小,而 timeout 指定等待发送操作完成的超时时间(单位为 ticks)。 返回一个整数值,表示是否成功发送数据。如果成功,则返回 0;否则返回一个负数错误代码。
int qurt_pipe_receive(qurt_pipe_t pipe_id, void *buf, unsigned int size, unsigned int *recv_size, unsigned int timeout); 用于从指定的管道接收数据。其中参数 pipe_id 是要接收数据的管道对象的句柄,参数 buf 指向接收数据的缓冲区,参数 size 指定要接收的数据大小,而 recv_size 是一个指针,用于返回实际接收到的数据大小。参数 timeout 指定等待接收操作完成的超时时间(单位为 ticks)。返回一个整数值,表示是否成功接收数据。如果成功,则返回 0;否则返回一个负数错误代码。

4.2 演示示例

4.2.1 QuRT 创建线程示例

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>
#include "qurt.h"

void task1(void *arg) {
printf("Task 1 is running...\n");
printf("Task 1 is done.\n");
}

void task2(void *arg) {
printf("Task 2 is running...\n");
printf("Task 2 is done.\n");
}

int main() {
qurt_thread_t t1, t2;
qurt_thread_attr_t attr;

qurt_thread_attr_init(&attr);
qurt_thread_create(&t1, &attr, (void (*)(void *))task1, NULL);
qurt_thread_create(&t2, &attr, (void (*)(void *))task2, NULL);

qurt_thread_join(t1, NULL);
qurt_thread_join(t2, NULL);

return 0;
}

在上述的示例中,我们使用 qurt_thread_create() 函数创建了两个线程,分别执行 task1()task2() 函数,并使用 qurt_thread_join() 函数等待它们结束。
注意: 在开发过程中,需要根据实际情况合理使用内存管理函数和多任务调度函数,并避免出现死锁、资源泄漏等问题。

4.2.2 QuRT 互斥锁示例

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
#include "qurt.h"
#include <stdio.h>

// 共享资源
int global_counter = 0;

// 互斥锁对象
static qurt_mutex_t mutex;

int main() {
// 初始化互斥锁对象
qurt_mutex_init(&mutex);

// 创建两个线程,同时访问共享资源
qurt_thread_t thread1, thread2;
qurt_thread_create(&thread1, NULL, increment_global_counter, NULL);
qurt_thread_create(&thread2, NULL, increment_global_counter, NULL);

// 等待两个线程结束
qurt_thread_join(thread1, NULL);
qurt_thread_join(thread2, NULL);

// 输出最终结果
printf("Global counter: %d\n", global_counter);

return 0;
}

void increment_global_counter(void *arg) {
for (int i = 0; i < 1000000; ++i) {
// 获取互斥锁
qurt_mutex_lock(&mutex);

// 访问共享资源
++global_counter;

// 释放互斥锁
qurt_mutex_unlock(&mutex);
}
}

在上面这个示例程序中,

  • 我们首先使用 qurt_mutex_init() 函数初始化了一个互斥锁对象。
  • 然后创建了两个线程,它们都会调用 increment_global_counter() 函数来增加全局计数器 global_counter 的值。由于多个线程可能同时访问该共享资源,因此在访问之前需要先获取互斥锁,以避免竞争条件的发生。在 increment_global_counter() 函数中,我们使用 qurt_mutex_lock() 函数获取互斥锁,并使用 qurt_mutex_unlock() 函数释放互斥锁。
  • 最后,我们在主函数中输出了最终的计数器值。

4.2.3 QuRT 信号量示例

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
47
48
49
50
51
52
53
#include "qurt.h"
#include <stdio.h>

// 共享资源
int global_counter = 0;

// 信号量对象
static qurt_signal_t sem;

int main() {
// 初始化信号量对象
qurt_signal_init(&sem);

// 创建两个线程,分别增加和减少全局计数器的值
qurt_thread_t thread1, thread2;
qurt_thread_create(&thread1, NULL, increment_global_counter, NULL);
qurt_thread_create(&thread2, NULL, decrement_global_counter, NULL);

// 等待两个线程结束
qurt_thread_join(thread1, NULL);
qurt_thread_join(thread2, NULL);

// 输出最终结果
printf("Global counter: %d\n", global_counter);

return 0;
}

void increment_global_counter(void *arg) {
for (int i = 0; i < 1000000; ++i) {
// 等待信号量
qurt_signal_wait(&sem, 1, QURT_SIGNAL_ATTR_WAIT_ANY, NULL);

// 访问共享资源
++global_counter;

// 触发信号量
qurt_signal_set(&sem, 1);
}
}

void decrement_global_counter(void *arg) {
for (int i = 0; i < 1000000; ++i) {
// 等待信号量
qurt_signal_wait(&sem, 1, QURT_SIGNAL_ATTR_WAIT_ANY, NULL);

// 访问共享资源
--global_counter;

// 触发信号量
qurt_signal_set(&sem, 1);
}
}

在上述的示例程序中,

  • 我们首先使用 qurt_signal_init() 函数初始化了一个信号量对象。
  • 然后创建了两个线程,一个增加全局计数器的值,一个减少全局计数器的值。由于多个线程同时访问该共享资源,因此需要使用信号量进行同步。在每个线程中,我们使用 qurt_signal_wait() 函数等待信号量,当信号量触发时才能访问共享资源,并使用 qurt_signal_set() 函数释放信号量。
  • 接着 使用 qurt_thread_join() 函数等待两个线程结束;
  • 最后输出最终结果。

4.2.4 QuRT 定时器示例

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
#include "qurt.h"
#include <stdio.h>

// 定时器对象
static qurt_timer_t timer;

// 定时器回调函数
void timer_callback(int arg) {
printf("Timer expired\n");
}

int main() {
// 创建定时器对象
qurt_timer_create(&timer, NULL);

// 启动定时器
qurt_timer_start(timer, 1000);

// 注册定时器回调函数
qurt_timer_set_attr(timer, QURT_TIMER_ATTR_CALLBACK_FUNCTION, (void *)timer_callback);
qurt_timer_set_attr(timer, QURT_TIMER_ATTR_CALLBACK_ARGUMENT, (void *)0);

// 等待定时器超时
while (1) {
qurt_timer_sleep(10);
}

// 停止定时器
qurt_timer_stop(timer);

// 删除定时器对象
qurt_timer_delete(timer);

return 0;
}

在上述的示例程序中,

  • 我们首先使用 qurt_timer_create() 函数创建了一个定时器。
  • 然后使用 qurt_timer_start() 函数启动了该定时器,并指定了定时器的超时时间(1000 毫秒)。
  • 接着使用 qurt_timer_set_attr() 函数注册了定时器回调函数。
  • 最后进入一个无限循环,每隔 10 毫秒调用 qurt_timer_sleep() 函数进入休眠状态,等待定时器超时。当定时器超时时,将触发定时器回调函数 timer_callback(),输出一条消息。

注意: 在程序结束时需要使用 qurt_timer_stop() 停止定时器,并使用 qurt_timer_delete() 删除定时器对象。

4.2.5 QuRT 共享内存区域示例

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

#define SHM_SIZE 1024

int main() {
// 创建共享内存区域
qurt_mem_region_t shm;
qurt_mem_region_attr_t attr;
qurt_mem_region_attr_init(&attr);
qurt_mem_region_create(&shm, SHM_SIZE, QURT_MEM_CACHE_NONE, QURT_MEM_REGION_SHARED | QURT_MEM_REGION_PERM_READ | QURT_MEM_REGION_PERM_WRITE);

// 在共享内存区域中写入数据
char *buf = (char *)qurt_mem_region_get_vaddr(&shm);
sprintf(buf, "Hello, shared memory!");

// 打印从共享内存区域中读取的数据
printf("%s\n", buf);

// 删除共享内存区域
qurt_mem_region_delete(shm);

return 0;
}

在上述这个示例程序中,

  • 我们首先使用 qurt_mem_region_create() 函数创建了一个大小为 SHM_SIZE 的共享内存区域,并设置其缓存属性为 QURT_MEM_CACHE_NONE,类型为 QURT_MEM_REGION_SHARED,并且具有读写权限。
  • 然后,在共享内存区域中写入了一些数据,并使用 printf() 函数打印了从共享内存区域中读取的数据。
  • 最后,使用 qurt_mem_region_delete() 函数删除了共享内存区域。

4.2.6 QuRT 使用管道进行进程间通信的示例

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
#include "qurt.h"
#include <stdio.h>

#define PIPE_SIZE 1024

int main() {
// 创建管道
qurt_pipe_t pipe;
qurt_pipe_create(&pipe, QURT_PIPE_ATTR_BLOCKING | QURT_PIPE_ATTR_PIPE_TYPE_BYTE_QUEUE, PIPE_SIZE, 1);

// 创建子进程
qurt_thread_t child;
qurt_thread_create(&child, NULL, child_thread, (void *)&pipe);

// 向管道发送数据
char msg[] = "Hello, pipe!";
qurt_pipe_send(pipe, msg, sizeof(msg), QURT_TIME_WAIT_FOREVER);

// 等待子进程结束
qurt_thread_join(child, NULL);

// 删除管道
qurt_pipe_delete(pipe);

return 0;
}

void child_thread(void *arg) {
// 从管道接收数据
char buf[PIPE_SIZE];
unsigned int recv_size;
qurt_pipe_receive(*(qurt_pipe_t *)arg, buf, PIPE_SIZE, &recv_size, QURT_TIME_WAIT_FOREVER);

// 打印从管道中接收到的数据
printf("%s\n", buf);
}

在上述示例程序中,

  • 我们首先使用 qurt_pipe_create() 函数创建一个大小为 1024 字节的管道对象,属性设置为阻塞式字节队列。
  • 然后我们使用 qurt_thread_create() 函数创建了一个名为 child 的子线程,并将管道对象传递给它。我们在 child_thread() 函数中调用了 qurt_pipe_receive() 函数来从管道接收数据,然后使用 printf() 函数打印出接收到的字符串。
  • 接着我们定义了一个字符串 msg,并使用 qurt_pipe_send() 函数向管道发送该字符串。
  • 最后我们使用 qurt_pipe_delete() 函数删除了管道对象。
0%