自学C语言--C库···笔记

一、数学库

math.h头文件提供这些函数的原型。

弧度角度转换公式:角度=弧度乘以180/π。

π的值为4*atan(1)。

ANSI C标准的一些数学函数
原型描述与说明
double  acos(double x)返回余弦值为x的角度(0~π)
double  asin(double  x)返回正弦值为x的角度(-π/2~π/2)
double  atan(double  x)返回正切值为x的角度(-π/2~π/2)
double  atan2(double  y,double  x)返回正切值为y/x的角度(-π~π)
double  cos(double  x)返回x的余弦值,x的单位为弧度
double  sin(double  x)返回x的正弦值,x的单位为弧度
double  tan(double  x)返回x的余正切值,x的单位为弧度
double  exp(double  x)返回x的指数函数的值(e^x)
double  log(double  x)返回x的自然对数值
double  log10(double  x)返回x的以10为底的对数值
double  pow(double  x,double  y)返回x的y次幂
double  sqrt(double  x)返回x的平方根
double  cbrt(double  x)返回x的立方根
double  ceil(double  x)返回不小于x的最小整数值
double  fabs(double  x)返回x的绝对值
double  floor(double  x)返回不大于x的最大整数值

 e.g.把直角坐标转化为极坐标

#include <stdio.h>
#include <math.h>

#define RAD_TO_DEG (180/(4 * atan(1)))

typedef struct polar_v {
    double magnitude;
    double angle;
} Polar_V;

typedef struct rect_v {
    double x;
    double y;
} Rect_V;

Polar_V rect_to_polar(Rect_V);

int main(void)
{
    Rect_V input;
    Polar_V result;
    
    puts("Enter x and y coordinates; enter q to quit:");
    while (scanf("%lf %lf", &input.x, &input.y) == 2)
    {
        result = rect_to_polar(input);
        printf("magnitude = %0.2f, angle = %0.2f\n",
               result.magnitude, result.angle);
    }
    puts("Bye.");
    
    return 0;
}

Polar_V rect_to_polar(Rect_V rv)
{
    Polar_V pv;
    
    pv.magnitude = sqrt(rv.x * rv.x + rv.y * rv.y);
    if (pv.magnitude == 0)
        pv.angle = 0.0;
    else
        pv.angle = RAD_TO_DEG * atan2(rv.y, rv.x);
    
    return pv;
}

二、泛型宏

泛型平方根函数

sqrtf()是sqrt()的float版本,sqrtl()是sqrt()的long double版本。

#include <stdio.h>
#include <math.h>
#define RAD_TO_DEG (180/(4 * atanl(1)))

// 泛型平方根函数 
#define SQRT(X) _Generic((X),\
    long double: sqrtl, \
    default: sqrt, \
    float: sqrtf)(X)

// 泛型正弦函数 
#define SIN(X) _Generic((X),\
long double: sinl((X)/RAD_TO_DEG),\
default:     sin((X)/RAD_TO_DEG),\
float:       sinf((X)/RAD_TO_DEG)\
)

int main(void)
{
    float x = 45.0f;
    double xx = 45.0;
    long double xxx =45.0L;
    
    long double y = SQRT(x);
    long double yy= SQRT(xx);
    long double yyy = SQRT(xxx);
    printf("%.17Lf\n", y);   // 匹配 float
    printf("%.17Lf\n", yy);  // 匹配 default
    printf("%.17Lf\n", yyy); // 匹配 long double
    int i = 45;
    yy = SQRT(i);            // 匹配 default
    printf("%.17Lf\n", yy);
    yyy= SIN(xxx);           // 匹配 long double
    printf("%.17Lf\n", yyy);
    
    return 0;
}

三、tgmath.h库(C99)

该库定义了泛型宏。

#include <tgmath.h>

```

  float x=5.0;

 double y;

 y=sqrt(x);   //调用宏,本质上是sqrtf(x)

 y=(sqrt) (x);    //调用函数sqrt(x)

注:如果包含了tgmath.h,要调用sqrt()函数而不是sqrt()宏,可以用圆括号把被调用的函数名括起来。

四、stdlib.h库

qsort()函数

用于快速排序数组的数据对象。

void qsort(void*base,size_t  number,size_t  size,

                   int  (*compar)(const  void *, const  void*));

第一个参数是指针。指向待排序的数组的首元素。即首元素地址,即数组名。

第二个参数是待排序的数量。

第三个参数是指明待排序数组中每个元素的大小。

第四个参数是一个指向函数的指针。确定了比较函数的形式。

e.g.

#include <stdio.h>
#include <stdlib.h>

#define NUM 40
void fillarray(double ar[], int n);
void showarray(const double ar[], int n);
int mycomp(const void * p1, const void * p2);

int main(void)
{
    double vals[NUM];
    fillarray(vals, NUM);
    puts("Random list:");
    showarray(vals, NUM);
    qsort(vals, NUM, sizeof(double), mycomp);
    puts("\nSorted list:");
    showarray(vals, NUM);
    return 0;
}

void fillarray(double ar[], int n)
{
    int index;
    
    for( index = 0; index < n; index++)
        ar[index] = (double)rand()/((double) rand() + 0.1);
}

void showarray(const double ar[], int n)
{
    int index;
    
    for( index = 0; index < n; index++)
    {
        printf("%9.4f ", ar[index]);
        if (index % 6 == 5)
            putchar('\n');
    }
    if (index % 6 != 0)
        putchar('\n');
}

//按从小到大的顺序排序 
int mycomp(const void * p1, const void * p2)
{
    //使用指向double的指针来访问这两个值 
    const double * a1 = (const double *) p1;   //将类型从void*强制转换成double*
    const double * a2 = (const double *) p2;   //将类型从void*强制转换成double*
    
    if (*a1 < *a2)
        return -1;
    else if (*a1 == *a2)
        return 0;
    else
        return 1;
}

五、string.h库中的memcpy()和memmove()

memcpymemmove是两个常用的内存操作函数,它们都用于复制内存区域的内容。

1、memcpy()函数:

函数声明:void *memcpy(void *dest,  const void *src,  size_t  n);

这个函数用于将src指向的内存区域的前n个字节复制到dest指向的内存区域。srcdest之间的内存区域不能重叠。

e.g.

#include <stdio.h>  
#include <string.h>  
  
int main() {  
    char src[] = "Hello, World!";  
    char dest[20];  
  
    memcpy(dest, src, 12);  
    printf("dest: %s\n", dest);  // 输出:dest: Hello, World!  
  
    return 0;  
}

2、memmove()函数

函数声明:void *memmove(void *dest,  const void *src,  size_t  n);

这个函数用于将src指向的内存区域的前n个字节复制到dest指向的内存区域。与memcpy不同的是,srcdest之间的内存区域可以重叠。当重叠发生时,memmove会正确地处理数据,确保原始数据不会被破坏。

e.g.

#include <stdio.h>  
#include <string.h>  
  
int main() {  
    char src[] = "Hello, World!";  
    char dest[20] = "Hello, ";  
  
    memmove(dest + 5, src, 7);  // 将src的内容复制到dest的特定位置,并覆盖dest原有的内容  
    printf("dest: %s\n", dest);  // 输出:dest: Hello, World!  
  
    return 0;  
}

注:在这个例子中,destsrc有重叠的部分。如果我们使用memcpy,那么原始的dest[5:]部分的数据将会被覆盖,导致结果不正确。但是使用memmove,它能够正确地处理这种情况,保证原始数据不会被破坏。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值