C语言谭浩强第三版第九章例题及课后题:预处理命令

目录

9.1定义一个带参数的宏,使两个参数的值互换

9.2输入两个整数,求它们相除的余数

9.3求三角形面积

9.4(5)判断闰年

9.5分析下面的宏所定义的输出格式

9.6设计输出实数的格式

9.7设计所需的各种各样的输出格式,用头文件包含进去

9.8分别用函数和带参的宏,从3个数中找出最大值

9.9试述“文件包含”和程序文件的连接的概念,二者有何不同?

eg9.7输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输出

9.10用条件编译输入一行电报文字选择输出形式


9.1定义一个带参数的宏,使两个参数的值互换

#include<stdio.h>

#define swap(a,b) tmp = a;  a = b; b = tmp;

void main(void){
	int a;
	int b;
	int tmp;
	
	printf("Please input two integers:");
	scanf("%d%d", &a, &b);
	
	swap(a,b);
	printf("交换后的值为:%d,%d\n", a, b);
} 

9.2输入两个整数,求它们相除的余数

//#define remainder(a,b) a%b       //自己 
#define remainder(a,b) ((a)%(b))   //课本 

//60 13    结果为:8 

#include<stdio.h>

//#define remainder(a,b) a%b       //自己 
#define remainder(a,b) ((a)%(b))   //课本 

void main(void){
	int a;
	int b;
	int tmp;
	
	printf("Please input two integers:");
	scanf("%d%d", &a, &b);
	
	printf("%d和%d相除的余数为:%d\n", a, b, a%b);
} 

9.3求三角形面积

#define  S(a,b,c)     (((a)+(b)+(c))/2.0 )     
//#define  AREA(a,b,c)  sqrt(S*(S-a)*(S-b)*(S-c))    //错误的
#define  AREA(a,b,c)  sqrt(S(a,b,c)*(S(a,b,c)-a)*(S(a,b,c)-b)*(S(a,b,c)-c))

 

要把参数带上,否则是错误的

一般宏定义用大写


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

#define  S(a,b,c)     (((a)+(b)+(c))/2.0 )     
//#define  AREA(a,b,c)  sqrt(S*(S-a)*(S-b)*(S-c))
#define  AREA(a,b,c)  sqrt(S(a,b,c)*(S(a,b,c)-a)*(S(a,b,c)-b)*(S(a,b,c)-c))

/*
//自己有两个失误 1.边长应该用浮点型   2.未考虑三角形的形成条件 
void main(void){
	int a;
	int b;
	int c; 
	
	printf("请输入三角形的三条边:");
	scanf("%d%d%d", &a, &b, &c);
	
	printf("三角形面积为:%d\n", AREA(a,b,c));
} 
*/

void main(void){
	float a;
	float b;
	float c; 
	
	printf("请输入三角形的三条边:");
	scanf("%f%f%f", &a, &b, &c);
	
	if(a+b>c && a+c>b && b+c>a){
		printf("三角形面积为:%.2f\n", AREA(a,b,c));
	}else{
		printf("It's not a triangle.\n");
	}	
}

9.4(5)判断闰年

// 7:10 - 7:15

#include<stdio.h>
#define LEAP_YEAR(y)  (y%400 == 0 || (y%4==0  &&  y%100!=0))

void main(void){
	int year;
	
	printf("请输入一个年份:");
	scanf("%d", &year);
	
	if(LEAP_YEAR(year)){
		printf("%d is a leap year.\n", year);
	}else{
		printf("%d is not a leap year.\n", year);
	}
} 

9.5分析下面的宏所定义的输出格式

对程序中用双撇号括起来的字符串内的字符,即使与宏名相同,也不进行置换。

9.6设计输出实数的格式

#include<stdio.h>

#define  PR  printf
#define  NL  "\n"
#define  Fs  "%f"
#define  F  "%6.2f"
#define  F1  F NL
#define  F2  F"\t"F NL
#define  F3  F"\t"F"\t"F NL

void main(void){
	float a;
	float b;
	float c;
	
	PR("Please input three floating number:\n");
	scanf(Fs, &a);
	scanf(Fs, &b);
	scanf(Fs, &c);
	PR(NL);
	
	PR("output one floating number each line:\n");
	PR(F1, a);
	PR(F1, b);
	PR(F1, c);
	PR(NL);
	
	PR("output two floating number each line:\n");
	PR(F2, a, b);
	PR(F1, c);
	PR(NL);

	PR("output three floating number each line:\n");
	PR(F3, a, b, c);
	PR(NL);
}

9.7设计所需的各种各样的输出格式,用头文件包含进去

//format.h
#define  INTEGER(d)  printf("%d\n", d)
#define  FLOAT(f)  printf("%8.2f\n", f)
#define  STRING(s)  printf("%s\n", s)
#include<stdio.h>
#include"format.h"

void main(void){
	int d;
	float f;
	char s[80];
	int num;
	
	printf("选择数据格式:1-integer, 2-float, 3-string:");
	scanf("%d", &num);
	
	switch(num){
		case 1:
			printf("input integer: ");
			scanf("%d", &d);
			INTEGER(d);
			break;
		case 2:
			printf("input float: ");
			scanf("%f", &f);
			FLOAT(f);
			break;
		case 3:
			printf("input string: ");
			scanf("%s", s);
			STRING(s);
			break;
		default:
			printf("input error.\n");
	}
}

9.8分别用函数和带参的宏,从3个数中找出最大值


/*
#include<stdio.h>

int max(int a, int b, int c);

int max(int a, int b, int c){
	return (a>b ? a:b) > c ? (a>b ? a:b) : c;
}

void main(void){
	int a, b, c;
	
	printf("请输入3个整数:");
	scanf("%d%d%d", &a, &b, &c);
	
	printf("%d、%d和%d中最大的数为:%d\n", a, b, c, max(a, b, c));
}
*/

#include<stdio.h>

//#define MAX  ((a>b)?a:b)
#define MAX(a, b)  ((a>b)?a:b)

void main(void){
	int a, b, c;
	
	printf("请输入3个整数:");
	scanf("%d%d%d", &a, &b, &c);
	
	printf("%d、%d和%d中最大的数为:%d\n", a, b, c, MAX(MAX(a,b), c));	
}

9.9试述“文件包含”和程序文件的连接的概念,二者有何不同?

“文件包含”是事先将程序中需要用到的信息分别存放在不同的“头文件”中(文件后缀为.h),用户在编写程序时,利用#include命令将该头文件的内容包含进来,成为程序中的一部分,特别应当注意的是,该头文件与它所在的源文件共同组成一个文件模块(而不是两个文件模块)。在编译时它是作为一个文件进行编译的。

 

连接(link)则与此不同,它的作用是将多个目标文件连接起来,得到两个或多个目标文件(后缀为.obj),在连接(link)阶段,把这些目标文件与系统提供的函数库等文件连接成一个可执行的文件(后缀为.exe)。

eg9.7输入一行字母字符,根据需要设置条件编译,使之能将字母全改为大写输出,或全改为小写字母输出

一般情况下,源程序中所有行都参加编译。但是有时候希望程序中一部分内容只在满足一定条件时才进行编译,也就是对这一部分内容指定编译的条件,这就是“条件编译”。

 

疑问:不用条件编译命令而直接用if语句也能达到要求,用条件编译命令有什么好处?

的确,对这个问题完全可以不用条件编译处理而用if语句处理,但那样做,目标程序长(因为所有语句都编译),运行时间长(因为在程序运行时对if语句进行测试)。而采用条件编译,可以减少被编译的语句,从而减少目标程序的长度,减少运行时间。当条件编译段比较多时,目标程序长度可以大大减少。

 

#include<stdio.h>
//#define LETTER  1  
//在对条件编译命令进行预处理时,由于LETTER为真,则对第一个if语句进行编译,运行时使小写字母变成大写 
#define LETTER  0
//在对条件编译命令进行预处理时,由于LETTER为假,则对第二个if语句进行编译,运行时使大写字母变成小写

void main(void){
    char str[20] = "C language";
    char c;
    int i = 0;
    
    while((c = str[i]) != '\0'){
        i++;
        #if  LETTER
        if(c >= 'a' && c <= 'z'){
            c = c-32;
        } 
        #else
        if(c >= 'A' && c <= 'Z'){
            c = c+32;
        }
        #endif
        printf("%c", c);
    }
    printf("\n");

#include<stdio.h>
//#define LETTER  1  
//在对条件编译命令进行预处理时,由于LETTER为真,则对第一个if语句进行编译,运行时使小写字母变成大写 
#define LETTER  0
//在对条件编译命令进行预处理时,由于LETTER为假,则对第二个if语句进行编译,运行时使大写字母变成小写

void main(void){
	char str[20] = "C language";
	char c;
	int i = 0;
	
	while((c = str[i]) != '\0'){
		i++;
		#if  LETTER
		if(c >= 'a' && c <= 'z'){
			c = c-32;
		} 
		#else
		if(c >= 'A' && c <= 'Z'){
			c = c+32;
		}
		#endif
		printf("%c", c);
	}
	printf("\n");
} 

9.10用条件编译输入一行电报文字选择输出形式

 

 

#include<stdio.h> 

#define  MAX 80
#define  CHANGE  1

void main(void){
    char str[MAX];
    int i;
    
    printf("Please input text:");
    gets(str);
    
    #if(CHANGE)
    {
        for(i = 0; i < MAX; i++){
            if(str[i] != '\0'){
                if((str[i] >= 'a' && str[i] < 'z') || (str[i] >= 'A' && str[i] < 'Z')){
                    str[i]+=1;
                }else if(str[i] == 'z' || str[i] == 'Z'){
                    str[i]-=25;
                }
            }
        }
    }
    #endif
    printf("output:%s\n", str);
}

比较(这两个很相似):

 

 

 

char str[80];
int i;

for(i = 0; i < strlen(str); i++){
   ......
}

 

char str[20] = "C language";
char c;
int i = 0;
    
while((c = str[i]) != '\0'){

    i++;
     ......
}

 

#include<stdio.h> 

#define  MAX 80
#define  CHANGE  1

void main(void){
	char str[MAX];
	int i;
	
	printf("Please input text:");
	gets(str);
	
	#if(CHANGE)
	{
		for(i = 0; i < MAX; i++){
			if(str[i] != '\0'){
				if((str[i] >= 'a' && str[i] < 'z') || (str[i] >= 'A' && str[i] < 'Z')){
					str[i]+=1;
				}else if(str[i] == 'z' || str[i] == 'Z'){
					str[i]-=25;
				}
			}
		}
	}
	#endif
	printf("output:%s\n", str);
}


 

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

安安csdn

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值