1-3 修改温度转换程序,使之能在转换表的顶部打印一个标题。
#include <stdio.h>
/* 当fahr=0, 20, ..., 300时,打印华氏温度与摄氏温度对照表;*/
main()
{
float fahr, celsius;
int lower, upper, step;
lower = 0;
upper = 300;
step = 20;
printf("华氏温度与摄氏温度对照表(0 ~ 300):\n");
fahr = lower;
while (fahr <= upper)
{
celsius = (5.0 / 9.0) * (fahr - 32.0);
printf("%3.0f %6.1f\n", fahr, celsius);
fahr = fahr + step;
}
}
1-4 编写一个程序打印摄氏温度转换为华氏温度的转换表。
#include <stdio.h>
/* 当celsius=-17.8, -6.7, ..., 148.9时,打印摄氏温度与华氏温度对照表*/
main()
{
float celsius, fahr;
float lower, upper, step;
lower = -17.8;
upper = 148.9;
step = 11.1;
printf("摄氏温度与华氏温度对照表(-17.8 ~ 148.9):\n");
celsius = lower;
while (celsius <= upper)
{
fahr = celsius * (9.0 / 5.0) + 32.0;
printf("%5.1f %3.0f\n", celsius, fahr);
celsius = celsius + step;
}
}
1-5 修改温度转换程序,要求以逆序(即按照从3000度到0度的顺序)打印温度转换表
#include <stdio.h>
/* 当fahr=300, 280, ..., 0时,打印华氏温度和摄氏温度对照表 */
main()
{
int fahr;
printf("华氏温度和摄氏温度对照表:(300 ~ 0)\n");
for (fahr = 300; fahr >= 0; fahr = fahr - 20) {
printf("%3d %5.1f\n", fahr, (5.0 / 9.0) * (fahr - 32.0));
}
}
1-6 验证布尔表达式getchar() != EOF的值是0还是1。
#include <stdio.h>
/* 验证表达式getchar() != EOF的值 */
main()
{
printf("%d\n", getchar() != EOF);
}
int getchar(void)
- 功能/返回值 - 读取标准输入流(stdin)中的字符,将该字符当作unsigned char类型并将其转换为 int返回,若遇到错误或文件结束则返回EOF。
- 当用键盘敲入”Ctrl + z/Z”时程序输出0;程序响应其它键盘输入(用回车表示输入的结束)都输出1。
1-7 编写一个打印EOF值的程序
#include <stdio.h>
/* 打印EOF的值 */
main()
{
printf("%d\n", EOF);//-1 windows devc++
}
1-8 编写一个统计空格、字符表与换行符个数的程序。
#include <stdio.h>
int main()
{
int c,nb,nt,nl;
nb=nt=nl= 0;
while ((c = getchar()) != EOF) {
if (c == ' ') {
++nb;
}else if (c == '\t') {
++nt;
}else if (c == '\n') {
++nl;
}
}
printf("空格数\t制表符\t换行符\n%d\t%d\t%d\n", nb, nt,nl);
}
1-9 编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替
#include <stdio.h>
#define NOBLANK 'a'
int main01()
{
int c,lastc;
while((c=getchar())!=EOF)
{
if(c!=' ')//输出非空格字符
putchar(c);
if(c==' ')//处理空格字符
if(lastc !=' ') //检查当前空格字符是一个单个的空格符还是一串空格中的第一个空格
putchar(c)
lastc=c;
}
}
int main02()
{
int c,lastc;
lastc=NONBLANK;
while((c=getchar())!=EOF){
if(c!=' '|| lastc !=' ')
putchar(c);
lastc=c;
}
}
1-10 编写一个将输入复制到输出的程序,并将其中的制表符替换为\t,把回退符替换为\b,把反斜扛替换为\。这样可以将制表符和回退符以可见的方式显示出来。
#include <stdio.h>
int main()
{
int c;
while((c=getchar())!=EOF){
switch(c){
case '\t':printf("\\t");break;
case '\b':printf("\\b");break;
case '\\':printf("\\\\");break;
default:putchar(c);break;
}
}
}
1-11 你准备如何测试单词计数程序?如果程序中存在某种错误,那么什么样的输入可能发现这类错误呢?
#include <stdio.h>
#define IN 1 /* 在单词内 */
#define OUT 0 /* 在单词外 */
/* 统计输入的行数、单词数与字符数 */
int main()
{
int c, nl, nw, nc, state;
state = OUT;
nl = nw = nc = 0;
while ((c = getchar()) != EOF) {
++nc;
if (c == '\n')
++nl;
if (c == ' ' || c == '\n' || c == '\t')
state = OUT;
else if (state == OUT) {
state = IN;
++nw;
}
}
printf("%d %d %d\n", nl, nw, nc);
}
1-12 编写一个程序,以每行一个单词的形式打印其输入。
#include <stdio.h>
#define IN 1 /* 在单词内 */
#define OUT 0 /* 在单词外 */
int main()
{
int c,state;
state=OUT;
while((c=getchar()) !=EOF){
if(c==' '||c=='\n'||c=='\t'){
if(state==IN){
putchar('\n'); //finish the world
state=OUT;
}
}else{
state= IN;
putchar(c);
}
}
}
1-13 编写一个程序,打印输入中单词长度的直方图。水平方向的直方图比较容易绘制,垂直放图则要苦难些。
#include<stdio.h>
#define IN 1 /*inside a word*/
#define OUT 0 /*outside a word*/
#define MAXHIST 15 //max length of histogram
#define MAXWORD 11 //max length of a word
void Printhist()
{
int c,i,nc,state;
int len; //length of each bar
int maxvalue; //maximum value of wl[]
int ovflow; //number of overflow words
int wl[MAXWORD]; //word length counters
state=OUT;
nc=0; //number of chars in a word
ovflow=0; //number of words >=MaxWORD
for(i=0;i<MAXWORD;++i)
wl[i]=0;
while((c=getchar())!=EOF){
if(c==' '||c=='\n'||c=='\t'){
state= OUT;
if(nc>0){
if(nc<MAXWORD)
++wl[nc];
else
++ovflow;
}
nc=0;
}else if(state==OUT){
state=IN;
nc=1; //beginning of a new word
}else{
++nc; //inside a word
}
}
maxvalue =0;
for(i=1;i<MAXWORD;++i){
if(wl[i]>maxvalue)
maxvalue=wl[i];
}
for(i=1;i<MAXWORD;++i){
printf("%5d - %5d : ",i,wl[i]);
if(wl[i]>0){
if((len=wl[i]*MAXHIST/maxvalue) <=0)
len=1;
}else
len=0;
while(len>0){
putchar('*');
--len;
}
putchar('\n');
}
if(ovflow>0)
printf("there are %d words >=%d\n",ovflow,MAXWORD);
}
1-14 编写一个程序,打印输入中各个字符出现频度的直方图。
#include<stdio.h>
#define IN 1 /*inside a word*/
#define OUT 0 /*outside a word*/
#define MAXHIST 15 //max length of histogram
#define MAXWORD 11 //max length of a word
void horizontal()
{
int c,i,j,nc,state;
int maxvalue; //maximum value of wl[]
int ovflow; //number of overflow words
int wl[MAXWORD]; //word length counters
state=OUT;
nc=0; //number of chars in a word
ovflow=0; //number of words >=MaxWORD
for(i=0;i<MAXWORD;++i)
wl[i]=0;
while((c=getchar())!=EOF){
if(c==' '||c=='\n'||c=='\t'){
state= OUT;
if(nc>0){
if(nc<MAXWORD)
++wl[nc];
else
++ovflow;
}
nc=0;
}else if(state==OUT){
state=IN;
nc=1; //beginning of a new word
}else{
++nc; //inside a word
}
}
maxvalue =0;
for(i=1;i<MAXWORD;++i){
if(wl[i]>maxvalue)
maxvalue=wl[i];
}
for(i=MAXHIST;i>0;--i){
for(j=1;j<MAXWORD;++j)
if(wl[j]=MAXHIST/maxvalue>=i)
printf(" * ");
else
printf(" ");
putchar('\n');
}
for(i=1;i<MAXWORD;++i)
printf("%4d ",i);
putchar('\n');
for(i=1;i<MAXWORD;++i)
printf("%4d",wl[i]);
putchar('\n');
if(ovflow>0)
printf("there are %d words >=%d\n",ovflow,MAXWORD);
}
1-16 修改打印最长文本行的程序的主程序main,使之可以打印任意长度的输入行的长度,并尽可能地打印文本。
#include <stdio.h>
#define MAXLINE 1000 /* 允许输入行的最大长度 */
int getline(char line[], int maxline);
void copy(char to[],char from[]);
int main()
{
int len; //当前行长度
int max; //最大长度
char line[MAXLINE]; //当前输入
char longest[MAXLINE];
max = 0;
while ((len = getline(line, MAXLINE)) > 0) {
printf("%d,%s",len, line);
if (len>max) {
max=len;
copy(longest,line);
}
}
if(max>0)
printf("%s", longest);
return 0;
}
int getline(char s[],int lim)
{
int c,i;
for(i=0;i<lim-1 && (c=getchar())!=EOF&&c!='\n';++i)
s[i]=c;
if(c=='\n') {
s[i]=c;
++i;
}
s[i]='\0';
return i;
}
int getline_2(char s[],int lim)
{
int c,i,j;
j=0;
for(i=0;(c=getchar())!=EOF&&c!='\n';++i)
if(i<lim-2){
s[j]=c;
++j;
}
if(c=='\n') {
s[j]=c;
++j;
++i;
}
s[j]='\0';
return i;
}
//copy: copy 'from' into 'to';assume to is bag enough
void copy(char to[],char from[])
{
int i=0;
while((to[i]=from[i]) !='\0'){
i++;
}
}
1-18 编写一个程序,删除每个输入行末尾的空格及制表符,并删除完全是空格的行。
#include <stdio.h>]
#define MAXLINE 1000
int main()
{
char line[MAXLINE];
int n;
while((n=getline(line,MAXLINE))>0){
if(remove(line)>0)
printf("%s %d",line,strlen(line));
}
}
int remove(char s[])
{
int i;
i=0;
while(s[i] !='\n')
++i;
--i;
while(i>=0 && (s[i]== ' '|| s[i]=='\t'))
--i;
if(i>=0){
++i;
s[i]='\n';
++i;
s[i]='\0';
}
return i;
}
1-19 编写函数reverse(s),将字符串s中的字符顺序颠倒过来。使用该函数编写一个程序,每次颠倒一个输入行中的字符顺序。
void reverse(char s[])
{
int i,j;
char temp;
i=0;
while(s[i]!='\0')
++i;
--i; //back off from '\0'
if(s[i]=='\n')
--i;
j=0;
while(j<i)
{
temp=s[j];
s[j]=s[i];
s[i]=temp;
--i;
++j;
}
}
void reverse_1(char s[])
{
int i,j;
char tmp;
i=0;
j=strlen(s)-1;
while(i<=j){
tmp=s[i];
s[i]=s[j];
s[j]=tmp;
j--;
i++;
}
}
1-20 编写detab,将输入中的制表符替换成适当数目的空格,使空格充满到下一个制表符终止位的地方。假设制表符终止位的位置是固定的,比如每个n列就会出现一个制表符终止位。n应该作为变量还是符号常量呢?
void detab()
{
int c,nb,pos;
nb=0;
pos=1;
while((c=getchar())!=EOF){
if(c== '\t'){
nb=TABINC-(pos-1)%TABINC;
while(nb>0){
putchar(' ');
++pos;
--nb;
}
}else if(c=='\n'){
putchar(c);
pos=1;
}else{
putchar(c);
++pos;
}
}
}
1-21 编写entab,将空格串替换为最少数量的制表符和空格,但要保持单词之间的间隔不变。假设制表符终止位置与练习 1-20 的detab程序的情况相同。当使用一个制表符或者一个空格都可以到达下一个制表符终止位时,选用哪一种替换字符比较好?
void entab()
{
int c,nb,nt,pos;
nb=0;
nt=0;
for(pos=1;(c=getchar())!=EOF;++pos)
if(c==' '){ //当前字符串为空字符串
if(pos%TABINC!=0)
++nb;
else{
nb=0;
++nt;
}
}else{
for(;nt>0;--nt)
putchar('\t');
if(c=='\t')
nb=0;
else
for(;nb>0;--nb)
putchar(' ');
putchar(c);
if(c=='\n') //回车,清空数据
pos=0;
else if(c=='\t')
pos=pos+(TABINC-(pos-1)%TABINC)-1;
}
}
1-22 编写一个程序,把较长的输入行“折”成短一些的两行或多行,执行的位置在输入行的第n列之前的最后一个非空格之后。要保证程序能够智能地处理输入行很长以及在指定的列前没有空格或制表符的情况。
//把较长的输入行"拆"成多行
void cline()
{
int c,pos;
pos=0;
while((c=getchar())!=EOF){
line[pos]=c;
if(c=='\t')
pos=exptab(pos);
else if(c=='\n'){ //打印文本
printl(pos);
pos=0;
}else if(++pos>=MAXCOL){
pos=findblnk(pos);
printl(pos);
pos=newpos(pos);
}
}
}
//打印输出0~pos-1之间的字符
void printl(int pos)
{
int i;
for(i=0;i<pos;++i)
putchar(line[i]);
if(pos>0)
putchar('\n');
}
int exptab(int pos)
{
line[pos]=' ';
for(++pos;pos<MAXCOL && pos%TABINC!=0;++pos)
line[pos]=' ';
if(pos<MAXCOL)
return pos;
else{
printl(pos);
return 0;
}
}
//从输入行pos处倒退寻找一个空格
int findblnk(int pos)
{
while(pos>0&&line[pos]!=' ')
--pos;
if(pos==0)
return MAXCOL;
else
return pos+1;
}
//把pos处的字符复制到下一个输出行的开始,返回变量pos的新值
int newpos(int pos)
{
int i,j;
if(pos<0||pos>=MAXCOL)
return 0;
else{
i=0;
for(j=pos;j<MAXCOL;++j){
line[i]=line[j];
++i;
}
return i;
}
}
1-23 编写一个程序删除C语言程序中的所有注释语句。同时要正确处理/识别带引号的字符串与字符常量。在C语言中,注释不允许嵌套
#include <stdio.h>
#define INIT_STATE 0 /* 状态表初始状态 */
#define LINE_COMMENT_STATE 1 /* 在行注释状态 */
#define BLOCK_COMMENT_STATE 2 /* 在块注释状态 */
#define DOUBLE_QUOTE_STATE 3 /* 在双引号状态 */
#define SINGLE_QUOTE_STATE 4 /* 在单引号状态 */
#define TRUE 1
#define FALSE 0
void del_comment();
int main()
{
del_comment();
return 0;
}
void del_comment()
{
int c, nc, con, state;
con = TRUE;
c = nc = 0;
state = INIT_STATE;
while (con && (c = getchar()) != EOF) {
switch (c) {
case '/':
if (state == INIT_STATE) {
if ((nc = getchar()) == EOF) {
putchar(c);
con = FALSE;
break;
}
if (nc == '/')
state = LINE_COMMENT_STATE;
else if (nc == '*')
state = BLOCK_COMMENT_STATE;
else {
putchar(c);
putchar(nc);
}
} else if( state != LINE_COMMENT_STATE &&
state != BLOCK_COMMENT_STATE){
putchar(c);
}
break;
case '\n':
if (state == LINE_COMMENT_STATE) {
state = INIT_STATE;
}
if (state != BLOCK_COMMENT_STATE)
putchar(c);
break;
case '*':
if (state == BLOCK_COMMENT_STATE) {
if((nc = getchar()) == EOF) {
con = FALSE;
break;
}
if (nc == '/') state = INIT_STATE;
} else {
putchar(c);
}
break;
case '\"':
if (state == INIT_STATE) {
state = DOUBLE_QUOTE_STATE;
putchar(c);
} else if (state == DOUBLE_QUOTE_STATE) {
state = INIT_STATE;
putchar(c);
}
break;
case '\'':
if (state == INIT_STATE) {
state = SINGLE_QUOTE_STATE;
putchar(c);
} else if (state == SINGLE_QUOTE_STATE) {
state = INIT_STATE;
putchar(c);
}
break;
default:
if (state != LINE_COMMENT_STATE &&
state != BLOCK_COMMENT_STATE)
putchar(c);
break;
}
}
}