再见编程小问题

来源:互联网 发布:手机电子相册软件 编辑:程序博客网 时间:2024/04/28 15:23

1、int main()前面为什么int而不用void,这是为了系统调用方便

2、变量的生命周期和{}相关

3、大小端模式的问题:我们常用的X86结构是小端模式,而KEIL C51则为大端模式。很多的ARM,DSP都为小端模式(这个记反了

4、堆栈搞反了

5、后缀表达式,一般算式转换成后缀表达式可以先用括号把数包括起来,然后把二者的符号放到最后,然后去掉括号即可。反之,把后缀表达式转成一般表达式,则需要从后面开始收缩一个符号就加一个括号,直道所有的括号都加载完毕,然后再转成一般就容易了,前缀的转换类似

6、内存相关错误

7、地址排列问题:(int *)p1-(int *)p2=4倍的(char *)p1-(char *)p2。

Union的使用注意内存公用,以最长的为准

8、const *p是内容不可改,p可以改

9、static只初始化一次,否则声明初始化语句不运行

10、sizeof那几个题目在前面两篇文章里面有讲诉,见c++内存管理

11、为么有了malloc还需要new,malloc只能机械的分配内存,而数据结构除了内部数据意外,还有大量的类对象,这些除了分配内存意外还需要构造和析构,还需要初始化

12、转义字符

13、为么叫单精度浮点数和双精度浮点数?一个是7位精度的浮点数,有时候这不够

所以就推出了double float,谓之双精度型

ps:float的存储结构:1bit符号位,8bit指数位E(实际指数e=E-127),23bit有效数字M(1=<M<2)
double的存储结构1bit符号位,11bit指数位E(实际指数e=E-1023),52bit有效数字M(1=<M<2)
具体见float和double的数据存储结构

14、求整数的绝对值 abs,求双精度实数的绝对值fabs,头文件math.h

15、检查字符串中的[]与()两个是否匹配的问题,考虑不能先出现右括号,并且嵌套不能交互,如[(})就不行

如果只求一个括号问题,没必要使用数据结构,单用一个while,然后再加两边计数,而且每次右括号不能比左括号多就完了

两个一起检查就要考虑嵌套,用单链表的头插法(模拟栈的功能),只要看前面一个是否是相差1或者2(左小括号与左小括号相差1,左中括号与右中括号相差2)就完了

还可以真用堆栈,相关代码及思想参考网页:检查表达式中左右圆括号是否匹配、c语言括号匹配检验源程序、括号匹配思想

16、c语言的输入函数及其作用

懒得赘述了,就提醒点,scanf遇到空格或者换行符退出,如果要输入整行的字符串,用gets,其中见网页:c语言输入输出函数

17、c语言赋值函数的真假问题。

赋值是0则为假,赋值为其他则为真,其中a=0,为假;a=1为真

18、一个小题目:假设现有一个单向的链表,但是只知道只有一个指向该节点的指针p,并且假设这个节点不是尾节点,试编程实现删除此节点

方法肯定是先把下一个节点的地址给个p指针,再把下一个节点的数据包括其下一个节点的指针复制到这个上面来,然后把下个节点free,然后把p指向0就算完了

19、关联数组就是map的典型应用,不像栈队列这些是线性表

20、程序计数器是不可改变的,不论在哪里

21各种排序方法及其适用的情况

算法适用情况冒泡排序容易出错地方(直接交换不用额外空间)直接插入排序即只需用到O(1)的额外空间的排序,复杂度o(n*n)选择排序 堆排序 希尔排序 快速排序 归并排序 

具体每种算法在每种情况下的选择见下:

(1)若n较小(如n≤50),可采用直接插入或直接选择排序。  

当记录规模较小时,直接插入排序较好;否则因为直接选择移动的记录数少于直接插入,应选直接选择排序为宜。
(2)若文件初始状态基本有序(指正序),则应选用直接插入、冒泡或随机的快速排序为宜;
(3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:快速排序、堆排序或归并排序。  
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;  
堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。这两种排序都是不稳定的。  
若要求排序稳定,则可选用归并排序。但本章介绍的从单个记录起进行两两归并的 排序算法并不值得提倡,通常可以将它和直接插入排序结合在一起使用。先利用直接插入排序求得较长的有序子文件,然后再两两归并之。因为直接插入排序是稳定的,所以改进后的归并排序仍是稳定的。
(4)在基于比较的排序方法中,每次比较两个关键字的大小之后,仅仅出现两种可能的转移,因此可以用一棵二叉树来描述比较判定过程。  
当文件的n个关键字随机分布时,任何借助于"比较"的排序算法,至少需要O(nlgn)的时间。  
箱排序和基数排序只需一步就会引起m种可能的转移,即把一个记录装入m个箱子之一,因此在一般情况下,箱排序和基数排序可能在O(n)时间内完成对n个记录的排序。但是,箱排序和基数排序只适用于像字符串和整数这类有明显结构特征的关键字,而当关键字的取值范围属于某个无穷集合(例如实数型关键字)时,无法使用箱排序和基数排序,这时只有借助于"比较"的方法来排序。  
若n很大,记录的关键字位数较少且可以分解时,采用基数排序较好。虽然桶排序对关键字的结构无要求,但它也只有在关键字是随机分布时才能使平均时间达到线性阶,否则为平方阶。同时要注意,箱、桶、基数这三种分配排序均假定了关键字若为数字时,则其值均是非负的,否则将其映射到箱(桶)号时,又要增加相应的时间。
(5)有的语言(如Fortran,Cobol或Basic等)没有提供指针及递归,导致实现归并、快速(它们用递归实现较简单)和基数(使用了指针)等排序算法变得复杂。此时可考虑用其它排序。
(6)本章给出的排序算法,输人数据均是存储在一个向量中。当记录的规模较大时,为避免耗费大量的时间去移动记录,可以用链表作为存储结构。譬如插入排序、归并排序、基数排序都易于在链表上实现,使之减少记录的移动次数。但有的排序方法,如快速排序和堆排序,在链表上却难于实现,

以上参考了网页排序算法汇总总结

19、关于判断程序是否运行于printf语句的问题

int x=1,y=1;int z=1 || y++ && x++;printf("%d %d %d\n",-x++,y,z);printf("%d %d %d\n",x=35,y+x,z+y);printf("%d %d %d\n",x,y+x,z+y);

运行的结果是

-1 1 1
35 3 2
35 36 2

想说明两个问题:1、运算符在运算得想要的结果之后就不会往下运算了。2、如果在printf中间出现的运算等等都会按照从右至左的顺序运算过来(左边出现的运算结果不会影响右边的式子)

20 

a) 一个整型数(An integer)
b) 一个指向整型数的指针(A pointer to an integer)
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
d) 一个有10个整型数的数组(An array of 10 integers)
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an

integer )

答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer

21、char str[] 和 char *str 的区别

(1)各自取常数了之后分配的地址不同,数组分配的是栈区,如果在函数内部用完就回收,而指针指向的应该是全局区,只有程序完成才会回收

(2)各自取常量,数组的内容可以改,指针的内容不可改

(3)sizeof得到的也不同,数组是数组有多少成员,指针永远都是4,但是作为函数参数,数组名退化成指针,都一样,全是4

22、!与&这些符号的特殊性

比如z=5,!Z=0;&&是单位运算,非零与零相区分

23、枚举类型的默认参数

默认从有值的地方开始增加1,全没有值的时候从0开始

比如enum  Months{JAN=1,FEB,MAR,APR,MAY=3,JUN,JUL,AUG,SEP,OCT,NOV,DEC}; 其中FEB=2 MAR=3 而JUN却要从4重新开始算,反正是后面比前面多1
printf("%d",(MAR & AUG) ^ !JUN); 

24、x *= x + 1; 等价于x=x*(x+1)即等号右边的式子相当于用括号括起来的,因为运算符的优先级

25、给几个程序相关的英文 strip去除,@S代表 char *

26、while(*s)意思就是字符串输出完就结束循环

27、c中的>>还有什么数组的第几位问题a[2][2][0]是第201位要注意好。

28、嵌入式c中如果按位清0就是 a&(~n),如果是除了某位之外都取反那就是a^(~n)(由于1^1=0,0^1=1,)

29解释一下位域

比如后面跟:数字,数字代表占用几个字节,参见网页位域全解析

30怎么比较两个浮点数的大小。

两个想减,其差在一定的范围内

31写一个类似于printf的函数,可以接受任意多个参数

采用微软的stdarg库,参加网页写一个类似printf的带有不定参数的函数

#include <stdio.h>#include <stdarg.h>        //要包含这个头文件void variable(int i, ...){    int j = 0;      va_list arg_ptr;    //第1步,定义这个指向参数列表的变量      va_start(arg_ptr, i);//第2步,把上面这个变量初始化.即让它指向参数列表    while( j != -1 )      {        //第3步,获取arg_ptr指向的当前参数.这个参数的类型由va_arg的第2个参数指定          j = va_arg(arg_ptr, int);          printf("%d ",j );      }      va_end(arg_ptr);    //第4步,做一些清理工作}main(){      variable(3, 3, 4, 5, 6, -1);}

32有两个单链表,用什么方法可以快速的知道他们有没有相同的部分

分别遍历两个表,求出差,然后从差的位置开始比较,找出的相同的

33有关僵尸进程的问题

 .解释一下僵尸进程、僵尸进程怎么回收 :一个进程结束了,但是父进程没有wait该进程就成为了僵尸进程

   在linux系统上怎么列出所有的僵尸进程ps aux

具体解决方法参加网页linux僵尸进程及其解决方法

34fork函数和wait函数的作用

一个是创建子线程和,一个是回收,具体见网页linux的fork和wait函数详解

35使用memcp函数的时候,有什么要注意的

空间够不够,具体参见strcpy和memcp的注意事项


未完待续。。。

 

 

 

 

原创粉丝点击