C-指针1

C语言是一门很强大的语言,他可以直接操作内存,指针就是他可以操作内存的一种方法。

指针是指对象对应的内存地址,读写指针就等于读写内存。

&操作符,又称为取址操作符,将&放在对象名前面,可以获取该对象的内存地址。

数组事实上就是一个指针,他具有长度属性,事实上,随便的一个数的指针也是数组,长度为1而已。指向数组的指针做加减法时,+i等于指针后移i个元素,-i等于前移i个元素,若是超出了数组的长度,称为出界,会导致未知错误,因为被出界的指针很有可能指向的是一个有什么用的变量,不知不觉给人家改了,当然有可能出问题了。有时候,运行良好的程序不一定就没有毛病,只是没爆发而已,养成良好的代码习惯,可以少犯奇奇怪怪的错误。

指针作为普通函数参数使用时,不需要长度,而作为数组参数使用时,需要定义长度。使用指针作为参数与传递给函数,效率会更高,而且不用受限于函数只能return一个结果,可以使用指针传递好几个结果出来。

写一个求数组中最大值最小值的函数如下:

void _max_min(int *p, int len, int *pmax, int *pmin) {
int _max = p[0], _min = p[0];
for(int i = 1; i<len; i++) {
if(p[i]>_max) {
_max = p[i];
}
if(p[i]<_min) {
_min = p[i];
}
}
*pmax = _max;
*pmin = _min;
}

int main()
{
int arr[4] = { 1,2,3,4 };
int _arr_max = 0,_arr_min = 0;
_max_min(arr, 4, &_arr_max, &_arr_min); //此处结果借由指针参数传递出来,得到两个结果
printf_s(“max is %d \n min is %d \n”,_arr_max,_arr_min);
return 0;
}

指针可以传递多个参数出来,是因为指针传递的是地址,不是值,函数运行时如果是传值,他会复制一份在进行运算,而传递指针就不需要复制,直接访问了指针所指向的地址,所以在值比较占内存的情况下,指针作为参数相对相率更高,而且不存在变量无法变更的情况。

递归

递归的定义是程序调用自身的编程技巧。

一直都没弄懂递归到底是怎么调用自身的,C语言函数学习到了递归这一章也还是一知半解。所以还是用实例来练手,总算明白过来了,事实上递归是以函数return出来的结果作为参数进行多次运算,直到结束条件满足为止,中间有任何的dom都不会有影响的。

写了一个简单的除法如下:

function ts(i){
var $new_td = $(“<li></li>”);
$new_td.html(i).appendTo($(“ul”));
if(i <= 1){
return 0;
}
else{
return ts(i/2);
}
}
ts(800);

写函数时究竟在写什么?

刚刚在知乎看到一个问题,为什么你的前端经验不值钱

作者说了“可用”、“健壮”、“可靠”原则,还有“宽容”, 对需求宽容、对用户宽容、对调用者宽容、对维护者宽容。

说的很有道理,但是作者自己写的那个方法,有一半的概率会死机,因为这个函数有可能死循环。

所以,我就在想,到底我们需要怎样写函数,写函数时究竟是在写什么呢?

可用性:可以执行,能处理异常数据、边界问题、还有扩展等;

可读性:妥当的备注,正确的命名,以及流畅的代码思路等;

优越性:减少循环,减少访问内存的次数,减少dom的操作等。

两个字:思路。上文说的作者的函数会死机,我觉得应该是属于作者忽然短路吧,毕竟这个函数多执行几次后就会触及死机状态。

清晰明了的函数一定是有很棒的思路,很多时候我们由于需求的叙述,不由自主的就会被带偏,走进了需求方的思路,但是他们的思路实际上不是程序员的思路,没关系,多坑坑自然会找到好方法的。

JQ-wap-overlay

终于自己写了第一个插件了,晚上要喝一瓶饮料庆祝一下~

;(function($){
$.fn.extend({
“overlay_show”: function(){
var $_html = $.trim(this.html());
var $overlay = $(“<div class=’overlay’ style=’display: table;’></div>”);
var $overlay_bg = $(“<div class=’overlay-bg’></div>”);
$($_html).clone().appendTo($overlay_bg).css({“display”:”block”});
$overlay_bg.appendTo($overlay);
$overlay.appendTo($(“body”));
if($(“.overlay”).length>1){
return;
}
var $body_scroll_top = $(“body”)[0].scrollTop;
$(“body div:first”).css({
“position”:”fixed”,
“top”:-$body_scroll_top+”px”
});
},
“overlay_close”:function(){
this.closest(“.overlay-wrap-bg”).remove();
this.closest(“.overlay”).remove();
if($(“.overlay”).length>0){
return;
}
var $body_scroll_top = -parseInt($(“body div:first”).css(“top”));
$(“body div:first”).removeAttr(“style”);
$(window).scrollTop($body_scroll_top);
}
})
})(jQuery);

$(“body”).delegate(“[data-toggle=’overlay.show’]”, “click”,function(){
var $target = $($(this).attr(“data-target”));
$target.overlay_show();
return false;
});

$(“body”).delegate(“[data-toggle=’overlay.close’]”, “click”, function() {
var $btn = $(this);
$btn.overlay_close();
return false;
});

$(“body”).delegate(“.overlay-bg div”, “click”, function(e) {
e.stopPropagation();
});

$(“body”).delegate(“.overlay-bg”, “click”, function() {
var $div = $(this);
$div.overlay_close();
return false;
});

这个方法写出来已经很久了,但是一直不会写成插件,使用期间也是一直完善,智能教了让背景固定的方法,超赞。

这个方法在以后使用中肯定也会一直完善,没有完美的方法,只有最合适的方式。

demo

C-state

记得有一位大神说过,程序的最终手段都是使用判断和循环来处理数据。

判断类的有if else switch case

循环类的就是 for while 和 do while

if else 和 switch case 效率差不多,不过switch case对于多个判断条件来说,看起来要明显点,代码可读性更强。

for while 是一个频道的,一般来说,使用for的时候会把结束条件和变量条件一起提到括号里,使人一目了然。而使用while的情况则是相反,更加的注重开始条件,而不是结束条件。do while 是执行语句在前,执行条件在后,不管条件合适不合适,执行了再说。

循环内部也有打断循环的方法,一个是continue,一个是break。

continue是打断此次循环,条件如果没有达到,还会继续循环。而break是不管结束条件有没有达到,都会打断整个循环。

C-expr

表达式是可以放在等号右边的,称为右值,而事实上赋值运算本身也是一个右值。

真假的判断只有2个值,非0和0。

if ? true : false  三目运算内在逻辑就是个if判断。

使用多种表达式时,最好使用小括号分清楚内在层级关系,毕竟代码写出来有时候还是需要别人维护的。

C语言里面表达式可能会出现类型转换,不注意的话可能会丢失数据,比如6/8这样的结果会是0……,用书上的逻辑来说,是int的盒子比double的盒子矮一层,它没有放小数点的楼层,就丢失了,此时需要显性的(double)6/8出来。

C-string

字符分为4种: 字母;数字;标点;控制符。它的存储是一个二进制的数,这个二进制的十进制数字就是它的ascii码,比如A的ascii码就是:65。

字符串和它的ascii码可以互相转换。printf(“%c”,65) 结果是 A;printf(“%d”,’A’)结果就是65了。

字符的数组组合在一起就是字符串,字符串和数组差不多,区别有以下几点:

它必须使用char 声明

它必须以 \0 结束

它遇到\0就结束

char声明的字符串数组一定需要0来结尾,否则会报错。事实上,不只是字符串必须使用0技术,char 声明的其他数组也必需使用0结束。此处留疑,为什么要留0呢,因为C不知道数组到哪里结束,得给它一个结束得null,但为什么不知道呢?留存待解。

C-arr

C的数组是指同一个类型的数据的集合,例如 char arr[5] 表示5个char类型数据的集合,必需声明长度,后期可能会学到不需要声明长度的方法,预留。

数组的初始化:未初始化的数组所有的元素都默认为0。

数组的调试:打断点之后按F5,使用局部变量窗口查看,使用F10按键观察数组变化。

二维数组事实上和一维数组没有区别,注意,声明二维数组时每个第二维数组后面都需要以逗号结尾,如下:

char arr[2][2]{

{89,90},

{88,92},

}

C-变量&内存

C语言的变量,和JS的变量略有不同,C语言中一般提起变量是特指数据变量,根据数据类型不同,声明方式也不同,整数型有int,short,char;浮点型有float,double。附表:

var

上面的表中有一个sizeof的值,这个值表示该变量类型在内存中占多大字节,一个字节可以放8个0或者1,所以char声明的数值只能在0000 0000 到1111 1111之间,char的第一位是作为符号位出现的,1为负0为正,于是char的范围是-128-127,有负值的。unsigned char的声明第一位不是符号位,就没有负数的概念,范围是0-255。

不论是哪种声明方式声明的变量,他的值都可以从内存中读取到,这个变量就放在内存的这几个字节中,修改变量就是修改内存,读取变量就是读取内存,所以可以用小字节变量的时候就不需要用大的类型,以节省内存。

C-printf & scanf_s

C语言的第二章: printf和 scanf_s,输出与输入。

printf,在我心目中和console.log以及document.write差不多,都是打印用,但printf是有自己的参数的,它使用起来是这样的:printf(“%d+%f”,10,10.2)。

%d 或者 %f 是坑,显示后面的参数的,第一个””,后面出现的就都是参数了,参数之间使用英文逗号隔开。

scanf_s,原来应该是scanf,scanf_s是scanf的安全版,我使用的vs2015已经不支持scanf了。这个参数是让输入的意思,和keydown差不多了。也可以有好几个参数,使用起来是这样的:int a,b; scanf_s(“%d,%d”,&a,&b); 他的参数前面需要“&”,键入参数时需要完整的按照中间的间隔符键入,比如我这里使用了半逗号,就需要输入半逗号,输入其它都会报错。
#include <stdio.h>
int main() {
double float1;
double float2;
printf(“please multiplying two float_num like 1.2*1.2: “);
scanf_s(“%lf*%lf”, &float1,&float2);
printf(“The result of multiplying two numbers is:%f*%f=%.2f”,float1,float2,float1*float2);
return 0;
}

附加其它基础:

%d:十进制整数。
%4d:最小4位宽整数,不足4位宽前面补足空格。
%04d:最小4位宽整数,不足4位宽前面补足0(只能使用0)。
%f:浮点数,保留浮点数后6位。
%lf:
%.2f:浮点数,保留浮点数后2位。
int a=10:声明变量a是类型为数字10。
double a = 12.2123:声明变量a是类型为浮点数12.2123。

C语言中声明变量竟然还需要声明类型,每个类型有不同的声明,心塞塞。
注:scanf_s使用浮点数时,需要用double声明%lf这样的双精度浮点型,使用float声明的%f单精度浮点型就会报错,甚至有可能引起程序崩溃 。