第16章 C预处理器和C库

C预处理器

预处理器: 就是在程序进行编译之前先做的事情,预处理器可以控制编译的过程,列出要替换的内容、指明要编译的代码行和影响编译器其他方面的行为
注意:预处理器仅仅只是会替换内容,而不会做实际的运算。

#define预处理器指令

首先他由 3 个部分组成

  1. ‘#define’指令本身
  2. 选定的缩写(也叫宏)。与变量的命名规则相同
  3. 替换列表或替换体
image.png
#include <stdio.h>
#define TWO 2
#define FOUR TWO * TWO

int main(void)
{
    int n;
    n = FOUR;  
     //注意这里并不是4
      //FOUR 先变成了了  TWO * TWO
      //然后   又替换成   2*2
      //之后便结束了,不会对他进行下一步的运算
}

在#define中使用参数


image.png
#include <stdio.h>
#define SQUARE(X) X*X
#define PR(X) printf("The result is %d.\n",X)

int main(void)
{
    int x = 5;
    int z;
    z = SQUARE(x);      /**
                            z = square(5);
                            z = 5 * 5;预处理结束下面不是预处理做的事情
                            所以
                            z = 25
                            */
    PR(z);              /***
                            printf("The result is %d.\n",25)
                            */
    z = SQUARE(2);          //
    PR(z);          //
    PR(SQUARE(x + 2));      /*
                                首先变成:
                                    printf("The result is %d.\n",SQUARE(x + 2))
                                    printf("The result is %d.\n", 5 + 2 * 5 + 2)
                                    所以结果是 17;
                                    不是49
                                    他只是替换上去不做运算
                                    */

    PR(100 / SQUARE(2));//25
    PR(SQUARE(++x));//
}

文件包含:#include

两种形式:
1. #include <stdio.h> //查找系统目录
2.#include "mystuff.h" //查找当前工作目录
3.#include "/usr/biff/p.h" //查找/usr/biff目录

条件编译

用于防止重复的创建和包含

  1. #ifdef、#else 、#\endif指令
#ifdef MAVIS
#include "horse.h"      //如果已经用#define定义了MAVIS, 则执行下面的指令
#define STABLES 5       
#else
#include "cow.h"        //如果没有定义则执行这里
#define STABLES 15
#endif                  //结束
  1. #ifndef指令 和#ifdef类似,如果是未定义的则执行

  2. #if和#elif指令

#if defined (IBMPC)     //较新的编译器可以这么写
    #include "ibmpc.h"  //这种方法和#ifdef VAX 一样不过这种写法可以使用elif
#elif defined (VAX)
    #include "vax.h"
#endif                  //结束

编程练习

1

/**
 * 自己定义一个头文件
*/

#ifndef JIHHHH_H_
#define JIHHHH_H_

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

#endif

2

/**
 * 用一个宏‘函数’计算两数的调和平均数
*/

#include "JIHHHH.h"

#define HARMEAN(x, y)   (1 / ((1 / (x) + 1 / (y)) / 2))
 
int main(void)
{
    printf("%lf ", HARMEAN(5.6, 6.3));
    return 0;
}

3

image.png
/**
 * 计算x y。
*/

#include "JIHHHH.h"
#include <math.h>

struct coordinate
{
    float x;
    float y;
    float r;
    float A;
};

struct coordinate count(struct coordinate coor);

int main(void)
{
    struct coordinate coordinates;

    puts("Please Enter:");
    scanf("%f %f", &coordinates.r, &coordinates.A);
    coordinates.A *= 3.14 / 180;
    coordinates = count(coordinates);
    printf("x: %.2f y: %.2f ", coordinates.x, coordinates.y);
}

struct coordinate count(struct coordinate coor)
{
    coor.x = coor.r * cos(coor.A);
    coor.y = coor.r * sin(coor.A);
    return coor;
}

4

/**
*  ANSI 库这样描述colok()函数的特性:
*  #include <time.h>
*  clock_t clock(void);
*  这里,clock_t是定义在time.h中的类型。该函数返回处理器时间,其单位取决于实现(如果
*  处理器时间不可用或无法表示,该函数返回-1)。然而,CLOCKS_PER_SEC(也定义在time.h
*  中)是每秒处理器时间单位的数量。因此,两个clock()返回的值的差值除以 CLOCKS_PER_SEC
*  得到两次调用之间经过的秒数。在进行除法运算之前,把值的类型强制转换成double类型,可以
*  将时间精确到小数点以后。编写一个函数,接受一个double类型的参数表示时间的延迟数,然后
*  在这段时间运行一个循环。编写一个简单的程序测试该函数。
*/

#include "JIHHHH.h"
#include <time.h>

void stop_time(double n);

int main(void)
{
   double num;
   puts("Please enter stop time");
   scanf("%lf", &num);
   stop_time(num);

   return 0;
}

void stop_time(double n)
{
   clock_t start_t;

   start_t = clock();
   while ((n - (double)(clock() - start_t) / CLOCKS_PER_SEC)> 0) ;

   printf("%.2f", n);
}

5

/**
 *  编写一个函数接受这些参数:内含int类型元素的数组名、是数组的大小和一个代表选取次数的
 *  值。该函数从数组中随机选择指定数量的元素,并打印他们。每个元素只能选择一次(模拟抽奖
 *  数字或挑选陪审团成员)。另外,如果你的实现有time()或类似的函数,可在srand()中
 *  使用这个函数的输出来初始化随机数生成器rand()。编写一个简单的程序测试该函数。
*/

#include "JIHHHH.h"
#include <time.h>

void lucky_draw(int st[], int nums, int next);

int main(void)
{
    int st[10];
    for (int i = 0; i < 10; i++)
    {
        st[i] = i + 1;
    }
    srand((unsigned int)time(0));

    lucky_draw(st, 10, 5);
    return 0;
}

void lucky_draw(int st[], int nums, int next)
{
    int temp[10] = {0};
    int i;
    int tem;
    for ( i = 0; i < next;/*i++ 也能这么写*/ )
    {
        tem = rand() % nums;
        if (temp[tem])
        {
            //i--;
            continue;
        }
        temp[tem] = 1;
        printf("%d ", st[tem]);
        i++;//防止重复时依旧++i 最后选的数字少
    }
}

6

/**
 *  修改程序清单16.17,使用struct names元素(在程序清单16.17后面的讨论中定义过),而不是
 *  double类型的数组。使用较少的元素,并用选定的名字显示初始化数组。
*/

#include "JIHHHH.h"
#include <time.h>
#define NUM 40

typedef struct
{
    char first[NUM];
    char last[NUM];
}NAMES;

void fillarray(NAMES pst[], int n);
void showarray(const NAMES pst[], int n);
int mycomp(const void * p1, const void * p2);

int main(void)
{
    NAMES staff[NUM];

    fillarray(staff, NUM);
    puts("Random list:");
    showarray(staff, NUM);
    qsort(staff, NUM, sizeof(NAMES), mycomp);
    puts("\nSorted list:");
    showarray(staff, NUM);
    return 0;
}

void fillarray(NAMES pst[], int n)
{
    int i, j;
    int count;
    srand((unsigned int) time(0));
    for ( i = 0; i < n; i++)
    {
        count = rand() % 10 + 1;
        for ( j = 0; j < count; j++)
        {
            pst[i].first[j] = rand() % 26 + 'a';
            pst[i].last[j] = rand() % 26 + 'a';
        }
        pst[i].first[j] = '\0';     //一定要加不然就不是字符串了。
        pst[i].last[j] = '\0';
    }
}

void showarray(const NAMES pst[], int n)
{
    int i;
    for ( i = 0; i < n; i++)
    {
        printf("%10s %-10s ", pst[i].first, pst[i].last);
        if (i % 5 == 4)
            putchar('\n');
    }
    
}

int mycomp(const void * p1, const void * p2)
{
    const NAMES * ps1 = (const NAMES *) p1;
    const NAMES * ps2 = (const NAMES *) p2;
    int res;
    res = strcmp(ps1->first, ps2->first);
    if (res != 0)
        return res;
    else
        return strcmp(ps1->last, ps2->last);
}

7

/**
 *  new_d_array()函数接受一个int类型的参数和double类型的参数。该函数返回一个指针,
 *  指向由malloc()分配的内存块。int类型的参数指定了动态数组中的元素个数,double类型的
 *  值用于初始化元素(第1个值赋给第1个元素,以此类推)。编写show_array()和new_d_array()
*/

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

void show_array(const double ar[], int n);
double * new_d_array(int n, ...);

int main(void)
{
    double * p1;
    double * p2;

    p1 = new_d_array(5, 1.2, 2.3, 3.4, 4.5, 5.6);
    p2 = new_d_array(4, 100.0, 20.00, 8.08, -1890.0);
    show_array(p1 , 5);
    show_array(p2, 4);
    free(p1);
    free(p2);
}

void show_array(const double ar[], int n)
{
    int i;
    for ( i = 0; i < n; i++)
    {
        printf("%.2lf ", ar[i]);
    }
    printf("\n");
    
}

double * new_d_array(int n, ...)
{
    va_list ap;
    double * p = (double *)malloc(n * sizeof(double));
    int i;

    va_start(ap, n);
    for ( i = 0; i < n; i++)
    {
        p[i] = va_arg(ap, double);
    }
    va_end(ap);

    return p;
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容