C预处理器
预处理器: 就是在程序进行编译之前先做的事情,预处理器可以控制编译的过程,列出要替换的内容、指明要编译的代码行和影响编译器其他方面的行为
注意:预处理器仅仅只是会替换内容,而不会做实际的运算。
#define预处理器指令
首先他由 3 个部分组成
- ‘#define’指令本身
- 选定的缩写(也叫宏)。与变量的命名规则相同
- 替换列表或替换体
#include <stdio.h>
#define TWO 2
#define FOUR TWO * TWO
int main(void)
{
int n;
n = FOUR;
//注意这里并不是4
//FOUR 先变成了了 TWO * TWO
//然后 又替换成 2*2
//之后便结束了,不会对他进行下一步的运算
}
在#define中使用参数
#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目录
条件编译
用于防止重复的创建和包含
- #ifdef、#else 、#\endif指令
#ifdef MAVIS
#include "horse.h" //如果已经用#define定义了MAVIS, 则执行下面的指令
#define STABLES 5
#else
#include "cow.h" //如果没有定义则执行这里
#define STABLES 15
#endif //结束
#ifndef指令 和#ifdef类似,如果是未定义的则执行
#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
/**
* 计算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;
}