1、strstr()

C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。

参考:C 库函数 - strstr()

#include <stdio.h>
#include <string.h>
int main() {
	char dest[] = "Hello A World";
	char sour[] = "A";
	char sour1 = 'A';
	char *temp;
	int  temp1;
	temp=strstr(dest, sour);
	printf("temp=%s\n",temp);
	temp = strrchr(dest, sour1);
	printf("temp=%s\n", temp);
	temp1 = strcmp(dest, sour);
	printf("temp=%d\n", temp1);
	return 0;
}

输出:

如果没有查找到,返回null

	//测试strstr
	char dest[] = "Hello A World";
	char sour[] = "A";
	char sour1 = 'Z';
	char *Temp;
	int  temp1;
	Temp = strstr(dest, sour);
	printf("Temp=%s\n", Temp);
	Temp = strrchr(dest, sour1);
	printf("Temp=%s\n", Temp);
	temp1 = strcmp(dest, sour);
	printf("temp1=%d\n", temp1);

2、strrchr() 和 strchr()

(1)strrchr()

#include "string"  
char *strrchr( const char *str, int ch );

 功能:函数返回一个指针,它指向字符ch 在字符串str末次/最后出现的位置,如果匹配失败,返回NULL。

extern int readpcv(const char *file, pcvs_t *pcvs)
{
    pcv_t *pcv;
    char *ext;
    int i,stat;
    
    trace(3,"readpcv: file=%s\n",file);
    /*char *strrchr( const char *str, int ch );
	功能:函数返回一个指针,它指向字符ch 在字符串str末次出现的位置,如果匹配失败,返回NULL。*/
    if (!(ext=strrchr(file,'.'))) ext="";
    
    if (!strcmp(ext,".atx")||!strcmp(ext,".ATX")) {
        stat=readantex(file,pcvs);
    }
    else {
        stat=readngspcv(file,pcvs);
    }

读取接收机和卫星天线文件中,使用!

(2) strchr()

char *strchr(const char *str, int c)
参数
 
    str -- 要被检索的 C 字符串。
    c -- 在 str 中要搜索的字符。
 
返回值
 
该函数返回在字符串 str 中第一次出现字符 c 的位置,如果未找到该字符则返回 NULL。

C 库函数 char *strchr(const char *str, int c) 在参数 str 所指向的字符串中搜索第一次/开始位置出现字符 c(一个无符号字符)的位置。

示例代码:

#include <stdio.h>
#include <string.h>
 
int main ()
{
   const char str[] = "http://www.runoob.com";
   const char ch = '.';
   char *ret;
 
   ret = strchr(str, ch);
 
   printf("|%c| 之后的字符串是 - |%s|\n", ch, ret);
   
   return(0);
}

运行结果:

|.| 之后的字符串是 - |.runoob.com|
复制

C 库函数 - strchr()

3、strcmp()

#include <string.h>
  int strcmp( const char *str1, const char *str2 );

功能:比较字符串str1 和 str2, 返回值如下:

返回值

解释

less than 0

str1 is less than str2

equal to 0

str1 is equal to str2

greater than 0

str1 is greater than str2


 for (j = k = nf = 0; j < n; j++) {
 
	ext = strrchr(infile[j], '.');
 
	if (ext && (!strcmp(ext, ".rtcm3") || !strcmp(ext, ".RTCM3"))) {
		strcpy(ifile[nf++], infile[j]);
	}
	else {
		/* include next day precise ephemeris or rinex brdc nav */
		ttte = tte;
		if (ext && (!strcmp(ext, ".sp3") || !strcmp(ext, ".SP3") ||
			!strcmp(ext, ".eph") || !strcmp(ext, ".EPH"))) {
			ttte = timeadd(ttte, 3600.0);
		}
		else if (strstr(infile[j], "brdc")) {
			ttte = timeadd(ttte, 7200.0);
		}
		nf += reppaths(infile[j], ifile + nf, MAXINFILE - nf, tts, ttte, "", "");
	}
	while (k < nf) index[k++] = j;
 
	if (nf >= MAXINFILE) {
		trace(2, "too many input files. trancated\n");
		break;
	}
}

简单总结下三个函数:

函数原型:

 int strcmp( const char *str1, const char *str2 );
 char *strrchr( const char *str, int ch );
 char *strstr( const char *str1, const char *str2 );

看两点:str2参数不同,返回值不同;

strncpy()

C 库函数 char *strncpy(char *dest, const char *src, size_t n) 把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。

https://www.runoob.com/cprogramming/c-function-strncpy.html

注:需要自己加上’\0‘;

4、定义一个指针数组,*ifile[MAXINFILE]

#define MAXINFILE   1000         /* max number of input files */
char *ifile[MAXINFILE]         //指针数组
for (i=0;i<n;i++) {
            if (!(ifile[i]=(char *)malloc(1024))) {
                free(base_); for (;i>=0;i--) free(ifile[i]);
                freepreceph(&navs,&sbss,&lexs);
                return 0;
            }
        }
/* free prec ephemeris and sbas data -----------------------------------------*/
static void freepreceph(nav_t *nav, sbs_t *sbs, lex_t *lex)
{
    int i;
    
    trace(3,"freepreceph:\n");
    
    free(nav->peph); nav->peph=NULL; nav->ne=nav->nemax=0;
    free(nav->pclk); nav->pclk=NULL; nav->nc=nav->ncmax=0;
    free(nav->fcb ); nav->fcb =NULL; nav->nf=nav->nfmax=0;
    free(nav->seph); nav->seph=NULL; nav->ns=nav->nsmax=0;
    free(sbs->msgs); sbs->msgs=NULL; sbs->n =sbs->nmax =0;
    free(lex->msgs); lex->msgs=NULL; lex->n =lex->nmax =0;
    for (i=0;i<nav->nt;i++) {
        free(nav->tec[i].data);
        free(nav->tec[i].rms );
    }
    free(nav->tec ); nav->tec =NULL; nav->nt=nav->ntmax=0;
    
    if (fp_rtcm) fclose(fp_rtcm);
    free_rtcm(&rtcm);
}

将指针数组中的每一个元素(指针),通过malloc函数,在堆区进行内存分配;如果分配任意一个没有分配成功,则free释放结构体变量(base_、ifile[i]、navs、sbss、lexs)

5、如果在VS中进行后处理,将ts、te设置为0,RTKLIB识别开始和结束时间在:

一般我们将其设置为0,如下所示:

gtime_t ts = { 0 }, te = { 0 };

当RTKLIB读取完obs、nav之后,

/* read obs and nav data -----------------------------------------------------*/
static int readobsnav(gtime_t ts, gtime_t te, double ti, char **infile,
                      const int *index, int n, const prcopt_t *prcopt,
                      obs_t *obs, nav_t *nav, sta_t *sta)

6、RTKLIB提供了Output Debug Trace (OFF Level1-5)

如果在VS中我们打开了Debug Trace,那么函数内部开始运行及将相关调试信息保存到文件中;调试开始的代码位于:

位于:static int execses(……)中

/* execute processing session ------------------------------------------------*/
static int execses(gtime_t ts, gtime_t te, double ti, const prcopt_t *popt,
                   const solopt_t *sopt, const filopt_t *fopt, int flag,
                   char **infile, const int *index, int n, char *outfile)
{
    FILE *fp;
    prcopt_t popt_=*popt;
    char tracefile[1024],statfile[1024],path[1024],*ext;
    
    trace(3,"execses : n=%d outfile=%s\n",n,outfile);
    
    /* open debug trace */
    if (flag&&sopt->trace>0) {
        if (*outfile) {
            strcpy(tracefile,outfile);
            strcat(tracefile,".trace"); //原输出文件名,后加.trace
        }
        else {
            strcpy(tracefile,fopt->trace);
        }
        traceclose();
        traceopen(tracefile); //开始对 trace文件进行写处理
        tracelevel(sopt->trace);
    }

 位于:static int execses(……)中

/* solution statistics level (0:off,1:states,2:residuals) */

输出结果统计文件:

    /* open solution statistics */
    if (flag&&sopt->sstat>0) {
        strcpy(statfile,outfile);
        strcat(statfile,".stat");
        rtkclosestat();
        rtkopenstat(statfile,sopt->sstat);
    }

7、strstr(infile[i],"%r")

C 库函数 char *strstr(const char *haystack, const char *needle) 在字符串 haystack 中查找第一次出现字符串 needle 的位置,不包含终止符 '\0'。

 readpreceph函数中,如下代码片段:

    /* read precise ephemeris files */
    for (i=0;i<n;i++) {
        if (strstr(infile[i],"%r")||strstr(infile[i],"%b")) continue;
        readsp3(infile[i],nav,0);
    }
    /* read precise clock files */
    for (i=0;i<n;i++) {
        if (strstr(infile[i],"%r")||strstr(infile[i],"%b")) continue;
        readrnxc(infile[i],nav);
    }
    /* read satellite fcb files */
    for (i=0;i<n;i++) {
        if (strstr(infile[i],"%r")||strstr(infile[i],"%b")) continue;
        if ((ext=strrchr(infile[i],'.'))&&
            (!strcmp(ext,".fcb")||!strcmp(ext,".FCB"))) {
            readfcb(infile[i],nav);
        }
    }

 如果输入文件中,含有基站和流动站的通配符:

if (strstr(infile[i],"%r")||strstr(infile[i],"%b")) continue;

8、reppath函数:

/* replace keywords in file path -----------------------------------------------
* replace keywords in file path with date, time, rover and base station id
* args   : char   *path     I   file path (see below)
*          char   *rpath    O   file path in which keywords replaced (see below)
*          gtime_t time     I   time (gpst)  (time.time==0: not replaced)
*          char   *rov      I   rover id string        ("": not replaced)
*          char   *base     I   base station id string ("": not replaced)
* return : status (1:keywords replaced, 0:no valid keyword in the path,
*                  -1:no valid time)
* notes  : the following keywords in path are replaced by date, time and name
*              %Y -> yyyy : year (4 digits) (1900-2099)
*              %y -> yy   : year (2 digits) (00-99)
*              %m -> mm   : month           (01-12)
*              %d -> dd   : day of month    (01-31)
*              %h -> hh   : hours           (00-23)
*              %M -> mm   : minutes         (00-59)
*              %S -> ss   : seconds         (00-59)
*              %n -> ddd  : day of year     (001-366)
*              %W -> wwww : gps week        (0001-9999)
*              %D -> d    : day of gps week (0-6)
*              %H -> h    : hour code       (a=0,b=1,c=2,...,x=23)
*              %ha-> hh   : 3 hours         (00,03,06,...,21)
*              %hb-> hh   : 6 hours         (00,06,12,18)
*              %hc-> hh   : 12 hours        (00,12)
*              %t -> mm   : 15 minutes      (00,15,30,45)
*              %r -> rrrr : rover id
*              %b -> bbbb : base station id
*-----------------------------------------------------------------------------*/
extern int reppath(const char *path, char *rpath, gtime_t time, const char *rov,
                   const char *base)

如果输入文件(file)中,含有通配符,则 reppath函数的目的就是将file[]文件名中的通配符进行替换,保存到rpath中;这个根据输入的文件名是否含通配符而定!

9、向量内积(点乘)和外积(叉乘)

概括地说,向量的内积(点乘/数量积)。对两个向量执行点乘运算,就是对这两个向量对应位一一相乘之后求和的操作,如下所示,对于向量a和向量b:

a和b的点积公式为:

这里要求一维向量a和向量b的行列数相同。注意:点乘的结果是一个标量(数量而不是向量)

向量的外积(叉乘)

概括地说,两个向量的外积,又叫叉乘、叉积向量积,其运算结果是一个向量而不是一个标量。并且两个向量的外积与这两个向量组成的坐标平面垂直。

定义:向量a与b的外积a×b是一个向量,其长度等于|a×b| = |a||b|sin∠(a,b),其方向正交于a与b。并且,(a,b,a×b)构成右手系。
特别地,0×a = a×0 = 0.此外,对任意向量a,a×a=0。

对于向量a和向量b:

a和b的外积公式为:

其中:

根据i、j、k间关系,有:

向量内积(点乘)和外积(叉乘)概念及几何意义

RTKLIB中 求向量范数:先内积,然后开方

/* euclid norm  欧几里得范数,说白了,就是同一个向量点乘后开方,求向量长度-----------------------------------------------------------------
* euclid norm of vector
* args   : double *a        I   vector a (n x 1)
*          int    n         I   size of vector a
* return : || a ||
*-----------------------------------------------------------------------------*/
extern double norm(const double *a, int n)
{
    return sqrt(dot(a,a,n));
}

RTKLIB叉乘实现:

/* outer product of 3d vectors 叉积 外积-------------------------------------------------
* outer product of 3d vectors 
* args   : double *a,*b     I   vector a,b (3 x 1)
*          double *c        O   outer product (a x b) (3 x 1)
* return : none
*-----------------------------------------------------------------------------*/
extern void cross3(const double *a, const double *b, double *c)
{
    c[0]=a[1]*b[2]-a[2]*b[1];
    c[1]=a[2]*b[0]-a[0]*b[2];
    c[2]=a[0]*b[1]-a[1]*b[0];
}

10、涉及的矩阵运算

 #include <string.h>
  void *memcpy( void *to, const void *from, size_t count );

 功能:函数从from中复制count 个字符到to中,并返回to指针。 如果to 和 from 重叠,则函数行为不确定。

/* copy matrix -----------------------------------------------------------------
* copy matrix 将B矩阵的值,复制到A中,所以传入两个矩阵
* args   : double *A        O   destination matrix A (n x m)
*          double *B        I   source matrix B (n x m)
*          int    n,m       I   number of rows and columns of matrix
* return : none
*-----------------------------------------------------------------------------*/
extern void matcpy(double *A, const double *B, int n, int m)
{
    memcpy(A,B,sizeof(double)*n*m);
}

11、setstr()

函数将 src字符串中长度为n的字串,复制给dst,长度必须小于strlen(dst),但是无论n为多少,dst的内容都被覆盖,详情见示例!

/* set string without tail space ---------------------------------------------*/
static void setstr(char *dst, const char *src, int n)
{
    char *p=dst;
    const char *q=src;
    while (*q&&q<src+n) *p++=*q++;
    *p--='\0';
    while (p>=dst&&*p==' ') *p--='\0';
}

示例程序:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/* set string without tail space ---------------------------------------------*/
static void setstr(char *dst, const char *src, int n)
{
	char *p = dst;
	const char *q = src;
	while (*q&&q < src + n) *p++ = *q++;
	*p-- = '\0';
	while (p >= dst && *p == ' ') *p-- = '\0';
}
int main()
{
	char A[] = "VVVVVVVV";
	char B[] = "Am er ican Welcome";
	setstr(A,B,strlen(A));
	printf("A[]=%s\n", A);
	printf("B[]=%s\n", B);
	char C[] = "VVVVVVVV";
	char D[] = "Am er ican Welcome";
	setstr(C, D, 5);
	printf("C[]=%s\n",C);
	printf("D[]=%s\n",D);
	return 0;
}

运行结果:

12、static int cmpobs(const void *p1,const void *p2)

其中cmpobs是C标准库的函数;函数的定义如下:

功能: 使用快速排序例程进行排序
头文件:stdlib.h
用法:  void qsort(void* base, size_t num, size_t width, int(__cdecl*compare)(const void*,const void*));
参数:

  • 待排序数组,排序之后的结果仍放在这个数组中
  • 数组中待排序元素数量
  • 各元素的占用空间大小(单位为字节)
  • 指向函数的指针,用于确定排序的顺序(需要用户自定义一个比较函数)
     

代码如下:

qsort(obs->data,obs->n,sizeof(obsd_t),cmpobs);
 
/* compare observation data -------------------------------------------------*/
static int cmpobs(const void *p1, const void *p2)
{
    obsd_t *q1=(obsd_t *)p1,*q2=(obsd_t *)p2;
    double tt=timediff(q1->time,q2->time);
    if (fabs(tt)>DTTOL) return tt<0?-1:1;
    if (q1->rcv!=q2->rcv) return (int)q1->rcv-(int)q2->rcv;
    return (int)q1->sat-(int)q2->sat;
}

13、结构体中含有字符数组,用指向结构体的指针赋初值

结构体sta_t里面有 字符数组、int 、double类型;因此通过指向sta_t结构体类型的指针,对结构体进行初始化(赋初值)时,字符数组的名字是个地址,也即看作指针;因此,

*sta->name='\0'; //成员数组的名字是个地址,需要使用”*“解引用,即把‘\0’赋值给这个数组的第0个成员(首位置处)

或一般把字符串赋值给一个结构体成员,使用memcpy

示例代码:

#include <iostream>
using namespace std;
#define  MAXANT 1024
 
typedef struct {        /* station parameter type */
	char name[MAXANT]; /* marker name */
	char marker[MAXANT]; /* marker number */
	char antdes[MAXANT]; /* antenna descriptor */
	char antsno[MAXANT]; /* antenna serial number */
	char rectype[MAXANT]; /* receiver type descriptor */
	char recver[MAXANT]; /* receiver firmware version */
	char recsno[MAXANT]; /* receiver serial number */
	int antsetup;       /* antenna setup id */
	int itrf;           /* ITRF realization year */
	int deltype;        /* antenna delta type (0:enu,1:xyz) */
	double pos[3];      /* station position (ecef) (m) */
	double del[3];      /* antenna position delta (e/n/u or x/y/z) (m) */
	double hgt;         /* antenna height (m) */
} sta_t;
/* initialize station parameter ----------------------------------------------*/
static void init_sta(sta_t *sta)
{
	int i;
	/* 	*/
	*sta->name = '\0'; // -> 优先级 高于 *
	*sta->marker = '\0';
	*sta->antdes = '\0';
	*sta->antsno = '\0';
	*sta->rectype = '\0';
	*sta->recver = '\0';
	*sta->recsno = '\0';
 
	sta->antsetup = sta->itrf = sta->deltype = 0;
	for (i = 0; i < 3; i++) sta->pos[i] = 0.0;
	for (i = 0; i < 3; i++) sta->del[i] = 0.0;
	sta->hgt = 0.0;
}
int main() {
 
	sta_t Sta;
	sta_t *sta = &Sta;
	if (sta) init_sta(sta);  /* station parameter type */
	/*
	char str[MAXANT];
	*str = '\0';
	*/
	/*
	char *p_str = str;
	p_str = (char *)"字符数组";
	*/
	system("pause");
	return 0;
}

14、getbits和getbitu函数

/* extract unsigned/signed bits ------------------------------------------------
* extract unsigned/signed bits from byte data
* args   : unsigned char *buff I byte data
*          int    pos    I      bit position from start of data (bits)
*          int    len    I      bit length (bits) (len<=32)
* return : extracted unsigned/signed bits
*-----------------------------------------------------------------------------*/
extern unsigned int getbitu(const unsigned char *buff, int pos, int len)
{
    unsigned int bits=0;
    int i;
    for (i=pos;i<pos+len;i++) bits=(bits<<1)+((buff[i/8]>>(7-i%8))&1u); //1U 表示无符号整型1
    return bits;
}
extern int getbits(const unsigned char *buff, int pos, int len)
{
    unsigned int bits=getbitu(buff,pos,len);
    if (len<=0||32<=len||!(bits&(1u<<(len-1)))) return (int)bits;
    return (int)(bits|(~0u<<len)); /* extend sign */
}

都是从多少位里面获取数据,getbitu是获取无符号32位的数据;getbits是获取32位有符号的数据。

其中,POS为起始位,len为位数长度;

示例代码:

#include <stdio.h>
/* extract unsigned/signed bits ------------------------------------------------
* extract unsigned/signed bits from byte data
* args   : unsigned char *buff I byte data
*          int    pos    I      bit position from start of data (bits)
*          int    len    I      bit length (bits) (len<=32)
* return : extracted unsigned/signed bits
*-----------------------------------------------------------------------------*/
extern unsigned int getbitu(const unsigned char *buff, int pos, int len)
{
	unsigned int bits = 0;
	int i;
	for (i = pos; i < pos + len; i++) bits = (bits << 1) + ((buff[i / 8] >> (7 - i % 8)) & 1u); //1U 表示无符号整型1
	//printf("getbitu 函数 bits=%d\n", bits);
	return bits;
	
}
extern int getbits(const unsigned char *buff, int pos, int len)
{
	unsigned int bits = getbitu(buff, pos, len);
	if (len <= 0 || 32 <= len || !(bits&(1u << (len - 1)))) return (int)bits;
	 
	return (int)(bits | (~0u << len)); /* extend sign */
}
/* get signed 38bit field ----------------------------------------------------*/
static double getbits_38(const unsigned char *buff, int pos)
{
	return (double)getbits(buff, pos, 32)*64.0 + getbitu(buff, pos + 32, 6);
}
int main() {
	//1005数据(基站位置)
	unsigned char str[] = { 0XD3, 0X00, 0X13, 0X3E, 0XD7, 0XD3, 0X02, 0X02, 0X98, 0X0E, 0XDE, 0XEF, 0X34, 0XB4, 0XBD, 0X62, 0XAC, 0X09, 0X41, 0X98, 0X6F, 0X33, 0X36, 0X0B, 0X98 };
	int i = 24, j, staid, itrf,messageID;
	double rr[3], re[3], pos[3];
	
	messageID= getbitu(str, i, 12); i += 12; //信息类型
	staid = getbitu(str, i, 12); i += 12; //基准站ID
	itrf = getbitu(str, i, 6); i += 6 + 4; //
	rr[0] = getbits_38(str, i); i += 38 + 2; //天线位置X (ECEF坐标)
	rr[1] = getbits_38(str, i); i += 38 + 2; //天线位置Y (ECEF坐标)
	rr[2] = getbits_38(str, i);   //天线位置Z (ECEF坐标)
 
	printf("messageID=%d staid =%d\n", messageID, staid);
	printf("ECEF下天线位置:%d %d %d\n", rr[0], rr[1], rr[2]);
 
	system("pause");
	return 0;
}

运行结果:

 

15、setbits和setbitu函数

/* set unsigned/signed bits ----------------------------------------------------
* set unsigned/signed bits to byte data
* args   : unsigned char *buff IO byte data
*          int    pos    I      bit position from start of data (bits)
*          int    len    I      bit length (bits) (len<=32)
*         (unsigned) int I      unsigned/signed data
* return : none
*-----------------------------------------------------------------------------*/
extern void setbitu(unsigned char *buff, int pos, int len, unsigned int data)
{
    unsigned int mask=1u<<(len-1);
    int i;
    if (len<=0||32<len) return;
    for (i=pos;i<pos+len;i++,mask>>=1) {
        if (data&mask) buff[i/8]|=1u<<(7-i%8); else buff[i/8]&=~(1u<<(7-i%8));
    }
}
extern void setbits(unsigned char *buff, int pos, int len, int data)
{
    if (data<0) data|=1<<(len-1); else data&=~(1<<(len-1)); /* set sign bit */
    setbitu(buff,pos,len,(unsigned int)data);
}

参考链接:

1、学习rtklib(一)

2、C语言qsort函数用法


转载自:https://blog.csdn.net/wuwuku123/article/details/104836779