36 函数设计原则

1 函数设计原则1

  • 函数从意义上应该是一个独立的功能模块

  • 函数名要在一定程度上反映函数的功能

  • 函数参数名要能够体现参数的意义

    void sc(char* s1,char* s2);  //×
    vs
    void str_copy(char* str_dest,char* str_src);  //√
    
  • 尽量避免在函数中使用全局变量

2 函数设计原则2

  • 当函数参数不应该在函数体内部被修改时,应加上 const 声明

  • 如果参数是指针,且仅作输入参数,则应加上 const 声明,避免野指针和内存操作的错误

    void str_copy(char* str_dest,const char* str_src);
    

3 函数设计原则3

  • 不能省略返回值的类型
    • 如果函数没有返回值,那么应该声明为 void 类型
  • 对参数进行有效性检查
    • 对于指针参数的检查尤为重要
  • 不要返回指向“栈内存”的指针
    • 栈内存在函数体结束时被自动释放

4 函数设计原则4

  • 函数体的规模要小,尽量控制在 80 行代码之内
  • 相同的输入对应相同的输出,壁面函数带有“记忆”功能
  • 避免函数有过多的参数,参数个数尽量控制在 4 个以内

5 函数设计原则5

  • 有时候函数不需要返回值,但为了增加灵活性,如支持链式表达,可以附加返回值

    char s[64];
    int len = strlen(strcpy(s,"android"));  //strcpy返回s本身,len = 7
    
  • 函数名与返回值类型在语义上不可冲突

    char c = getchar();
    
    if(EOF == c)
    {
        //...
    }
    

6 示例:优秀代码赏析

  • Demo:sclipseUtil.c

    /*******************************************************************************
     * Copyright (c) 2000, 2005 IBM Corporation and others.
     * All rights reserved. This program and the accompanying materials
     * are made available under the terms of the Eclipse Public License v1.0
     * which accompanies this distribution, and is available at 
     * http://www.eclipse.org/legal/epl-v10.html
     * 
     * Contributors:
     *     IBM Corporation - initial API and implementation
     *     Kevin Cornell (Rational Software Corporation)
     *******************************************************************************/
    
    /* Eclipse Launcher Utility Methods */
    
    #include "eclipseOS.h"
    #include "eclipseCommon.h"
    #include "eclipseUtil.h"
    
    #include <string.h>
    #include <stdlib.h>
    #include <stdio.h>
    #include <sys/stat.h>
    #ifdef _WIN32
    #include <direct.h>
    #else
    #include <unistd.h>
    #include <strings.h>
    #endif
    
    #define MAX_LINE_LENGTH 256
    
    /* Is the given VM J9 */
    int isJ9VM( _TCHAR* vm )
    {
    	_TCHAR * ch = NULL, *ch2 = NULL;
    	int res = 0;
    	
    	if (vm == NULL)
    		return 0;
    	
    	ch = lastDirSeparator( vm );
    	if (isVMLibrary(vm)) {
    		/* a library, call it j9 if the parent dir is j9vm */
    		if(ch == NULL)
    			return 0;
    		ch[0] = 0;
    		ch2 = lastDirSeparator(vm);
    		if(ch2 != NULL) {
    			res = (_tcsicmp(ch2 + 1, _T_ECLIPSE("j9vm")) == 0);
    		}
    		ch[0] = dirSeparator;
    		return res;
    	} else {
    		if (ch == NULL)
    		    ch = vm;
    		else
    		    ch++;
    		return (_tcsicmp( ch, _T_ECLIPSE("j9") ) == 0);
    	}
    }
    
    int checkProvidedVMType( _TCHAR* vm ) 
    {
    	_TCHAR* ch = NULL;
    	struct _stat stats;
    	
    	if (vm == NULL) return VM_NOTHING;
    	
    	if (_tstat(vm, &stats) == 0 && (stats.st_mode & S_IFDIR) != 0) {
    		/* directory */
    		return VM_DIRECTORY;
    	}
    
    	ch = _tcsrchr( vm, _T_ECLIPSE('.') );
    	if(ch == NULL)
    		return VM_OTHER;
    	
    #ifdef _WIN32
    	if (_tcsicmp(ch, _T_ECLIPSE(".dll")) == 0)
    #else
    	if ((_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0))
    #endif
    	{
    		return VM_LIBRARY;
    	}
    	
    	if (_tcsicmp(ch, _T_ECLIPSE(".ee")) == 0)
    		return VM_EE_PROPS;
    	
    	return VM_OTHER;
    }
    
    /*
     * pathList is a pathSeparator separated list of paths, run each through
     * checkPath and recombine the results.
     * New memory is always allocated for the result
     */
    _TCHAR * checkPathList( _TCHAR* pathList, _TCHAR* programDir, int reverseOrder) {
    	_TCHAR * c1, *c2;
    	_TCHAR * checked, *result;
    	size_t checkedLength = 0, resultLength = 0;
    	size_t bufferLength = _tcslen(pathList);
    	
    	result = malloc(bufferLength * sizeof(_TCHAR));
    	c1 = pathList;
        while (c1 != NULL && *c1 != _T_ECLIPSE('\0'))
        {
        	c2 = _tcschr(c1, pathSeparator);
    		if (c2 != NULL)
    			*c2 = 0;
    		
    		checked = checkPath(c1, programDir, reverseOrder);
    		checkedLength = _tcslen(checked);
    		if (resultLength + checkedLength + 1> bufferLength) {
    			bufferLength += checkedLength + 1;
    			result = realloc(result, bufferLength * sizeof(_TCHAR));
    		}
    		
    		if(resultLength > 0) {
    			result[resultLength++] = pathSeparator;
    			result[resultLength] = _T_ECLIPSE('\0');
    		}
    		_tcscpy(result + resultLength, checked);
    		resultLength += checkedLength;
    		
    		if(checked != c1)
    			free(checked);
    		if(c2 != NULL)
    			*(c2++) = pathSeparator;
    		c1 = c2;
    	}
        
        return result;
    }
    
    _TCHAR * concatStrings(_TCHAR**strs) {
    	return concatPaths(strs, 0);
    }
    
    _TCHAR * concatPaths(_TCHAR** strs, _TCHAR separator) {
    	_TCHAR separatorString[] = { separator, 0 };
    	_TCHAR * result;
    	int i = -1;
    	size_t length = 0;
    	/* first count how large a buffer we need */
    	while (strs[++i] != NULL) {
    		length += _tcslen(strs[i]) + (separator != 0 ? 1 : 0);
    	}
    
    	result = malloc((length + 1) * sizeof(_TCHAR));
    	result[0] = 0;
    	i = -1;
    	while (strs[++i] != NULL) {
    		result = _tcscat(result, strs[i]);
    		if (separator != 0)
    			result = _tcscat(result, separatorString);
    	}
    	return result;
    }
    
    /*
     * buffer contains a pathSeparator separated list of paths, check 
     * that it contains all the paths given.  Each path is expected to be
     * terminated with a pathSeparator character.
     */
    int containsPaths(_TCHAR * str, _TCHAR** paths) {
    	_TCHAR * buffer;
    	_TCHAR * c;
    	int i;
    	
    	/* terminate the string with a pathSeparator */
    	buffer = malloc((_tcslen(str) + 2) * sizeof(_TCHAR));
    	_stprintf(buffer, _T_ECLIPSE("%s%c"), str, pathSeparator);
    	
    	for (i = 0; paths[i] != NULL; i++) {
    		c = _tcsstr(buffer, paths[i]);
    		if ( c == NULL || !(c == buffer || *(c - 1) == pathSeparator))
    		{
    			/* entry not found */
    			free(buffer);
    			return 0;
    		}
    	}
    	free(buffer);
    	return 1;
    }
    
    int isVMLibrary( _TCHAR* vm )
    {
    	_TCHAR *ch = NULL;
    	if (vm == NULL) return 0;
    	ch = _tcsrchr( vm, '.' );
    	if(ch == NULL)
    		return 0;
    #ifdef _WIN32
    	return (_tcsicmp(ch, _T_ECLIPSE(".dll")) == 0);
    #else
    	return (_tcsicmp(ch, _T_ECLIPSE(".so")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".jnilib")) == 0) || (_tcsicmp(ch, _T_ECLIPSE(".dylib")) == 0);
    #endif
    }
    
    #ifdef AIX
    
    #include <sys/types.h>
    #include <time.h>
    
    /* Return the JVM version in the format x.x.x 
     */
    char* getVMVersion( char *vmPath )
    {
        char   cmd[MAX_LINE_LENGTH];
        char   lineString[MAX_LINE_LENGTH];
        char*  firstChar;
        char   fileName[MAX_LINE_LENGTH];
        time_t curTime;
        FILE*  fp;
        int    numChars = 0;
        char*  version  = NULL;
    
    	/* Define a unique filename for the java output. */
        (void) time(&curTime);
        (void) sprintf(fileName, "/tmp/tmp%ld.txt", curTime);
    
        /* Write java -version output to a temp file */
        (void) sprintf(cmd,"%s -version 2> %s", vmPath, fileName);
        (void) system(cmd); 
    
        fp = fopen(fileName, "r");
        if (fp != NULL)
        {
        	/* Read java -version output from a temp file */
        	if (fgets(lineString, MAX_LINE_LENGTH, fp) == NULL)
        		lineString[0] = '\0';
        	fclose(fp);
        	unlink(fileName);
    
        	/* Extract version number */
        	firstChar = (char *) (strchr(lineString, '"') + 1);
        	if (firstChar != NULL)
        		numChars = (int)  (strrchr(lineString, '"') - firstChar);
        	
        	/* Allocate a buffer and copy the version string into it. */
        	if (numChars > 0)
        	{
        		version = malloc( numChars + 1 );
        		strncpy(version, firstChar, numChars);
    			version[numChars] = '\0';
    		}
    	}  
    
        return version;
    }
    
    /* Compare JVM Versions of the form "x.x.x..."
     *     
     *    Returns -1 if ver1 < ver2
     *    Returns  0 if ver1 = ver2 
     *    Returns  1 if ver1 > ver2
     */     
    int versionCmp(char *ver1, char *ver2)
    {
        char*  dot1;
        char*  dot2;
        int    num1;
        int    num2;
    
        dot1 = strchr(ver1, '.');
        dot2 = strchr(ver2, '.');
    
        num1 = atoi(ver1);
        num2 = atoi(ver2);
    
        if (num1 > num2)
        	return 1;
        	
    	if (num1 < num2)
    		return -1;
    	
    	if (dot1 && !dot2)   /* x.y > x */
            return 1;
    
        if (!dot1 && dot2)   /* x < x.y */
            return -1;
        
        if (!dot1 && !dot2)  /* x == x */
            return 0;
    
        return versionCmp((char*)(dot1 + 1), (char*)(dot2 + 1) );
    }
    #endif /* AIX */
    
posted @ 2020-10-06 18:04  nxgy  阅读(268)  评论(0编辑  收藏  举报