Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1754236
  • 博文数量: 335
  • 博客积分: 4690
  • 博客等级: 上校
  • 技术积分: 4341
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-08 21:38
个人简介

无聊之人--除了技术,还是技术,你懂得

文章分类

全部博文(335)

文章存档

2016年(29)

2015年(18)

2014年(7)

2013年(86)

2012年(90)

2011年(105)

分类: C/C++

2012-12-14 18:49:03

看来斯坦福大学的CS107以后,以为自己对C已经很熟悉了,但是发现事情根本不是想象中的那样问题还是很多。假设是面试官提问的话,我感觉自己肯定挂了,,,同时也发现C语言中的字符串功能虽然很强大,但是其中的陷阱太多了,不要以为编译器通过了就万事大吉,其实你的程序问题多的去了。。。。
首先我们从整数的栈的定义,入栈,出栈,销毁开始

点击(此处)折叠或打开

  1. #include <stdio.h>
  2. #include <assert.h>
  3. #include <stdlib.h>
  4. typedef struct {
  5. int * elebase;
  6. int logicallength;
  7. int alloclength;
  8. }stack;

  9. void stacknew(stack *s){
  10. s->logicallength =0;
  11. s->alloclength =4;
  12. s->elebase =malloc(4 * sizeof(int));
  13. assert(s->elebase != NULL);
  14. }
  15. void stackdispose(stack *s ){
  16. free(s->elebase);
  17. /* free(s); ????????????? local variable */
  18. }
  19. void stackpush(stack *s,int value)
  20. {
  21. if (s->logicallength==s->alloclength){
  22. s->alloclength*=2;
  23. s->elebase=(int *)realloc(s->elebase,s->alloclength*sizeof(int));
  24. assert(s-> NULL);
  25. }
  26. s->elebase[s->logicallength]=value;
  27. s->logicallength++;
  28. }
  29. int stackpop(stack *s )
  30. {
  31. assert(s->logicallength > 0);
  32. s->logicallength--;
  33. return s->elebase[s->logicallength];
  34. }

  35. int main(int agrc,char * argv[])
  36. {
  37.     stack istack;
  38.     stacknew(&istack);
  39.     int i=0;
  40.     for (i =0 ;i <= 4 ; i++){
  41.         stackpush(&istack,i*3);
  42.     }
  43.     printf("the size of stack is logciallength %d allocallength %d\r\n",istack.logicallength,istack.alloclength);
  44.     /* pop */
  45.     for(i = 0; i < 4 ; i++){
  46.         
  47.         printf("the %d elememt of int stack is %d \r\n",i,stackpop(&istack));
  48.     }
  49.     /* dispose the stack */
  50.     stackdispose(&istack);
  51.     exit(0);
  52. }
OUTPUT OF THE ABOVE PROGAM:

点击(此处)折叠或打开

  1. the size of stack is logciallength 5 allocallength 8

  2. the 0 elememt of int stack is 12

  3. the 1 elememt of int stack is 9

  4. the 2 elememt of int stack is 6

  5. the 3 elememt of int stack is 3
图示如下:
下面给出通用函数的实现

点击(此处)折叠或打开

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. typedef struct{
  6. void * elems;
  7. int elemsize;
  8. int loglength;
  9. int alloclength;
  10. }stack;
  11. void stacknew(stack *s ,int elemsize);
  12. void stackdispose(stack * s);
  13. void stackpush(stack *s,void * eleaddr);
  14. void stackpop(stack *s, void * elemaddr);
  15. void stacknew(stack *s,int elemsize)
  16. {
  17. s->loglength = 0;
  18. s->elemsize = elemsize;
  19. assert(s->elemsize > 0);
  20. s->alloclength = 4;
  21. s->elems = malloc(4*s->elemsize);
  22. assert(s->elems != NULL);
  23. }
  24. static void stackgrew(stack *s)
  25. {
  26. s->alloclength*=2;
  27. s->elems = realloc(s->elems,s->alloclength*s->elemsize);
  28. }    



  29. void stackdispose(stack *s){
  30. free(s->elems);
  31. }
  32. void stackpush(stack *s,void * elemaddr)
  33. {
  34. if (s->loglength == s->alloclength)
  35.         stackgrew(s);
  36.         
  37. void * target = (char *) s->elems + s->loglength*s->elemsize;
  38. memcpy(target,elemaddr,s->elemsize);
  39. s->loglength++;
  40. }
  41. void stackpop(stack * s, void * elemaddr)
  42. {
  43.       void * source=(char *)s->elems+(s->loglength-1)*s->elemsize;
  44.     memcpy(elemaddr,source,s->elemsize);
  45.     s->loglength--;
  46. }
整数的使用方法:

点击(此处)折叠或打开

  1. #include "stack.h"

  2. int main(int argc,char * argv[])
  3. {
  4.     stack gintstack;
  5.     stacknew(&gintstack,sizeof(int));
  6.     int i=0;
  7.     int k;
  8.     for (i =0 ;i <= 4 ; i++){
  9.         k=i*i;
  10.         stackpush(&gintstack,&k);
  11.     }
  12.     printf("the size of gstack is logciallength %d allocallength %d\r\n",gintstack.loglength,gintstack.alloclength);
  13.     /* pop */
  14.     int element;
  15.     for(i = 0; i < 4 ; i++){
  16.         stackpop(&gintstack,&element);
  17.         printf("the %d elememt of int gstack is %d \r\n",i,element);
  18.     }
  19.     /* dispose the stack */
  20.     stackdispose(&gintstack);
  21.     exit(0);
  22. }

点击(此处)折叠或打开

  1. the size of gstack is logciallength 5 allocallength 8
  2. the 0 elememt of int gstack is 16
  3. the 1 elememt of int gstack is 9
  4. the 2 elememt of int gstack is 4
  5. the 3 elememt of int gstack is
图示与上面的相同。

下面讨论字符串的出入栈,看起来和整数和类似,但是真的很类似?貌似不是

点击(此处)折叠或打开

  1. #include "stack.h"

  2. int main(int argc,char * argv[])
  3. {
  4.     stack gcharstack;
  5.     stacknew(&gcharstack,sizeof(char *));
  6.     int i=0;
  7.     char * friend[]={"kate","lucy","bob","nath","john"};
  8.     char * name;
  9.     for (i =0 ;i <= 4 ; i++){
  10.         name =strdup(friend[i]);        
  11.         stackpush(&gcharstack,&name);
  12.     }
  13.     printf("the size of gstack is logciallength %d allocallength %d\r\n",gcharstack.loglength,gcharstack.alloclength);
  14.     /* pop */
  15.     for(i = 0; i < 4 ; i++){
  16.         stackpop(&gcharstack,&name);
  17.         printf("the %d elememt of int gstack is %s \r\n",i,name);
  18.     }
  19.     /* dispose the stack */
  20.     stackdispose(&gcharstack);
  21.     exit(0);
  22. }
下图给出了字符串入栈的步骤,需要注意的
绿色的箭头表示字符串的指向关系
红色的箭头表示地址的复制


上图忘记修改了,此时2个元素入栈,应为2,需要注意的字符串函数stdup,它返回了一个新的字符串,因此问题也就随之而来

点击(此处)折叠或打开

  1. the size of gstack is logciallength 5 allocallength 8

  2. the 0 elememt of int gstack is john

  3. the 1 elememt of int gstack is nath

  4. the 2 elememt of int gstack is bob

  5. the 3 elememt of int gstack is lucy
看到上图,发现问题了没有?程序编译正常,运行也正常,但是问题出在哪里呢?

————————--
如果看懂了,请继续往下看
————————--
new version of stack without  mem leak :

点击(此处)折叠或打开

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <assert.h>
  5. typedef struct{
  6. void * elems;
  7. int elemsize;
  8. int loglength;
  9. int alloclength;
  10. void (*freefn)(void *);
  11. }stack;
  12. void stacknew(stack *s ,int elemsize,void (*freefn)(void *));
  13. void stackdispose(stack * s);
  14. void stackpush(stack *s,void * eleaddr);
  15. void stackpop(stack *s, void * elemaddr);
  16. void stacknew(stack *s,int elemsize,void (*freefn)(void *))
  17. {
  18. s->loglength = 0;
  19. s->elemsize = elemsize;
  20. assert(s->elemsize > 0);
  21. s->alloclength = 4;
  22. s->elems = malloc(4*s->elemsize);
  23. assert(s->elems != NULL);
  24. s->freefn=freefn;
  25. }
  26. static void stackgrew(stack *s)
  27. {
  28. s->alloclength*=2;
  29. s->elems = realloc(s->elems,s->alloclength*s->elemsize);
  30. }    

  31. void stringfn(void *eleaddr) {
  32.     free(*(char **) eleaddr);
  33. }


  34. void stackdispose(stack *s){
  35.     int i = 0;
  36.     if (s->freefn != NULL) {
  37.         for( i=0; i < s->loglength; i++) {
  38.             s->freefn(s->elems+i*s->elemsize);
  39.         }
  40.     }
  41. free(s->elems);
  42. }
  43. void stackpush(stack *s,void * elemaddr)
  44. {
  45. if (s->loglength == s->alloclength)
  46.         stackgrew(s);
  47.         
  48. void * target = (char *) s->elems + s->loglength*s->elemsize;
  49. memcpy(target,elemaddr,s->elemsize);
  50. s->loglength++;
  51. }
  52. void stackpop(stack * s, void * elemaddr)
  53. {
  54.       void * source=(char *)s->elems+(s->loglength-1)*s->elemsize;
  55.     memcpy(elemaddr,source,s->elemsize);
  56.     s->loglength--;
  57. }

点击(此处)折叠或打开

  1. #include "nstack.h"

  2. int main(int argc,char * argv[])
  3. {
  4.     stack gcharstack;
  5.     stacknew(&gcharstack,sizeof(char *),stringfn);
  6.     int i=0;
  7.     char * friend[]={"kate","lucy","bob","nath","john"};
  8.     char * name;
  9.     for (i =0 ;i <= 4 ; i++){
  10.         name =strdup(friend[i]);        
  11.         stackpush(&gcharstack,&name);
  12.     }
  13.     printf("the size of gstack is logciallength %d allocallength %d\r\n",gcharstack.loglength,gcharstack.alloclength);
  14.     /* pop */
  15.     for(i = 0; i <= 4 ; i++){
  16.         stackpop(&gcharstack,&name);
  17.         printf("the %d elememt of int gstack is %s \r\n",i,name);
  18.         free(name);
  19.     }
  20.     /* dispose the stack */
  21.     stackdispose(&gcharstack);
  22.     exit(0);
  23. }
output of the above program :

点击(此处)折叠或打开

  1. the size of gstack is logciallength 5 allocallength 8

  2. the 0 elememt of int gstack is john

  3. the 1 elememt of int gstack is nath

  4. the 2 elememt of int gstack is bob

  5. the 3 elememt of int gstack is lucy

  6. the 4 elememt of int gstack is kate
由于使用了strdup函数,动态的分配了内存,因此你必须释放,释放的操作有函数来完成。
后续后继续补充该内容,二级指针不是太好理解------

help  document :

点击(此处)折叠或打开

  1. STRDUP(3) Linux Programmer's Manual STRDUP(3)



  2. NAME
  3.        strdup, strndup, strdupa, strndupa - duplicate a string

  4. SYNOPSIS
  5.        #include <string.h>

  6.        char *strdup(const char *s);

  7.        char *strndup(const char *s, size_t n);
  8.        char *strdupa(const char *s);
  9.        char *strndupa(const char *s, size_t n);
后续后继续补充该内容,二级指针不是太好理解------










阅读(1028) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~