打印输入中包含特定“模式”或字符串的各行(UNIX程序grep的特例)
#include <stdio.h>
#define MAXLINE 1000 /*输入的最大行长度 */
int getline(char line[],int max);
int strindex(char source[],char searchfor[]);
char pattern[] = "ould"; /*待查找的模式 */
main()
{
char line[MAXLINE];
int found = 0;
while (getline(line, MAXLINE) > 0)
if (strindex(line, pattern) >= 0){
printf("%s", line);
found++;
}
return found;
}
int getline(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && ((c = getchar()) != EOF && c != '\n'))
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
int strindex(char s[], char t[])
{
int i, j, k;
for (i = 0;s[i] != '\0';i++){
for (j = i,k = 0;t[k] != '\0' && s[j] == t[k];j++,k++)
;
if (k > 0 && t[k] == '\0')
return i;
}
return -1;
}
简单的计算器程序:
#include <stdio.h>
#include <ctype.h>
#define MAXLINE 1000
double atof(char s[]); /*把字符串s转换为相应的双精度浮点数*/
int getline(char line[], int max);
main()
{
double sum;
char line[MAXLINE];
sum = 0;
while (getline(line,MAXLINE) > 0)
printf("\t%g\n", sum += atof(line));
return 0;
}
int getline(char s[], int lim)
{
int c, i;
i = 0;
while (--lim > 0 && ((c = getchar()) != EOF && c != '\n'))
s[i++] = c;
if (c == '\n')
s[i++] = c;
s[i] = '\0';
return i;
}
double atof(char s[])
{
double val, power;
int i, sign;
for(i = 0;isspace(s[i]);i++)
;
sign = (s[i] == '-')? -1 : 1;
if(s[i] == '-' || s[i] == '+')
i++;
for (val = 0.0;isdigit(s[i]);i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0;isdigit(s[i]);i++){
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
return sign * val / power;
}
寄存器变量,它所声明的变量在程序中使用的频率较高
register int x;
递归函数实现打印十进制数:
#include <stdio.h>
void printd(int);
main()
{
int n = -999;
printd(n);
getch();
}
void printd(int n)
{
if (n < 0){
putchar('-');
n = -n;
}
if (n / 10)
printd(n / 10);
putchar(n%10 + '0');
}
快速排序算法:对于给定的数组,从中选出一个元素,以该元素为界将其余的元素划分为两个子集,一个子集中的所有元素都小于该元素,另一个子集中的元素都大于或等于该元素。对这两个子集递归这一过程,当某个子集的元素数小于2时,这个子集不再需要递归。
#include <stdio.h>
void qsort(int v[],int left,int right);
void swap(int v[],int i,int j);
main()
{
int i, v[7] = {9,5,6,3,1,4,2};
qsort(v,0,6);
for(i = 0;i <= 6;i++)
printf("%d ",v[i]);
getch();
}
void qsort(int v[],int left,int right)
{
int i, last;
if (left >= right)/*若数组包含的元素数少于2个*/
return; /*不执行任何操作*/
swap(v, left, (left + right) / 2); /*将划分子集的元素*/
last = left; /*移动到v[0]*/
for (i = left + 1;i <= right;i++) /*划分子集*/
if (v[i] < v[left])
swap(v,++last,i);
swap(v,left,last); /*恢复划分子集的元素*/
qsort(v,left,last - 1);
qsort(v,last+1,right);
}
void swap(int v[],int i,int j)
{
int temp;
temp = v[i];
v[i] = v[j];
v[j] = temp;
}
练习4-1 编写函数strrindex返回字符串t在s中最右端出现的位置。
#include <stdio.h>
#include <string.h>
//int strrindex(char s[], char t[]);
main()
{
char pattern[] = "ould";
char s[] = "icouldandwouldfindyou";
printf("%d\n",strrindex(s,pattern));
getch();
}
/*int strrindex(char s[], char t[])
{
int i, j, k, pos;
pos = -1;
for (i = 0;s[i] != '\0';i++){
for (j = i, k = 0;t[k] == s[j] && t[k] != '\0';j++,k++)
;
if (k > 0 && t[k] == '\0')
pos = i;
}
return pos;
} */
int strrindex(char s[], char t[])
{
int i, j, k;
for (i = strlen(s) - strlen(t);i > 0;i--){
for (j = i, k = 0;s[j] == t[k] && t[k] != '\0';j++,k++)
;
if (k > 0 && t[k] == '\0')
return i;
}
return -1;
}
练习4-2 对atof扩充使之能处理科学表示法。
#include <stdio.h>
#include <ctype.h>
double atof(char s[]);
main()
{
char s[] = "123.45e6";
printf("123.45e6 is %e\n",atof(s));
getch();
}
double atof(char s[])
{
double val, power;
int exp, i, sign;
for (i = 0;isspace(s[i]);i++) //skip white space
;
sign = (s[i] == '-') ? -1 : 1;
if (s[i] == '-' || s[i] == '+')
i++;
for (val = 0.0;isdigit(s[i]);i++)
val = 10.0 * val + (s[i] - '0');
if (s[i] == '.')
i++;
for (power = 1.0;isdigit(s[i]);i++){
val = 10.0 * val + (s[i] - '0');
power *= 10.0;
}
val = val * sign / power;
if (s[i] == 'e' || s[i] == 'E'){
sign = (s[++i] == '-') ? -1 : 1;
if (s[i] == '+' || s[i] == '-')
i++;
for (exp = 0;isdigit(s[i]);i++)
exp = 10.0 * exp + (s[i] - '0');
if (sign = 1)
while(exp-- > 0)
val *= 10.0;
else
while (exp-- > 0)
val /= 10.0; /*用val除以10.0而不是乘以0.1是因为0.1无法用二进制精确的表示出来。在大多数机器中,0.1的二进制表示法都比0.1稍微 小一些 */
}
return val;
}
练习4-3加入取模运算
#include <stdio.h>
#include <stdlib.h> /* for atof() */
#include <ctype.h>
#define MAXOP 100 /* max size of operand or operator */
#define NUMBER '0' /* signal that a number was found */
#define MAXVAL 100 /* maximum depth of val stack */
#define BUFSIZE 100
int getop(char []);
void push(double);
double pop(void);
int getch(void);
void ungetch(int);
int sp = 0; /* next free stack position */
double val[MAXVAL]; /* value stack */
char buf[BUFSIZE]; /* buffer for ungetch */
int bufp = 0; /* next free position in buf */
int main(void)
{
int type;
double op2;
char s[MAXOP];
while((type = getop(s)) != EOF)
{
switch(type){
case NUMBER:
push(atof(s));
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2 != 0.0)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
op2 = pop();
if(op2)
push((int)pop()%(int)op2);
else
printf("\nError: Division by zero!");
break;
case '\n':
printf("\t%.8g\n", pop());
break;
default:
printf("error: unknown command %s\n", s);
break;
}
}
return EXIT_SUCCESS;
}
void push(double f)
{
if (sp < MAXVAL)
val[sp++] = f;
else
printf("error: stack full, can't push %g\n", f);
}
/* pop: pop and return top value from stack */
double pop(void)
{
if (sp > 0)
return val[--sp];
else {
printf("error: stack empty\n");
return 0.0;
}
}
int getop(char s[])
{
#define PERIOD '.'
int i = 0;
int c;
int next;
/* Skip whitespace */
while((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
/* Not a number but may contain a unary minus. */
if(!isdigit(c) && c != PERIOD && c != '-')
return c;
if(c == '-') //如果当前读入的c是'-'
{
next = getch(); //判断下一个输入字符next
if(!isdigit(next) && next != PERIOD)
{
return c; //如果next不是数字并且不是小数点,则c为操作符
}
c = next; //否则,既next是数字
}
else
{
c = getch();
}
/*收集整数部分*/
while(isdigit(s[++i] = c)) //则把c保存到数组s[]中
c = getch();
if(c == PERIOD)
/* 收集小数部分*/
while(isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if(c != EOF)
ungetch(c);
return NUMBER;
}
int getch(void) /* get a (possibly pushed-back) character */
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(int c) /* push character back on input */
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
练习4-5 增加sin,cos,exp,pow等操作
#include <stdio.h>
#include <stdlib.h> // for atof()
#include <ctype.h>
#include <math.h>
#include <string.h>
#define MAXOP 100 /* max size of operator */
#define NUMBER '0' /*signal that a number is founded */
#define NAME 'n' /* signal that a name is founded */
#define MAXVAL 100 /* maximum depth of val stack */
#define BUFSIZE 100
int getop(char s[]);
void mathfnc(char s[]);
void push(double);
double pop();
int getch();
void ungetch(int);
int sp; /* top stack position */
double val[MAXVAL];
char buf[BUFSIZE];
double variable[26];
int bufp = 0; /* next buf position */
main()
{
int i, type, var = 0;
double op2, v;
char s[MAXOP];
for (i = 0;i < 26;i++)
variable[i] = 0.0;
while ((type = getop(s)) != EOF){
switch(type){
case NUMBER:
push(atof(s));
break;
case NAME:
mathfnc(s);
break;
case '+':
push(pop() + pop());
break;
case '*':
push(pop() * pop());
break;
case '-':
op2 = pop();
push(pop() - op2);
break;
case '/':
op2 = pop();
if (op2)
push(pop() / op2);
else
printf("error: zero divisor\n");
break;
case '%':
op2 = pop();
if(op2)
push(fmod(pop(),op2));
else
printf("error: zero divisor\n");
break;
case '\n':
if (sp > 0){
v = pop();
printf("\t%.8g\n",v);
}
break;
case '=':
pop();
if (var >= 'A' && var <= 'Z')
variable[var - 'A'] = pop();
break;
default:
if (type >= 'A' && type <= 'Z')
push(variable[type - 'A']);
else if ('v' == type)
push(v);
else
printf("error: unknown command %s\n",s);
break;
}
var = type;
}
return 0;
}
void mathfnc(char s[])
{
double op2;
if (!strcmp(s,"sin"))
push(sin(pop()));
else if (!strcmp(s,"cos"))
push(cos(pop()));
else if (!strcmp(s,"exp"))
push(exp(pop()));
else if (!strcmp(s,"pow")){
op2 = pop();
push(pow(pop(),op2));
}
else
printf("error: %s not support.\n",s);
}
int getop(char s[])
{
int c, i;
while ((s[0] = c = getch()) == ' ' || c == '\t')
;
s[1] = '\0';
i = 0;
if (islower(c)){
while (islower(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c); /* went one char too far */
if (strlen(s) > 1)
return NAME; /* >1 char;it is a NAME */
else
return c; /* it may be a command */
}
if (!isdigit(c) && c != '.' && c != '-')
return c; /* not a number */
if (c == '-')
if (isdigit(c = getch()) || c == '.') /*之前写成c = ‘.’ 造成输入1 2 +\n时出现错误,为什么呢? 以后写成'.' == c就不会出现这样错误 了 */
s[++i] = c; /* negative number */
else{
if (c != EOF)
ungetch(c);
return '-';
}
if (isdigit(c))
while (isdigit(s[++i] = c = getch()))
;
if (c == '.')
while (isdigit(s[++i] = c = getch()))
;
s[i] = '\0';
if (c != EOF)
ungetch(c);
return NUMBER;
}
int getch()
{
return (bufp > 0) ? buf[--bufp] : getchar();
}
void ungetch(char c)
{
if (bufp >= BUFSIZE)
printf("ungetch: too many characters\n");
else
buf[bufp++] = c;
}
void push(double c)
{
if (sp < MAXVAL)
val[sp++] = c;
else
printf("error: stack is full,cann't push %g\n",c);
}
double pop()
{
if (sp > 0)
return val[--sp];
else
printf("error: stack is empty.\n");
return 0.0;
}
练习4-6增加变量处理的命令
见上
练习4-11在getop函数中不使用ungetch函数,而可以使用一个static类型的内部变量解决该问题