继续!!!
 
/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim (xtimor@gmail.com)
 * Licence: http://www.gnu.org/licenses/lgpl.html
 * $Id: tok.h 4 2007-08-27 13:11:03Z xtimor $
 *
 */
//对于这个tok,也不知道他的英文,我搜了一下:theory of knowledge,也不知合不合适
#ifndef __NMEA_TOK_H__
#define __NMEA_TOK_H__
#include "config.h"
#ifdef  __cplusplus    //所有的c的文件都加上了这个,方便c++的调用
extern "C" {
#endif
int     nmea_calc_crc(const char *buff, int buff_sz);   //这个是求校验值的
int     nmea_atoi(const char *str, int str_sz, int radix);  //这个一看就知char 2 int
double  nmea_atof(const char *str, int str_sz);
int     nmea_printf(char *buff, int buff_sz, const char *format, ...); //可变多参函数,具体看看c文件中是怎么实现的。
int     nmea_scanf(const char *buff, int buff_sz, const char *format, ...);
#ifdef  __cplusplus
}
#endif
#endif /* __NMEA_TOK_H__ */
 
 
/*
 *
 * NMEA library
 * URL: http://nmea.sourceforge.net
 * Author: Tim (xtimor@gmail.com)
 * Licence: http://www.gnu.org/licenses/lgpl.html
 * $Id: tok.c 17 2008-03-11 11:56:11Z xtimor $
 *
 */
/*! \file tok.h */
#include "nmea/tok.h"
#include <stdarg.h>    //可变多参函数就是在这里面
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>  //C 的 limits.h声明了整型的极限常量.头文件的库函数。我给你一个路径。==
D:\Microsoft Visual Studio\VC98\Include
你就是找这个include文件下就可以了。
#define NMEA_TOKS_COMPARE   (1)   //将format分解,如%02d
#define NMEA_TOKS_PERCENT   (2)
#define NMEA_TOKS_WIDTH     (3)
#define NMEA_TOKS_TYPE      (4)
/**
 * \brief Calculate control sum of binary buffer
 */
int nmea_calc_crc(const char *buff, int buff_sz)
{
    int chsum = 0,
        it;
    for(it = 0; it < buff_sz; ++it)
        chsum ^= (int)buff[it];            //这个算法很简单,抑或所有的字符
    return chsum;
}
/**
 * \brief Convert string to number
 */
int nmea_atoi(const char *str, int str_sz, int radix)
{
    char *tmp_ptr;
    char buff[NMEA_CONVSTR_BUF];  //这个宏定义在config.h
    int res = 0;
    if(str_sz < NMEA_CONVSTR_BUF)
    {
        memcpy(&buff[0], str, str_sz);  //使用mem函数,尽量不要用str函数
        buff[str_sz] = '\0';
        res = strtol(&buff[0], &tmp_ptr, radix);
    }
    return res;
}
/**
 * \brief Convert string to fraction number
 */
double nmea_atof(const char *str, int str_sz)
{
    char *tmp_ptr;
    char buff[NMEA_CONVSTR_BUF];
    double res = 0;
    if(str_sz < NMEA_CONVSTR_BUF)
    {
        memcpy(&buff[0], str, str_sz);
        buff[str_sz] = '\0';
        res = strtod(&buff[0], &tmp_ptr);
    }
    return res;
}
/**
 * \brief Formating string (like standart printf) with CRC tail (*CRC)
格式化字符串,在尾部加上一个crc校验值 
*/
 
//对于可变参数不了解的可以参考http://no001.blog.51cto.com/1142339/354252
int nmea_printf(char *buff, int buff_sz, const char *format, ...)
{
    int retval, add = 0;
    va_list arg_ptr;
    if(buff_sz <= 0)
        return 0;
    va_start(arg_ptr, format);
    retval = NMEA_POSIX(vsnprintf)(buff, buff_sz, format, arg_ptr);
//相当于_vsnprintf 用于像字符串中打印数据,数据格式用户自定义.
    if(retval > 0)
    {
        add = NMEA_POSIX(snprintf)(
            buff + retval, buff_sz - retval, "*%02x\r\n",
            nmea_calc_crc(buff + 1, retval - 1));
//加上校验值
//snprintf将可变个参数(...)按照format格式化成字符串,然后将其复制到str中.这里会变成_snprintf,但是没有这个函数,奇怪!!! 
    }
    retval += add;
    if(retval < 0 || retval > buff_sz)
    {
        memset(buff, ' ', buff_sz);
        retval = buff_sz;
    }
    va_end(arg_ptr);
    return retval;
}
/**
 * \brief Analyse string (specificate for NMEA sentences)
 */
int nmea_scanf(const char *buff, int buff_sz, const char *format, ...)
{
    const char *beg_tok;
    const char *end_buf = buff + buff_sz;  //这是怎么个用法?
    va_list arg_ptr;
    int tok_type = NMEA_TOKS_COMPARE;
    int width = 0;
    const char *beg_fmt = 0;
    int snum = 0, unum = 0;
    int tok_count = 0;
    void *parg_target;
    va_start(arg_ptr, format);
   
    for(; *format && buff < end_buf; ++format)
    {
        switch(tok_type)
        {
        case NMEA_TOKS_COMPARE:
            if('%' == *format)
                tok_type = NMEA_TOKS_PERCENT;
            else if(*buff++ != *format)
                goto fail;     //,如果再没有format语句,直接结束到最后
            break;
        case NMEA_TOKS_PERCENT:
            width = 0;
            beg_fmt = format;
            tok_type = NMEA_TOKS_WIDTH;
        case NMEA_TOKS_WIDTH:
            if(isdigit(*format))
                break;
            {
                tok_type = NMEA_TOKS_TYPE;
                if(format > beg_fmt)
                    width = nmea_atoi(beg_fmt, (int)(format - beg_fmt), 10);
            }
        case NMEA_TOKS_TYPE:
            beg_tok = buff;
            if(!width && ('c' == *format || 'C' == *format) && *buff != format[1])
                width = 1;
            if(width)
            {
                if(buff + width <= end_buf)
                    buff += width;
                else
                    goto fail;
            }
            else
            {
                if(!format[1] || (0 == (buff = (char *)memchr(buff, format[1], end_buf - buff))))
                    buff = end_buf;
            }
            if(buff > end_buf)
                goto fail;
            tok_type = NMEA_TOKS_COMPARE;
            tok_count++;
            parg_target = 0; width = (int)(buff - beg_tok);
            switch(*format)    //对于格式的区分,具体实现细节繁琐
            { 
            case 'c':
            case 'C':
                parg_target = (void *)va_arg(arg_ptr, char *);
                if(width && 0 != (parg_target))
                    *((char *)parg_target) = *beg_tok;
                break;
            case 's':
            case 'S':
                parg_target = (void *)va_arg(arg_ptr, char *);
                if(width && 0 != (parg_target))
                {
                    memcpy(parg_target, beg_tok, width);
                    ((char *)parg_target)[width] = '\0';
                }
                break;
            case 'f':
            case 'g':
            case 'G':
            case 'e':
            case 'E':
                parg_target = (void *)va_arg(arg_ptr, double *);
                if(width && 0 != (parg_target))
                    *((double *)parg_target) = nmea_atof(beg_tok, width);
                break;
            };
            if(parg_target)
                break;
            if(0 == (parg_target = (void *)va_arg(arg_ptr, int *)))
                break;
            if(!width)
                break;
            switch(*format)
            {
            case 'd':
            case 'i':
                snum = nmea_atoi(beg_tok, width, 10);
                memcpy(parg_target, &snum, sizeof(int));
                break;
            case 'u':
                unum = nmea_atoi(beg_tok, width, 10);
                memcpy(parg_target, &unum, sizeof(unsigned int));
                break;
            case 'x':
            case 'X':
                unum = nmea_atoi(beg_tok, width, 16);
                memcpy(parg_target, &unum, sizeof(unsigned int));
                break;
            case 'o':
                unum = nmea_atoi(beg_tok, width, 8);
                memcpy(parg_target, &unum, sizeof(unsigned int));
                break;
            default:
                goto fail;
            };
            break;
        };
    }
fail:
    va_end(arg_ptr);
    return tok_count;
}