版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/admintan/article/details/50619885
《深入探究C语言》系列
c语言 作为一个科班出身的Coder可谓是神奇
一切似乎以他为起点 但多数人不会对他研究很深 和OIer或ACMer不同的是 大多数人太早的转向了面对对象语言也就是所谓的很强大的C# java python objc等等 一般人也不会去从底到顶的实现什么
但是 一些重要的 设计思维 编程思维 甚至编程习惯就这样被遗失了
试想想windows.h 里面的东西你知道多少? 倒不是说他们很重要 但是这样形成了一个空档
即 我们基本功在这种低级直接向高级跨越中丢失了很多 这也就是为什么 ACMer在工作中成长速度一般都超过常人很多
所以这个系列 我们将会从源头 去捡回c语言中
那些遗失的美好
从《深入理解计算机系统》,《操作系统》,《编译原理》这三本书所论述的角度深入理解
什么是编程 ,怎么编程
那么 show time
#include <stdio.h>
#include <math.h>
#include <windows.h>
#include <tchar.h>//微软制定的 ASCII和Unicode转换头文件
/*
如果我们这样写程序:
_TCHAR *RetVal, *szString;
RetVal = _tcsrev(szString);
如果预编译系统定义了宏_UNICODE ,则上述代码被翻译成如下:
wchar_t *RetVal, *szString;
RetVal = _wcsrev(szString);
*/
float f(float x, float y, float z) {
float a = x * x + 9.0f / 4.0f * y * y + z * z - 1;
return a * a * a - x * x * z * z * z - 9.0f / 80.0f * y * y * z * z * z;
}
float h(float x, float z) {
for (float y = 1.0f; y >= 0.0f; y -= 0.001f)
if (f(x, y, z) <= 0.0f)
return y;
return 0.0f;
}
int main() {
HANDLE o = GetStdHandle(STD_OUTPUT_HANDLE);
//将其赋值为GetStdHandle((STD_OUTPUT_HANDLE)),即标准输出的句柄
/*
handle类型实际上是一个整形变量!
windows操作系统==》操作系统(进程调度,内存管理,文件系统,设备管理等等)
进程,文件和内存都有handle,handle作为一个索引让操作系统可以找到这些内核对象,
可以认为是这些内核对象的ID
进程的handle是pid,文件的handle是描述符,内存的handle是地址,外设的handlle。。
*/
_TCHAR buffer[25][80] = { _T(' ') };
/*
char是C语言标准数据类型,字符型,至于由几个字节组成通常由编译器决定,一般一个字节。
Windows为了消除各编译器的差别,重新定义了一些数据类型,你提到了另外几个类型都是这样。
CHAR为单字节字符。还有个WCHAR为Unicode字符,即不论中英文,每个字有两个字节组成。
如果当前编译方式为ANSI(默认)方式,TCHAR等价于CHAR,如果为Unicode方式,
TCHAR等价于WCHAR。LPCSTR 相当于CONST CHAR * 和LPSTR 相当于CHAR *。
*/
_TCHAR ramp[] = _T(".:-=+*#%@");
/*
_T("")是一个宏,他的作用是让你的程序支持Unicode编码
因为Windows使用两种字符集ANSI和UNICODE,
前者就是通常使用的单字节方式,
但这种方式处理象中文这样的双字节字符不方便,
容易出现半个汉字的情况。
而后者是双字节方式,方便处理双字节字符。
*/
for (float t = 0.0f;; t += 0.1f) {
int sy = 0;
float s = sinf(t);//弧度制
float a = s * s * s * s * 0.2f;
for (float z = 1.3f; z > -1.2f; z -= 0.1f)
{
_TCHAR* p = &buffer[sy++][0];
float tz = z * (1.2f - a);
for (float x = -1.5f; x < 1.5f; x += 0.05f)
{
float tx = x * (1.2f + a);
float v = f(tx, 0.0f, tz);
if (v <= 0.0f)
{
float y0 = h(tx, tz);
float ny = 0.01f;
float nx = h(tx + ny, tz) - y0;
float nz = h(tx, tz + ny) - y0;
float nd = 1.0f / sqrtf(nx * nx + ny * ny + nz * nz);
float d = (nx + ny - nz) * nd * 0.5f + 0.5f;
*p++ = ramp[(int)(d * 5.0f)];
}
else
*p++ = ' ';
}
}
for (sy = 0; sy < 25; sy++) {
COORD coord = { 0, sy };
SetConsoleCursorPosition(o, coord);
WriteConsole(o, buffer[sy], 79, NULL, 0);
}
/*
COORD是一个结构体。
typedef struct _COORD {
SHORT X;
SHORT Y;
} COORD;
X:横坐标;
Y:纵坐标。
*/
Sleep(33);//等待,参数表示 等待时间
}
}
可以看到 这和我们日常学习的 c语言 有很大区别 因为 引入了 句柄
而这是我们 日常 学习中 一般不会去接触的类型
那么 这个代码究竟是用来干嘛的呢?
一颗跳动的红心
当然
控制台 我改动过
这是个跳动的心 其中利用了比较复杂的计算 和概念 来确定 在相应坐标上的 点应该是哪个字符
今后的这个系列 将会着眼于一些 c语言的编程技巧和思维 以及一些c语言的妙用
see you~(这么短的博客真的不是来灌水的么哈哈哈)