c_cpp 二叉树的前序,中序和后序遍历

二叉树的前序,中序和后序遍历

bitree.c
//二叉树抽象数据类型的头文件
typedef struct BiTreeNode_{
    void *data;
    struct BiTreeNode_ *left;
    struct BiTreeNode_ *right;
}BiTreeNode;

typedef struct BiTree_{
    int size;
    void (*compare)(const void *key1,const void *key2);
    void (*destroy)(void *data);
    BiTreeNode* root;
}BiTree;

//遍历二叉树的实现函数
/* 前序遍历 */
int preorder(const BiTreeNode *node){
    if(node){
        //对结点的处理函数
        printNode(node);
        if(node->left)
             if(perorder(node->left)!=0)
                   return -1;
        if(node->right)
             if(perorder(node->right)!=0)
                   return -1;
        return 0;
    }
}

/* 中序遍历 */
int inorder(const BiTreeNode *node){
    if(node){
        if(node->left)
             if(inorder(node->left)!=0)
                   return -1;

        //对结点的处理函数
        printNode(node);

        if(node->right)
             if(inorder(node->right)!=0)
                   return -1;
        return 0;
    }
}

/* 后序遍历 */
int postorder(const BiTreeNode *node){
    if(node){
        if(node->left)
             if(postorder(node->left)!=0)
                   return -1;
        if(node->right)
             if(postorder(node->right)!=0)
                   return -1;
        //对结点的处理函数
        printNode(node);
        return 0;
    }
}

c_cpp client.c

client.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>

int main(int argc, char const* argv[])
{
    struct sockaddr_in server;
    int client_socket;
    char buf[32];
    int res;

    client_socket = socket(AF_INET, SOCK_STREAM, 0);

    server.sin_family = AF_INET;
    server.sin_port = htons(18081);
    server.sin_addr.s_addr = inet_addr("127.0.0.1");

    res = connect(client_socket, (struct sockaddr *)&server, sizeof(server));
    if (res == -1) {
        printf("failed to connect\n");
        switch (errno) {
            case EBADF:
                printf("file descriptor is invalid\n");
                break;
            case EALREADY:
                printf("target socket is already used\n");
                break;
            case ETIMEDOUT:
                printf("timed out\n");
                break;
            case ECONNREFUSED:
                printf("connection refused\n");
                break;
            default:
                printf("unknown\n");
                break;
        }
        return 1;
    }

    memset(buf, 0, sizeof(buf));
    res = read(client_socket, buf, sizeof(buf));

    printf("%d, %s\n", res, buf );

    return 0;
}
server.c
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>

int main(int argc, char const* argv[])
{
    // AF_INET IPv4を利用することを指定する
    // AF_INET6 IPv6を利用することを指定する
    int socket_descriptor;
    int client_socket;
    int res;
    struct sockaddr_in addr;
    struct sockaddr_in client;
    socklen_t client_length;

    socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);

    if (socket_descriptor == -1) {
        printf("failed to create socket\n");
        return 1;
    }

    addr.sin_family = AF_INET;
    addr.sin_port = htons(18081);
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_len = sizeof(addr);

    res = bind(socket_descriptor, (struct sockaddr *)&addr, sizeof(addr));
    if (res == -1) {
        printf("failed to bind\n");
        return 1;
    }

    // これからclientの接続要求を待つようにする
    res = listen(socket_descriptor, 5);
    if (res == -1) {
        printf("failed to listen\n");
        return 1;
    }

    // 接続要求を受け付ける状態にする
    client_length = sizeof(client);
    client_socket = accept(socket_descriptor, (struct sockaddr *)&client, &client_length);
    if (client_socket == -1) {
        printf("failed to accept client\n");
        return 1;
    }

    write(client_socket, "Hello, world!", 13);

    close(client_socket);

    close(socket_descriptor);

    return 0;
}

/**
 * socket関数がsocket descriptorを返す
 * socket descriptorを特定のportにbindする
 * その次どうするかな
 *
 *
 */

c_cpp 大整数运算

大整数运算

biginteger.c
//大整数运算
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//字符串反转
void strrev(char* s)
{
    int i=-1;
    while(s[++i]!='\0');
    for(int j=0;j<i/2;j++){
        char tmp = s[j];
        s[j] = s[i-j-1];
        s[i-j-1]=tmp;
    }
}
void Add(const char*str1, const char* str2, char* ans)
{
    int l1, l2, l;
    l1 = strlen(str1);
    l2 = strlen(str2);
    l = l1>l2 ? l1 : l2;
    char* s1 = (char*)malloc(sizeof(char)*(l1+1));
    char* s2 = (char*)malloc(sizeof(char)*(l2+1));
    memcpy(s1,str1,(l1+1)*sizeof(char));
    memcpy(s2,str2,(l2+1)*sizeof(char));
    strrev(s1);
    strrev(s2);
    int i;
    int sum, carry;
    i=sum=carry=0;
    while(i<l){
        char a = i<l1?s1[i]:'0';
        char b = i<l2?s2[i]:'0';
        sum = a-'0'+b-'0' + carry;
        ans[i] = sum % 10 + '0';
        carry = sum / 10;
        i++;
    }
    if(carry!=0)
        ans[i++]=carry+'0';
    ans[i]='\0';
    strrev(ans);
    free(s1);
    free(s2);
}
void Mul(const char*str1, const char* str2, char* ans)
{
    int l1, l2, l;
    l1 = strlen(str1);
    l2 = strlen(str2);
    l = l1 + l2;
    ans[0]='\0';
    char* s1 = (char*)malloc(sizeof(char)*(l1+1));
    char* s2 = (char*)malloc(sizeof(char)*(l2+1));
    memcpy(s1,str1,(l1+1)*sizeof(char));
    memcpy(s2,str2,(l2+1)*sizeof(char));
    strrev(s1);
    strrev(s2);
    char* tmp = (char*)malloc(sizeof(char)*(l1+2));
    int s, carry;
    s = carry = 0;
    for(int i=0;i<l2;i++){
        int j;
        for(int j=0;j<i;j++)
            tmp[j]='0';
        for(j=0;j<l1;j++){
            s = (s1[j]-'0')*(s2[i]-'0')+carry;
            tmp[i+j]=s%10+'0';
            carry=s/10;
        }
        if(carry!=0)
            tmp[i+j++]=carry+'0';
        tmp[i+j]='\0';
        strrev(ans);
        strrev(tmp);
        Add(ans,tmp, ans);
        strrev(ans);
    }
    strrev(ans);
}
int main()
{
    const char a[] = "12345";
    const char b[] = "123";
    char c[1024];

    Add(a,b,c);
    printf("a+b=%s\n", c);
    Mul(a,b,c);
    printf("a*b=%s\n", c);

    return 0;
}

c_cpp C - 使用dbg.h的项目

C - 使用dbg.h的项目

ex22_main.c
#include "ex22.h"
#include "dbg.h"

const char *MY_NAME = "Zed A. Shaw";

void scope_demo(int count)
{
    log_info("count is: %d", count);

    if(count > 10) {
        int count = 100;  // BAD! BUGS!

        log_info("count in this scope is %d", count);
    }

    log_info("count is at exit: %d", count);

    count = 3000;

    log_info("count after assign: %d", count);
}

int main(int argc, char *argv[])
{
    // test out THE_AGE accessors
    log_info("My name: %s, age: %d", MY_NAME, get_age());

    set_age(100);

    log_info("My age is now: %d", get_age());

    // test out THE_SIZE extern
    log_info("THE_SIZE is: %d", THE_SIZE);
    print_size();

    THE_SIZE = 9;

    log_info("THE SIZE is now: %d", THE_SIZE);
    print_size();

    // test the ratio function static
    log_info("Ratio at first: %f", update_ratio(2.0));
    log_info("Ratio again: %f", update_ratio(10.0));
    log_info("Ratio once more: %f", update_ratio(300.0));

    // test the scope demo
    int count = 4;
    scope_demo(count);
    scope_demo(count * 20);

    log_info("count after calling scope_demo: %d", count);

    return 0;
}
ex22.h
#ifndef EX22_H
#define EX22_H

// makes THE_SIZE in ex22.c available to other .c files
extern int THE_SIZE;

// gets and sets an internal static variable in ex22.c
int get_age();
void set_age(int age);

// updates a static variable that's inside update_ratio
double update_ratio(double ratio);

void print_size();

#endif
ex22.c
#include <stdio.h>
#include "ex22.h"
#include "dbg.h"

int THE_SIZE = 1000;

static int THE_AGE = 37;

int get_age()
{
    return THE_AGE;
}

void set_age(int age)
{
    THE_AGE = age;
}


double update_ratio(double new_ratio)
{
    static double ratio = 1.0;

    double old_ratio = ratio;
    ratio = new_ratio;

    return old_ratio;
}

void print_size()
{
    log_info("I think size is: %d", THE_SIZE);
}

c_cpp 叉子

叉子

cups_fork_process.c
  if ((*pid = fork()) == 0)
  {
   /*
    * Child process goes here; update stderr as needed...
    */

    if (errfd != 2)
    {
      if (errfd < 0)
        errfd = open("/dev/null", O_WRONLY);

      if (errfd != 2)
      {
        dup2(errfd, 2);
  close(errfd);
      }
    }

   /*
    * Put this process in its own process group so that we can kill any child
    * processes it creates.
    */

#ifdef HAVE_SETPGID
    if (!RunUser && setpgid(0, 0))
      exit(errno + 100);
#else
    if (!RunUser && setpgrp())
      exit(errno + 100);
#endif /* HAVE_SETPGID */

   /*
    * Update the remaining file descriptors as needed...
    */

    if (infd != 0)
    {
      if (infd < 0)
        infd = open("/dev/null", O_RDONLY);

      if (infd != 0)
      {
        dup2(infd, 0);
	close(infd);
      }
    }

    if (outfd != 1)
    {
      if (outfd < 0)
        outfd = open("/dev/null", O_WRONLY);

      if (outfd != 1)
      {
        dup2(outfd, 1);
	close(outfd);
      }
    }

    if (backfd != 3 && backfd >= 0)
    {
      dup2(backfd, 3);
      close(backfd);
      fcntl(3, F_SETFL, O_NDELAY);
    }

    if (sidefd != 4 && sidefd >= 0)
    {
      dup2(sidefd, 4);
      close(sidefd);
      fcntl(4, F_SETFL, O_NDELAY);
    }

   /*
    * Change the priority of the process based on the FilterNice setting.
    * (this is not done for root processes...)
    */

    if (!root)
      nice(FilterNice);

   /*
    * Reset group membership to just the main one we belong to.
    */

    if (!RunUser && setgid(Group))
      exit(errno + 100);

    if (!RunUser && setgroups(1, &Group))
      exit(errno + 100);

   /*
    * Change user to something "safe"...
    */

    if (!RunUser && user && setuid(user))
      exit(errno + 100);

   /*
    * Change umask to restrict permissions on created files...
    */

    umask(077);

   /*
    * Unblock signals before doing the exec...
    */

#ifdef HAVE_SIGSET
    sigset(SIGTERM, SIG_DFL);
    sigset(SIGCHLD, SIG_DFL);
    sigset(SIGPIPE, SIG_DFL);
#elif defined(HAVE_SIGACTION)
    memset(&action, 0, sizeof(action));

    sigemptyset(&action.sa_mask);
    action.sa_handler = SIG_DFL;

    sigaction(SIGTERM, &action, NULL);
    sigaction(SIGCHLD, &action, NULL);
    sigaction(SIGPIPE, &action, NULL);
#else
    signal(SIGTERM, SIG_DFL);
    signal(SIGCHLD, SIG_DFL);
    signal(SIGPIPE, SIG_DFL);
#endif /* HAVE_SIGSET */

    cupsdReleaseSignals();

   /*
    * Execute the command; if for some reason this doesn't work, log an error
    * exit with a non-zero value...
    */

    if (envp)
      execve(exec_path, argv, envp);
    else
      execv(exec_path, argv);

    exit(errno + 100);
  }
  else if (*pid < 0)
  {
   /*
    * Error - couldn't fork a new process!
    */

    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command,
                    strerror(errno));

    *pid = 0;
  }
  else
  {
    if (!process_array)
      process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL);
 
    if (process_array)
    {
      if ((proc = calloc(1, sizeof(cupsd_proc_t) + strlen(command))) != NULL)
      {
        proc->pid    = *pid;
	proc->job_id = job ? job->id : 0;
	_cups_strcpy(proc->name, command);

	cupsArrayAdd(process_array, proc);
      }
    }
  }

c_cpp 杯子信号

杯子信号

config.h
/*
 * What signal functions to use?
 */

#undef HAVE_SIGSET
#define HAVE_SIGACTION
cups_signal.c
static int              holdcount = 0;  /* Number of times "hold" was called */
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
static sigset_t         holdmask;       /* Old POSIX signal mask */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */

/*
 * 'cupsdHoldSignals()' - Hold child and termination signals.
 */

void
cupsdHoldSignals(void)
{
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
  sigset_t              newmask;        /* New POSIX signal mask */
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */


  holdcount ++;
  if (holdcount > 1)
    return;

#ifdef HAVE_SIGSET
  sighold(SIGTERM);
  sighold(SIGCHLD);
#elif defined(HAVE_SIGACTION)
  sigemptyset(&newmask);
  sigaddset(&newmask, SIGTERM);
  sigaddset(&newmask, SIGCHLD);
  sigprocmask(SIG_BLOCK, &newmask, &holdmask);
#endif /* HAVE_SIGSET */
}

/*
 * 'cupsdReleaseSignals()' - Release signals for delivery.
 */

void
cupsdReleaseSignals(void)
{
  holdcount --;
  if (holdcount > 0)
    return;

#ifdef HAVE_SIGSET
  sigrelse(SIGTERM);
  sigrelse(SIGCHLD);
#elif defined(HAVE_SIGACTION)
  sigprocmask(SIG_SETMASK, &holdmask, NULL);
#endif /* HAVE_SIGSET */
}

c_cpp C - Zed的调试宏

C - Zed的调试宏

dbg.h
#ifndef __dbg_h__
#define __dbg_h__

#include <stdio.h>
#include <errno.h>
#include <string.h>

#ifdef NDEBUG
#define debug(M, ...)
#else
#define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__)
#endif

#define clean_errno() (errno == 0 ? "None" : strerror(errno))

#define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)

#define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d:%s: errno: %s) " M "\n", __FILE__, __LINE__, __func__, clean_errno(), ##__VA_ARGS__)

#define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d:%s:) " M "\n", __FILE__, __LINE__, __func__, ##__VA_ARGS__)

#define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; }

#define sentinel(M, ...)  { log_err(M, ##__VA_ARGS__); errno=0; goto error; }

#define check_mem(A) check((A), "Out of memory.")

#define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; }

#endif

c_cpp 小波滤波算法

小波滤波算法

gistfile1.cpp
const int datalen=32;
const int dbN=3;
const int stages=4;

/* interface array, put your signal data here and
pure signal is returned here after filtering*/
double dataio[datalen];
double data[datalen];// main data arrays
double har[stages][datalen];
double gar[stages][datalen];
static const double db[]={0.3326706,0.8068915,0.4598775,-0.1350110,
    -0.0854413,0.0352263};

int recodeh(int nlevel,int len)
{
  int i,k,k1,len1;
	double temp;

	len1=len>>1;
	for(i=0;i<len;i++)
	{
		dataio[i]=0.0;
		if(len>(2*dbN))
		{
			for(k1=(i-dbN);k1<(i+dbN);k1++)
			{
				k=k1/2;
				if((k>=0) && (k<len1) &&((k1%2)==0) && ((temp=har[nlevel][(i-k1+len)%len])!=0))
					dataio[i]+=temp*data[k];
			}
			for(k1=(i+len-dbN);k1<(i+len+1);k1++)
			{
				k=k1/2;
				if((k>=0) && (k<len1) &&((k1%2)==0) && ((temp=har[nlevel][(i-k1+len)%len])!=0))
					dataio[i]+=temp*data[k];
			}
			for(k1=(i-len+1);k1<(i-len+dbN);k1++)
			{
				k=k1/2;
				if((k>=0) && (k<len1) &&((k1%2)==0) && ((temp=har[nlevel][(i-k1+len)%len])!=0))
					dataio[i]+=temp*data[k];
			}
		}
		else
		{
			for(k=0;k<len1;k++)
			{
				if((temp=har[nlevel][(i-2*k+len)%len])!=0)
					dataio[i]+=temp*data[k];
			}
		}
	}
	return 1;
}

int recodeg(int nlevel,int len)
{
	int i,k,k1,len1;
	double temp;

	len1=len>>1;
	for(i=0;i<len;i++)
	{
		if(len>(2*dbN))
		{
			for(k1=(i+len-dbN-2);k1<(i+len);k1++)
			{
				k=k1/2;
				if((k>=0) && (k<len1) &&((k1%2)==0) && ((temp=gar[nlevel][(i-k1+len)%len])!=0))
					dataio[i]+=temp*data[k+len1];
			}
			for(k1=(i-dbN-2);k1<(i+dbN-2);k1++)
			{
				k=k1/2;
				if((k>=0) && (k<len1) &&((k1%2)==0) && ((temp=gar[nlevel][(i-k1+len)%len])!=0))
					dataio[i]+=temp*data[k+len1];
			}
			for(k1=(i-len);k1<(i-len+dbN-2);k1++)
			{
				k=k1/2;
				if((k>=0) && (k<len1) &&((k1%2)==0) && ((temp=gar[nlevel][(i-k1+len)%len])!=0))
					dataio[i]+=temp*data[k+len1];
			}
		}
		else
		{
			for(k=0;k<len1;k++)
			{
				if((temp=gar[nlevel][(i-2*k+len)%len])!=0)
					dataio[i]+=temp*data[k+len1];
			}
		}
	}
	return 1;
}

int recompose()
{
	int nlevel,len,j;

	for(nlevel=stages-1;nlevel>0;nlevel--)
	{
		len=datalen>>(nlevel-1);
		recodeh(nlevel,len);
		recodeg(nlevel,len);
		for(j=0;j<datalen;j++)
			data[j]=dataio[j];
	}
	return 1;
}

int hperiod(int nlevel,int len)
{
	int sign,i;
	double temp;

	for(sign=0;sign<len;sign++)
	{
		temp=0.0;
		for(i=0;i<(2*dbN);i++)
		{
			if( ( (sign-i+dbN-1) % len) == 0)
				temp+=db[i];
		}
		har[nlevel][sign]=temp;
	}
	return 1;
}

int gperiod(int nlevel,int len)
{
	int sign,i,flag;
	double temp;

	for(sign=0;sign<len;sign++)
	{
		temp=0.0;
		for(i=0;i<(2*dbN);i++)
		{
			if( ( (sign+i-dbN-2) % len) == 0)
			{
				if((dbN-i+1)%2)
					flag=-1;
				else
					flag=1;
				temp+=db[i]*flag;
			}
		}
		gar[nlevel][sign]=temp;
	}
	return 1;
}

int codeh(int nlevel,int len)
{
	int i,i2,k,len1;
	double temp;

	len1=len>>1;
	for(i=0;i<len1;i++)
	{
		i2=2*i;
		data[i]=0.0;
		if(len>(2*dbN))
		{
			for(k=i2-len;k<i2-len+dbN+1;k++)
			{
				if((k>=0) && (k<len) && ( (temp=har[nlevel][(k-i2+len)%len]) != 0 ) )
					data[i]+=temp*dataio[k];
			}
			for(k=i2-dbN+1;k<i2+dbN+1;k++)
			{
				if((k>=0) && (k<len) && ( (temp=har[nlevel][(k-i2+len)%len]) != 0) )
					data[i]+=temp*dataio[k];
			}
			for(k=i2+len-dbN+1;k<i2+len;k++)
			{
				if((k>=0) && (k<len) && ( (temp=har[nlevel][(k-i2+len)%len]) != 0) )
					data[i]+=temp*dataio[k];
			}
		}
		else
		{
			for(k=0;k<len;k++)
			{
				if((temp=har[nlevel][(k-i2+len)%len]) != 0)
					data[i]+=temp*dataio[k];
			}
		}
	}
	return 1;
}

int codeg(int nlevel,int len)
{
	int i,i2,k,len1;
	double temp;

	len1=len>>1;
	for(i=0;i<len1;i++)
	{
		i2=2*i;
		data[i+len1]=0.0;
		if(len>(2*dbN))
		{
			for(k=i2-len;k<i2-len+dbN+3;k++)
			{
				if((k>=0) && (k<len) && ( (temp=gar[nlevel][(k-i2+len)%len]) != 0 ) )
					data[i+len1]+=temp*dataio[k];
			}
			for(k=i2-dbN+3;k<i2+dbN+3;k++)
			{
				if((k>=0) && (k<len) && ( (temp=gar[nlevel][(k-i2+len)%len]) != 0) )
					data[i+len1]+=temp*dataio[k];
			}
			for(k=i2+len-dbN+3;k<i2+len;k++)
			{
				if((k>=0) && (k<len) && ( (temp=gar[nlevel][(k-i2+len)%len]) != 0) )
					data[i+len1]+=temp*dataio[k];
			}
		}
		else
		{
			for(k=0;k<len;k++)
			{
				if((temp=gar[nlevel][(k-i2+len)%len]) != 0)
					data[i+len1]+=temp*dataio[k];
			}
		}
	}
	return 1;
}

int decompose()
{
	int nlevel,len,j;

	// main loop for the nlevel-th decomosition
	for(nlevel=1;nlevel<stages;nlevel++)
	{
		len=datalen>>(nlevel-1);
		codeh(nlevel,len);
		codeg(nlevel,len);
		for(j=0;j<datalen;j++)
			dataio[j]=data[j]; 
	}
	return 1;
}

int filter(/* PFILTER pFilter */)
{
	int len,j;
	double dfilter = 0.01;

	len = datalen>>(stages-1);
	for( j=len; j<datalen; j++ )
	{
		// 这里需要使用指定的过滤函数,对越高阶的小波成分,衰减越大才能起到滤波作用
		// data[j] = (*pFilter)(data[j], j);
		// data[j] = 0.0; //最初的过滤方法,直接令高阶分量为0
		data[j] *= dfilter; // 这里让高阶分量乘以小的因子
		dfilter *= 0.01; // 因子为pow(0.01, j-len+1)
	}
	return 1;
}

int dwt_filter()
{
	int nlevel,len,j;

	for(nlevel=1;nlevel<stages;nlevel++)
	{
		len=datalen>>(nlevel-1);
		hperiod(nlevel,len);
		gperiod(nlevel,len);
	}
	decompose();
	filter();// get rid of detail part of components

	for(j=0;j<datalen;j++)
		dataio[j]=data[j]; 
	recompose();

	return 1;
}

double WaveletFilter( double dData, double *dSave )
{
	int j;

	// shifting and saving the origin data
	for(j=0; j<datalen-1; j++)
	{
		dSave[j] = dSave[j+1];
	}
	dSave[datalen-1] = dData;

	for(j=0; j<datalen; j++)
		dataio[j] = dSave[j];

	// wavelet transformation
	dwt_filter();

	return dataio[datalen-1];
}

c_cpp C - 错误句柄

C - 错误句柄

die.c
/**
 * die - error handle function
 * @message:	info about the error
 *
 * Print error message and exit.
 *
 */
void die (const char *message)
{
	if (errno) {
		perror (message);
	} else {
		printf("ERROR: %s\n", message);
	}

	exit(1);
}

c_cpp JTDropShadowFixNavigationViewController - 在UINavigationBar中使用自定义阴影(针对iOS 6.1修复)

JTDropShadowFixNavigationViewController - 在UINavigationBar中使用自定义阴影(针对iOS 6.1修复)

README.md
# Using custom drop shadows in UINavigationBar (fix for iOS 6.1)

This is an update to the [Adding Drop Shadow on UINavigationBar](http://ioscodesnippet.com/post/10437516225/adding-drop-shadow-on-uinavigationbar) which was written prior to iOS 6.0

Since iOS 6.0 Apple introduced the `-[UINavigationBar shadowImage]` property. We should probably leverage that, which are also UIAppearance selectors.

    // Configure your images
    UIImage *background = [UIImage imageNamed:@"titlebar44"];
    UIImage *shadow = [UIImage imageNamed:@"titlebar-bottom-highlight"];

    // Using the appearance proxy
    // Note: setBackgroundImage:forBarMetrics has been documented to be
    // **compulsory** to enable the displaying of the custom shadow image.
    [[UINavigationBar appearance] setBackgroundImage:background forBarMetrics:UIBarMetricsDefault];
    [[UINavigationBar appearance] setShadowImage:shadow];


You probably went with similar code, but the custom shadow just didn't show up, right?

The problem occurs because of the implementation on UINavigationBar, the clipsToBounds property is needed to be set to NO, and this step has been missing from the documentation. (At least I didn't find it)

Most probably you'll need to set self.navigationController.navigationBar.clipsToBounds = NO in every UIViewController subclass you wrote, a more convenience way is to subclass UINavigationController and have it do the job for you. And I've created a snippet for you.

<script src="https://gist.github.com/6591926.js?file=JTDropShadowFixNavigationViewController.h"> </script>
<script src="https://gist.github.com/6591926.js?file=JTDropShadowFixNavigationViewController.m"> </script>

So now you can initialise your view controllers in code like this:

    UIViewController *controller; // configure your view controller
    UINavigationController *navController = [[JTDropShadowFixNavigationViewController alloc] initWithRootViewController:controller];
  
Or if you use storyboard, simply change the subclass of your UINavigationController to JTDropShadowFixNavigationViewController.

![](https://gist.github.com/jamztang/6591926/raw/0437477ed7efd34a81bcc66a47de30c95071d7cb/modify-class.png)

**In fact there's an even simpler method you'll notice in the snippet.**

This is a hack that adds a category method to always set clipsToBounds to NO for UINavigationBar. Enable it defining this constant somewhere in your code (recommended in .pch):

    #define ENABLE_JTDROPSHADOW_GLOBAL_FIX 1

Let me know your thoughts!

Jamz

LICENSE
Copyright (c) 2013 Jamz Tang <jamz@jamztang.com>
 
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
 
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
 
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
JTDropShadowFixNavigationViewController.m
/*
 * This file is part of the http://ioscodesnippet.com
 * (c) Jamz Tang <jamz@jamztang.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */


#import "JTDropShadowFixNavigationViewController.h"

@implementation JTDropShadowFixNavigationViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.navigationBar.clipsToBounds = NO;
}

@end

#if ENABLE_JTDROPSHADOW_GLOBAL_FIX

@interface UINavigationBar (JTDropShadowFix)

@end

@implementation UINavigationBar (JTDropShadowFix)

- (void)awakeFromNib {
    self.clipsToBounds = NO;
}

@end

#endif
JTDropShadowFixNavigationViewController.h
/*
 * This file is part of the http://ioscodesnippet.com
 * (c) Jamz Tang <jamz@jamztang.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

#import <UIKit/UIKit.h>

@interface JTDropShadowFixNavigationViewController : UINavigationController

@end