导航语音实现方案(文尾附有源码)
函数接口如下
char *textTranslate(char *content, …)
content:可变参列表中的固定参,包含占位符的字符串;
…:可变参数;
返回值:为替换后的字符串
使用时将占位符所代表的值解析后,按照content中占位符顺序依次传递给可变参数列表,函数即可返回content所代表的实际内容,用法同printf(char*, …);
结合配置文件,实现可配置语音组合模式
占位符定义
- 1 占位符定义
定义 |
含义 |
备注 |
@i |
整形数据 |
代表所有int型数据,最大为int取值范围,可表示距离/角度等 |
@s |
字符型数据 |
字符串,char* |
如“前方100米上坡”
content表示为:
- 2 “前方100米上坡”的通用述方式
前方 |
@i |
米 |
@s |
函数接口与配置文件
配合配置文件可实现语音组合的来灵活配置,配置文件配置示例如下:
[导航语音]
beginNavi = “开始导航,向北偏南@i度方向出发,全程共@i米”
distanceNotice = “当前已行使@i米,还剩@i米完成本次机动任务”
keyPoint1 = “前方@i米路口@s”
[关键点类型]
key1 = “左转”
key2 = “右转”
key3 = “左调头”
.
.
[桅杆告警]
mastWarning = “桅杆升起,请勿行车”
[偏航告警]
yawWarning = “您已偏离预定航线”
函数使用举例如下:
如播报配置文件中设置的开始导航语音条目:
beginNavi = “开始导航,向北偏南@a度方向出发,全程共@i米”时,调用方式如下:
beginNavi = textTranslate(beginNavi, 30, 100);
该函数将@a替换为30,@i替换为100,替换后的结果为:
beginNavi = “开始导航,向北偏南30度方向出发,全程共100米”
开发者只需要从配置文件中选择自己需要的条目,并将对应的数值传递按照顺序传递给textTranslate函数即可。
函数实现
Algorithm.h
#ifndef ALGORITHM_H
#define ALGORITHM_H
class Algorithm
{
public:
Algorithm();
char *textTranslate(char *format,...);//数字不能以0开头
private:
char *replaceHolder(char *&str, char *replace, int pos);
char *intToChar(int val);
};
#endif // ALGORITHM_H
Algorithm.cpp
#include "Algorithm.h"
#include <stdio.h>
#include<iostream>
#include<string.h>
#include<stdarg.h>
Algorithm::Algorithm()
{
}
char *Algorithm::replaceHolder(char *&str, char* replace ,int pos)
{
if(str == nullptr)
return nullptr;
int lenTotal = strlen(str);
int lenReplace;
if(!replace)
lenReplace = 0;
else
lenReplace = strlen(replace);
int lenTail = lenTotal - pos - 2;
char *strTotal = new char[lenTotal + lenReplace - 2 + 1];
char *strTail = new char[lenTail];
memcpy(strTail, str + pos + 2, lenTail);
memcpy(strTotal, str, lenTotal);
memcpy(strTotal + pos, replace, lenReplace);
memcpy(strTotal + pos + lenReplace, strTail, lenTail);
memcpy(strTotal + pos + lenReplace + lenTail, "\0",1);
delete[] strTail;
return strTotal;
}
char *Algorithm::textTranslate(char *format,...)
{
va_list ap;
char *p;
int ival;
char *s;
if(!format)
{
return nullptr;
}
va_start(ap,format);
int i = 0, j = 0;
loop:
for(i = j, p = format + i; *p; ++i, ++p)
{
if(*p != '@')
{
continue;
}
switch(*++p)
{
case 'i'://整形数据
ival = va_arg(ap,int);
s = intToChar(ival);
format = replaceHolder(format, s, i);
j = i + 1;
goto loop;
break;
case 's'://字符数据
s = va_arg(ap,char *);
format = replaceHolder(format,s,i);
j = i + 1;
goto loop;
break;
default:
break;
}
}
va_end(ap);
return format;
}
char *Algorithm::intToChar(int val)
{
char *str = nullptr;
int count = 0;
int localValue = val;
while(val%10 > 0)
{
count++;
val = val/10;
}
str = new char[count];
_itoa(localValue, str, 10);
return str;
}
调用测试
main .cpp
#include <QCoreApplication>
#include "algorithm.h"
#ifdef WINDOWS
#include<windows.h>
#endif
#ifdef UNIX
#include<sys\timeb.h>
#endif
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
#ifdef WINDOWS
DWORD tStart, tEnd;
tStart = GetTickCount();
#endif
Algorithm alg;
char *tempp="hello @s hello @s!\n@i\n@i";
char *aaa = alg.textTranslate(tempp,"world","windows",100,30);
cout<<"aaa="<< aaa<<endl;
#ifdef WINDOWS
tEnd = GetTickCount();
DWORD tPeriod = tEnd - tStart;
cout << "tStart=" << tStart << endl;
cout<< "tEnd=" << tEnd << endl;
cout << "period=" <<tPeriod<<endl;
#endif
return a.exec();
}
输出结果:
aaa=hello world hello windows!
100
30
tStart=259596406
tEnd=259596406
period=0