導航語音實現方案(文尾附有源碼)
函數接口如下
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