-
Lesson 1 - 最简单的C程序
-
Lesson 2 - 打印输出
-
Lesson 3 - 循环打印
-
Lesson 4 - 判断奇偶
-
Lesson 5 - 从1加到100求和
-
Lesson 6 - 乘法表
-
Lesson 7 - 求100以内的最大素数
-
Lesson 8 - 1到100有多少个9
-
Lesson 9 - 整型转字符串
-
Lesson 10 - 约瑟夫环
-
Lesson 11 - 求两个坐标点之间的距离
-
Lesson 12 - 判断机器存储是否小尾端
-
Lesson 13 - 对不起,你的车今天限行
-
Lesson 14 - 判断地图上某点是否有出路
-
Lesson 15 - 统计一个数二进制表示中1的个数
-
Lesson 16 - 字符串拷贝
-
Lesson 17 - 统计单词个数
-
Lesson 18 - 实现 printf
-
Lesson 19 - 命令解释器
-
Lesson 20 - 预处理器实现
-
Lesson 21 - 词法分析器实现
-
Lesson 22 - 猜数游戏
-
Lesson 23 - 五子棋
-
Lesson 24 - 超链接分析器
-
Lesson 25 - cp命令实现
-
Lesson 26 - ELF文件头分析器实现
-
Lesson 27 - 简单流处理器实现和正则表达式
-
Lesson 28 - 数学计算器实现
-
Lesson 29 - 数学计算器实现more命令实现
-
Lesson 30 - sort命令实现
-
Lesson 31 - ls -l命令实现
-
Lesson 32 - Bash项目
-
Lesson 33 - 动态数组实现
-
Lesson 34 - 约瑟夫环问题
-
Lesson 35 - 表达式求值问题
-
Lesson 36 - 广度优先解决迷宫问题
-
Lesson 37 - 词频统计器
-
Lesson 38 - 堆排序问题
-
Lesson 39 - 构造符号表
-
Lesson 40 - MyDictionary项目
-
Lesson 41 - BSearch 实现
-
Lesson 42 - QSort 实现
-
Lesson 43 - 深度优先解决迷宫问题
-
Lesson 44 - KMP 算法实现
-
Lesson 45 - 最长公共子序列(LCS)问题
-
Lesson 46 - Dijkstra 算法
-
Lesson 47 - Huffman Coding 算法
-
Lesson 48 - 地图导航项目
Lesson 18 My printf 实现 printf
#include <stdio.h>
void putchar_hex(char c)
{
const char * hex = "0123456789ABCDEF"; // good
//char hex[] = "0123456789ABCDEF"; bad!
putchar(hex[(c & 0xf0)>>4]);
putchar(hex[(c & 0x0f)>>0]);
//putchar(' ');
}
void putint_hex(int a)
{
putchar_hex( (a>>24) & 0xFF );
putchar_hex( (a>>16) & 0xFF );
putchar_hex( (a>>8) & 0xFF );
putchar_hex( (a>>0) & 0xFF );
}
char * itoa(int num, char * buf)
{
int i = 0;
int len = 0;
do
{
buf[i++] = num % 10 + '0';
num /= 10;
} while (num);
buf[i] = '\0';
len = i;
for (i = 0; i < len/2; i++)
{
char tmp;
tmp = buf[i];
buf[i] = buf[len-i-1];
buf[len-i-1] = tmp;
}
return buf;
}
static int myputs(const char * s)
{
while (*s)
putchar(*s++);
return 0;
}
#if 0
#include <stdarg.h>
#else
typedef int * va_list;
#define va_start(ap, A) (ap = (int *)&(A) + 1)
#define va_arg(ap, T) (*(T *)ap++)
#define va_end(ap) ((void)0)
#endif
static char buf[100];
int myprintf(const char * format, ...)
{
char c;
va_list ap;
va_start(ap, format);
while ((c = *format++) != '\0')
{
switch (c)
{
case '%':
c = *format++;
switch (c)
{
char ch;
char * p;
int a;
case 'c':
ch = va_arg(ap, int);
putchar(ch);
break;
case 's':
p = va_arg(ap, char *);
myputs(p);
break;
case 'x':
a = va_arg(ap, int);
putint_hex(a);
break;
case 'd':
a = va_arg(ap, int);
itoa(a, buf);
myputs(buf);
break;
default:
break;
}
break;
default:
putchar(c);
break;
}
}
return 0;
}
int main(void)
{
myprintf("test: %c, %s, %d, 0x%x\n", 'A', "abcdef", 11, 0x23);
return 0;
}
copy
语法知识点
- printf 的函数原型
- typedef 类型声明的用法
- va_start, va_arg, va_end 3个宏的实现
- switch-case 语句的嵌套用法
- 指针的指针 用法
课堂讨论
- printf 的原型,参数和返回值各是什么?
- 为何用 %c 打印时,传入 my_va_arg 的参数是一个 int 类型?
- 当前栈帧的位置是如何判别的? 它和哪些因素有关?
课后练习
- 请实现一个可变长度参数的 max 函数,可以求出任意多传入参数中的最大值。
例如 max(3, 100, 200, 300) 返回 300; max(6, 10, 20, 30, 40, 50, 60) 返回 60 - 请在 myprintf 的基础上,实现一个 mysprintf 函数。