Mex type C file to normal C file - c

I have a c file written using mex functions, run by Matlab using mex compiler Now I want to run those mex type .c files without Matlab environment. So, is there any way to convert mex type .c file to normal .c file ? Or any other options available for the above mentioned concern.
Thanks in advance....!
Here is the one mex type .c file for sample.
#include <stdlib.h>
#include "mex.h"
#include "matrix.h"
#include "distances.h"
#include "ltl2tree.h"
#include "param.h"
#define BUFF_LEN 4096
char * emalloc(size_t n)
{
char *tmp;
if (!(tmp = (char *) mxMalloc(n)))
mexErrMsgTxt("mx_dp_taliro: not enough memory!");
memset(tmp, 0, n);
return tmp;
}
int tl_Getchar(int *cnt, size_t hasuform, char *uform)
{
if (*cnt < hasuform)
return uform[(*cnt)++];
(*cnt)++;
return -1;
}
void tl_UnGetchar(int *cnt)
{
if (*cnt > 0) (*cnt)--;
}
#define Binop(a) \
fprintf(miscell->tl_out, "("); \
dump(n->lft, miscell); \
fprintf(miscell->tl_out, a); \
dump(n->rgt, miscell); \
fprintf(miscell->tl_out, ")")
static void sdump(Node *n, char *dumpbuf)
{
switch (n->ntyp) {
case PREDICATE: strcat(dumpbuf, n->sym->name);
break;
case U_OPER: strcat(dumpbuf, "U");
goto common2;
case V_OPER: strcat(dumpbuf, "V");
goto common2;
case OR: strcat(dumpbuf, "|");
goto common2;
case AND: strcat(dumpbuf, "&");
common2: sdump(n->rgt,dumpbuf);
common1: sdump(n->lft,dumpbuf);
break;
case NEXT: strcat(dumpbuf, "X");
goto common1;
case NOT: strcat(dumpbuf, "!");
goto common1;
case TRUE: strcat(dumpbuf, "T");
break;
case FALSE: strcat(dumpbuf, "F");
break;
default: strcat(dumpbuf, "?");
break;
}
}
Symbol *DoDump(Node *n, char *dumpbuf, Miscellaneous *miscell)
{
if (!n) return ZS;
if (n->ntyp == PREDICATE)
return n->sym;
dumpbuf[0] = '\0';
sdump(n,dumpbuf);
return tl_lookup(dumpbuf, miscell);
}
void dump(Node *n, Miscellaneous *miscell)
{
if (!n) return;
switch(n->ntyp) {
case OR: Binop(" || "); break;
case AND: Binop(" && "); break;
case U_OPER: Binop(" U "); break;
case V_OPER: Binop(" V "); break;
case NEXT:
fprintf(miscell->tl_out, "X");
fprintf(miscell->tl_out, " (");
dump(n->lft, miscell);
fprintf(miscell->tl_out, ")");
break;
case NOT:
fprintf(miscell->tl_out, "!");
fprintf(miscell->tl_out, " (");
dump(n->lft, miscell);
fprintf(miscell->tl_out, ")");
break;
case FALSE:
fprintf(miscell->tl_out, "false");
break;
case TRUE:
fprintf(miscell->tl_out, "true");
break;
case PREDICATE:
fprintf(miscell->tl_out, "(%s)", n->sym->name);
break;
case -1:
fprintf(miscell->tl_out, " D ");
break;
default:
printf("Unknown token: ");
tl_explain(n->ntyp);
break;
}
}
void tl_explain(int n)
{
switch (n) {
case ALWAYS: printf("[]"); break;
case EVENTUALLY: printf("<>"); break;
case IMPLIES: printf("->"); break;
case EQUIV: printf("<->"); break;
case PREDICATE: printf("predicate"); break;
case OR: printf("||"); break;
case AND: printf("&&"); break;
case NOT: printf("!"); break;
case U_OPER: printf("U"); break;
case V_OPER: printf("V"); break;
case NEXT: printf("X"); break;
case TRUE: printf("true"); break;
case FALSE: printf("false"); break;
case ';': printf("end of formula"); break;
default: printf("%c", n); break;
}
}
static void non_fatal(char *s1, char *s2, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
int i;
printf("TaLiRo: ");
if (s2)
printf(s1, s2);
else
printf(s1);
if ((*tl_yychar) != -1 && (*tl_yychar) != 0)
{ printf(", saw '");
tl_explain((*tl_yychar));
printf("'");
}
printf("\nTaLiRo: %s\n---------", uform);
for (i = 0; i < (*cnt); i++)
printf("-");
printf("^\n");
fflush(stdout);
(miscell->tl_errs)++;
}
void
tl_yyerror(char *s1, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
Fatal(s1, (char *) 0, cnt, uform, tl_yychar, miscell);
}
void
Fatal(char *s1, char *s2, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
non_fatal(s1, s2, cnt, uform, tl_yychar, miscell);
tl_exit(0);
}
void fatal(char *s1, char *s2, int *cnt, char *uform, int *tl_yychar, Miscellaneous *miscell)
{
non_fatal(s1, s2, cnt, uform, tl_yychar, miscell);
tl_exit(0);
}
void put_uform(char *uform, Miscellaneous *miscell)
{
fprintf(miscell->tl_out, "%s", uform);
}
void tl_exit(int i)
{
mexErrMsgTxt("mx_dp_taliro: unexpected error, tl_exit executed.");
}
void mexFunction(int nlhs, mxArray *plhs[],int nrhs, const mxArray *prhs[])
{
/* Variables needed to process the input */
int status, pstatus;
mwSize buflen, pbuflen;
size_t NElems,NCells;
mwSize ndimA, ndimb, ndimG, ndim, pdim,ndimP;
const mwSize *dimsA, *dimsb, *dimsG, *dims, *pardims,*dimsP;
mwIndex jstruct, iii, jjj, i1, j1, idx_j;
mxArray *tmp,*tmp1,*tmp_cell;
/* Variables needed for monitor */
Node *node;
double *XTrace, *TStamps, *LTrace;
DistCompData distData;
PMap *predMap;
int ii,jj,kk,ll,objs,tempI;
bool par_on;
bool is_Multi_HA;
bool initial_of_par;
int npred, npar;
static char uform[BUFF_LEN];
static size_t hasuform=0;
static int *cnt;
int temp = 0;
Miscellaneous *miscell = (Miscellaneous *) emalloc(sizeof(Miscellaneous));
int *tl_yychar = (int *) emalloc(sizeof(int));
miscell->dp_taliro_param.LTL = 1;
miscell->dp_taliro_param.ConOnSamples = 0;
miscell->dp_taliro_param.SysDim = 0;
miscell->dp_taliro_param.nSamp = 0;
miscell->dp_taliro_param.nPred = 0;
miscell->dp_taliro_param.true_nPred = 0;
miscell->dp_taliro_param.tnLoc = 0;
miscell->dp_taliro_param.nInp = 0;
miscell->dp_taliro_param.nCLG = 0;
miscell->tl_errs = 0;
miscell->type_temp = 0;
/* Reset cnt to 0:
cnt is the counter that points to the next symbol in the formula
to be processed. This is a static variable and it retains its
value between Matlab calls to mx_dp_taliro. */
cnt = &temp;
/* Other initializations */
miscell->dp_taliro_param.nInp = nrhs;
par_on = false;
initial_of_par = false;
npred = 0;
npar= 0;
/* Make sure the I/O are in the right form */
if(nrhs < 3)
mexErrMsgTxt("mx_dp_taliro: At least 3 inputs are required.");
else if(nlhs > 1)
mexErrMsgTxt("mx_dp_taliro: Too many output arguments.");
else if(nrhs > 8)
mexErrMsgTxt("mx_dp_taliro: Too many input arguments.");
else if(!mxIsChar(prhs[0]))
mexErrMsgTxt("mx_dp_taliro: 1st input must be a string with TL formula.");
else if(!mxIsStruct(prhs[1]))
mexErrMsgTxt("mx_dp_taliro: 2nd input must be a structure (predicate map).");
else if(!mxIsDouble(prhs[2]))
mexErrMsgTxt("mx_dp_taliro: 3rd input must be a numerical array (State trace).");
else if(nrhs>3 && !mxIsDouble(prhs[3]))
mexErrMsgTxt("mx_dp_taliro: 4th input must be a numerical array (Time stamps).");
else if(nrhs>5 && !mxIsDouble(prhs[4]))
mexErrMsgTxt("mx_dp_taliro: 5th input must be a numerical array (Location trace).");
else if(nrhs>5 && !(mxIsDouble(prhs[5])||mxIsCell(prhs[5])))
mexErrMsgTxt("mx_dp_taliro: 6th input must be a numerical array \n (Minimum path distance to each control location for each predicate).");
else if(nrhs>7 && !(mxIsCell(prhs[6])))
mexErrMsgTxt("mx_dp_taliro: 7th input must be a cell array (Adjacency list).");
else if(nrhs>7 && !(mxIsStruct(prhs[7])||mxIsCell(prhs[7])))
mexErrMsgTxt("mx_dp_taliro: 8th input must be a structure (guard map).");
if(nlhs > 1)
mexErrMsgTxt("Too many output arguments.");
plhs[0] = mxCreateDoubleMatrix(1,1,mxREAL);
/* Process inputs */
/* Get the formula */
ndim = mxGetNumberOfDimensions(prhs[0]);
dims = mxGetDimensions(prhs[0]);
buflen = dims[1]*sizeof(mxChar)+1;
if (buflen >= BUFF_LEN)
{
mexPrintf("%s%d%s\n", "The formula must be less than ", BUFF_LEN," characters.");
mexErrMsgTxt("mx_dp_taliro: Formula too long.");
}
status = mxGetString(prhs[0], uform, buflen);
hasuform = strlen(uform);
for (iii=0; iii<hasuform; iii++)
{
if (uform[iii] == '\t' || uform[iii] == '\"' || uform[iii] == '\n')
uform[iii] = ' ';
}
/* Get state trace */
ndim = mxGetNumberOfDimensions(prhs[2]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The state trace is not in proper form!");
dims = mxGetDimensions(prhs[2]);
miscell->dp_taliro_param.nSamp = dims[0];
miscell->dp_taliro_param.SysDim = dims[1];
XTrace = mxGetPr(prhs[2]);
/* Get time stamps */
if (nrhs>3)
{
ndim = mxGetNumberOfDimensions(prhs[3]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The time stamp sequence is not in proper form!");
dims = mxGetDimensions(prhs[3]);
if (miscell->dp_taliro_param.nSamp != dims[0])
mexErrMsgTxt("mx_dp_taliro: The lengths of the time stamp sequence and the state trace do not match!");
TStamps = mxGetPr(prhs[3]);
}
/* Get location trace and location graph */
if (nrhs>4)
{
ndim = mxGetNumberOfDimensions(prhs[4]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The location trace is not in proper form!");
dims = mxGetDimensions(prhs[4]);
if (miscell->dp_taliro_param.nSamp != dims[0])
mexErrMsgTxt("mx_dp_taliro: The lengths of the location trace and the state trace do not match!");
LTrace = mxGetPr(prhs[4]);
/* For Multiple H.A.s is added */
if(nrhs>5 && (mxIsCell(prhs[5]))){/* For Multiple H.A.s */
is_Multi_HA=1;
miscell->dp_taliro_param.nCLG = dims[1];
ndim = mxGetNumberOfDimensions(prhs[5]);
if (ndim>2)
{
mexErrMsgTxt("mx_dp_taliro.c: !");
}
dims = mxGetDimensions(prhs[5]);
if (dims[0]!=1)
{
mexErrMsgTxt("mx_dp_taliro: DMin is a cell, it must be a column vector cell!");
}
if (dims[1]!=miscell->dp_taliro_param.nCLG)
{
mexErrMsgTxt("mx_dp_taliro: DMin is a cell, it must be of the size of nCLG!");
}
distData.LDistNCLG = (double **)emalloc((miscell->dp_taliro_param.nCLG)*sizeof(double*));
miscell->dp_taliro_param.tnLocNCLG = (mwSize*)emalloc((miscell->dp_taliro_param.nCLG)*sizeof(mwSize));
for(kk=0; kk<miscell->dp_taliro_param.nCLG; kk++){
tmp = mxGetCell(prhs[5],kk);
dims = mxGetDimensions(tmp);
miscell->dp_taliro_param.tnLocNCLG[kk] = dims[0];
distData.LDistNCLG[kk]=mxGetPr(tmp);
}
}
else if(nrhs>5) {/* For Single H.A. */
is_Multi_HA=0;
ndim = mxGetNumberOfDimensions(prhs[5]);
if (ndim>2)
mexErrMsgTxt("mx_dp_taliro: The minimum distance array is not in proper form!");
dims = mxGetDimensions(prhs[5]);
miscell->dp_taliro_param.tnLoc = dims[0];
distData.LDist = mxGetPr(prhs[5]);
}
}
}

In your code, you are using a lot of functions and data types, provided by the MEX API. Therefore, if you want to produce "normal" C-Code you will have to completly refactor your code.
But one possible solution might be to compile your source code outside MATLAB IDE, by gcc or any other compiler. In this case you will have to include all necessary header files and link against all libraries you need.
Follwo the link to find a pretty good documentation from Mathworks:
https://de.mathworks.com/matlabcentral/answers/377799-compiling-mex-files-without-the-mex-command
Another way for creating C Code from Matlab Scipts/Functions is to use MATLAB Coder:
https://de.mathworks.com/products/matlab-coder.html
Hope this is helpful.

Related

wlan compiled code returns error and i need to specify the password for the ssid

I have this code right here I am using mingw to compile and I am running windows XP. When I run the output executable it gives me error prompt about the application..
Do I set everything correctly ? How do I set the SSID password for it to connect ? Also I want to know if I am using the correct network interface to connect (I have an external wifi adapter)..
I got the code from this link any help is very much appreciated..
//#define _WIN32_DCOM
#define _WIN32_WINNT 0x0600
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <objbase.h>
#include <rpcsal.h>
#include <objbase.h>
#include <wlanapi.h>
int main(){
PDOT11_SSID pSsid;
strcpy(pSsid->ucSSID, "SUPERONLINE-WiFi_24811");
pSsid->uSSIDLength = 25;
HANDLE wlanHandle;
unsigned long nv;
WlanOpenHandle(1, NULL, &nv, &wlanHandle);
DWORD dwResult = 0;
WLAN_CONNECTION_PARAMETERS cp;
memset(&cp, 0, sizeof(WLAN_CONNECTION_PARAMETERS));
cp.wlanConnectionMode = wlan_connection_mode_profile;
cp.strProfile = NULL;
cp.dwFlags = 0;
cp.pDot11Ssid = pSsid;
cp.pDesiredBssidList = 0;
cp.dot11BssType = dot11_BSS_type_any;
PWLAN_INTERFACE_INFO_LIST pIfList = NULL;
PWLAN_INTERFACE_INFO pIfInfo = NULL;
// only use the first wifi interface
dwResult = WlanEnumInterfaces(wlanHandle, NULL, &pIfList);
pIfInfo = (WLAN_INTERFACE_INFO *)&pIfList->InterfaceInfo[1];
if (dwResult == ERROR_SUCCESS)
{
dwResult = WlanConnect(wlanHandle, &(pIfInfo->InterfaceGuid), &cp, NULL);
if (dwResult == ERROR_SUCCESS)
{
printf("Connected..\n");
//connected = true;
}
}
return 0;
}
This is the error I get:
Edit: I have made it this far to the code below.. But still I can not assign the value to PDOT11_SSID struct.. It seems the struct has UCHAR array yet I can't assign.. Here is the link
PDOT11_SSID pSsid;
UCHAR arr[22] = { 0 };
//memset(pSsid->ucSSID, '\0', 32); //this causes the same error too
memcpy(
arr,
(unsigned char[]){ 'S','U','P','E','R','O','N','L','I','N','E','-','W','i','F','i','_','2','4','8','1','1' },
sizeof(arr)); //memcpy to arr struct works..
ULONG len = 22;
pSsid->uSSIDLength = len;
memcpy(pSsid->ucSSID, arr, sizeof(arr)); // this line fails still..
Edit: I ran with -Wall -Wextra -pedantic -Werror Like David mentioned and with the code segment below:
PDOT11_SSID pSsid;
memset(pSsid->ucSSID, '\0', 32); //fails
I got this error
yet if I initialized with
PDOT11_SSID pSsid = { 0 };
or
PDOT11_SSID pSsid = NULL;
It compiled but I got the crash image above I used to get.. Important to note that memset(pSsid->ucSSID, '\0', 32); causes the crash as well. I can know this by commenting out each line and compiling/running again.
This is a burden since I am yet to figure out how to add SSID password with wlanapi.h so help for these will be much appreciated for me to move on forward.
Fyi: I use basic gcc to compile gcc.exe wlan.c -lwlanapi. If there is any working solution code to connect to an ssid with the ssid and password using wlanapi, a link to that is also appreciated.
Wlan connect from msdn is this link.. I can't see any security parameters, how do I set the password of the SSID I want to connect to ?
Here is what you have been looking for:
#include <winsock2.h>
#include <Wlanapi.h>
#include <iphlpapi.h>
#include <stdio.h>
#pragma warning(disable:4996) /*fuss sprintf*/
#define SSID_MAX_LEN (32)
int ConnectToTargetWifiSSID(char *pSSIDName, char *pPassword)
{
DWORD dwVersion;
#if(0)
DWORD dwMajorVersion;
dwVersion = 0 = dwMajorVersion;
dwVersion = GetVersion();
dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
DWORD dwClientVersion;
dwClientVersion = ( dwMajorVersion >= 6) ? 2 : 1 ; /*vista or latter*/
#endif
DWORD result;
HANDLE iWifiHandle;
PWLAN_INTERFACE_INFO_LIST iAvailableInterfaces;
PWLAN_AVAILABLE_NETWORK_LIST availableNetworkList;
GUID iInterfaceGuid;
int isHavingProfile;
char authentication[64];
char encryption[64];
int isOpenedAP;
unsigned int i;
unsigned int iii;
WLAN_CONNECTION_PARAMETERS connParam;
iWifiHandle = NULL;
iAvailableInterfaces = NULL;
availableNetworkList = NULL;
/*part zero : one a wlan handle*/
result = WlanOpenHandle(1,NULL,&dwVersion, &iWifiHandle);
if(NULL != iWifiHandle)
{
/*get wireless network card*/
result = WlanEnumInterfaces(iWifiHandle, NULL, &iAvailableInterfaces);
if(ERROR_SUCCESS == result && iAvailableInterfaces->dwNumberOfItems > 0)
{
/*chose the zeroth one*/
printf("InterFaceName: %ls",iAvailableInterfaces->InterfaceInfo[0].strInterfaceDescription);
iInterfaceGuid = iAvailableInterfaces->InterfaceInfo[0].InterfaceGuid;
}
else
{
/*no wireless card*/
result = -2;
goto Exit_ConnectToTargetSSID;
}
}
else
{
result = -1;
goto Exit_ConnectToTargetSSID;
}/*if NULL != iWifiHandle*/
/*part one: scan available wifi routers(SSID)*/
result= WlanGetAvailableNetworkList(iWifiHandle, &iInterfaceGuid,
0x00000001, NULL, &availableNetworkList);
//WLAN_AVAILABLE_NETWORK_INCLUDE_ALL_ADHOC_PROFILES, NULL, &availableNetworkList);
if(ERROR_SUCCESS != result)
return -3;
isHavingProfile = FALSE;
isOpenedAP = FALSE;
iii = -1;
memset(&authentication[0], 0, 64);
memset(&encryption[0], 0, 64);
if( 0 == availableNetworkList->dwNumberOfItems)
{
/*on wifi router has been found*/
result = -4;
goto Exit_ConnectToTargetSSID;
}/*if 0 < wifiList->dwNumberOfItems*/
for(i = 0; i < availableNetworkList->dwNumberOfItems; i++)
{
DWORD flag;
printf("SSID:\t\t\t%s\nSIGNAL:\t\t\t%d\n",
availableNetworkList->Network[i].dot11Ssid.ucSSID,
availableNetworkList->Network[i].wlanSignalQuality);
printf("SECURITY:\t\t");
switch(availableNetworkList->Network[i].dot11DefaultAuthAlgorithm)
{
case DOT11_AUTH_ALGO_80211_OPEN:
printf("OPEN\n");
break;
case DOT11_AUTH_ALGO_80211_SHARED_KEY:
printf("WEP\n");
break;
case DOT11_AUTH_ALGO_WPA:
case DOT11_AUTH_ALGO_WPA_PSK:
case DOT11_AUTH_ALGO_WPA_NONE:
printf("WPA\n");
break;
case DOT11_AUTH_ALGO_RSNA:
case DOT11_AUTH_ALGO_RSNA_PSK:
printf("WPA2\n");
break;
default:
printf("UNKNOWN\n");
break;
}
printf("encryption:\t\t");
switch(availableNetworkList->Network[i].dot11DefaultCipherAlgorithm)
{
case DOT11_CIPHER_ALGO_NONE:
printf("NONE\n");
break;
case DOT11_CIPHER_ALGO_WEP40:
printf("WEP40\n");
break;
case DOT11_CIPHER_ALGO_TKIP:
printf("TKIP\n");
break;
case DOT11_CIPHER_ALGO_WEP104:
printf("WEP104\n");
break;
case DOT11_CIPHER_ALGO_CCMP:
printf("CCMP\n");
break;
default:
printf("UNKNOWN\n");
break;
}/*switch*/
flag = availableNetworkList->Network[i].dwFlags;
if(flag & 0x00000001)
printf("\t NOTE : Current connecting\n");
if(flag & 0x00000002)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_HAS_PROFILE\n");
if(flag & 0x00000004)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_CONSOLE_USER_PROFILE\n");
/*if(flag & WLAN_AVAILABLE_NETWORK_CONNECTED)
printf("\t NOTE : Current connecting\n");
if(flag & WLAN_AVAILABLE_NETWORK_HAS_PROFILE)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_HAS_PROFILE\n");
if(flag & WLAN_AVAILABLE_NETWORK_CONSOLE_USER_PROFILE)
printf("\t NOTE : WLAN_AVAILABLE_NETWORK_CONSOLE_USER_PROFILE\n");*/
printf("\n");
}/*for */
/*part two: save target SSID propertis*/
for(i = 0; i < availableNetworkList->dwNumberOfItems; i++)
{
if(0 == strncmp(pSSIDName, (char*)availableNetworkList->Network[i].dot11Ssid.ucSSID , SSID_MAX_LEN))
{
//WLAN_AVAILABLE_NETWORK_CONNECTED
if( 0x00000001 & availableNetworkList->Network[i].dwFlags)
{
printf("%s is current connecting!!\n", pSSIDName);
result = 1;
goto Exit_ConnectToTargetSSID;
}/*if*/
iii = i;
if(0x00000002 & availableNetworkList->Network[i].dwFlags)
//if(WLAN_AVAILABLE_NETWORK_HAS_PROFILE & availableNetworkList->Network[i].dwFlags)
isHavingProfile = TRUE;
/*list the target SSID properties*/
switch(availableNetworkList->Network[i].dot11DefaultAuthAlgorithm)
{
case DOT11_AUTH_ALGO_80211_OPEN:
sprintf(&authentication[0], "OPEN");
break;
case DOT11_AUTH_ALGO_80211_SHARED_KEY:
sprintf(&authentication[0], "WEP");
break;
case DOT11_AUTH_ALGO_WPA:
case DOT11_AUTH_ALGO_WPA_PSK:
case DOT11_AUTH_ALGO_WPA_NONE:
sprintf(&authentication[0], "WPAPSK");
break;
case DOT11_AUTH_ALGO_RSNA:
case DOT11_AUTH_ALGO_RSNA_PSK:
sprintf(&authentication[0], "WPA2PSK");
break;
default:
sprintf(&authentication[0], "UNKNOWN");
break;
}/*switch dot11DefaultAuthAlgorithm*/
switch(availableNetworkList->Network[i].dot11DefaultCipherAlgorithm)
{
case DOT11_CIPHER_ALGO_NONE:
sprintf(&encryption[0], "NOEN");
break;
case DOT11_CIPHER_ALGO_TKIP:
sprintf(&encryption[0], "TKIP");
break;
case DOT11_CIPHER_ALGO_CCMP:
sprintf(&encryption[0], "AES");
break;
default:
sprintf(&encryption[0], "WEP");
break;
}/*/*switch dot11DefaultCipherAlgorithm*/
break;
}/*if 0 == strncmp(pSSIDName, (char*)availableNetworkList->Network[i].dot11Ssid.ucSSID , SSID_MAX_LEN)*/
}/*for i*/
if(-1 == iii)
{
/*target router could not found */
result = -5;
goto Exit_ConnectToTargetSSID;
}/*if */
/*part there, set XML profile*/
if(FALSE == isHavingProfile)
{
/*if current computer has never connected to target router..*/
wchar_t profileXMLUnicode[4096];
char buff[4096];
DWORD reasonCode;
char profileTemplateXML[] = "<?xml version=\"1.0\"?>" \
"<WLANProfile xmlns=\"http://www.microsoft.com/networking/WLAN/profile/v1\">"\
" <name>%s</name>" \
" <SSIDConfig> " \
" <SSID>" \
" <name>%s</name>"\
" </SSID>"\
" </SSIDConfig>"\
" <connectionType>ESS</connectionType>"\
" <connectionMode>auto</connectionMode>"\
" <MSM>"\
" <security>"\
" <authEncryption>"\
" <authentication>%s</authentication>"\
" <encryption>%s</encryption>"\
" <useOneX>false</useOneX>"\
" </authEncryption>"\
" <sharedKey>"\
" <keyType>passPhrase</keyType>"\
" <protected>false</protected>"\
" <keyMaterial>%s</keyMaterial>"\
" </sharedKey>"\
" </security>" \
" </MSM>" \
"</WLANProfile>" ;
reasonCode = 0;
sprintf(buff, profileTemplateXML, availableNetworkList->Network[iii].dot11Ssid.ucSSID,
availableNetworkList->Network[iii].dot11Ssid.ucSSID,
&authentication[0], &encryption[0], pPassword);
/*Covert ansi to unicode*/
MultiByteToWideChar(CP_ACP, 0, &buff[0], -1, &profileXMLUnicode[0], 4096);
result = WlanSetProfile(iWifiHandle, &iInterfaceGuid, 0, &profileXMLUnicode[0],
NULL, TRUE, NULL, &reasonCode);
wprintf( L"%s", profileXMLUnicode);
if(ERROR_SUCCESS != result)
{
result = -6;
goto Exit_ConnectToTargetSSID;
}/*if */
}
else
{
/*if current computer had connected to target router, and remember who it is ...*/
DWORD dwFlags;
DWORD dwGrantedAccess;
LPWSTR xml;
result = WlanGetProfile(iWifiHandle, &iInterfaceGuid,
availableNetworkList->Network[iii].strProfileName, NULL, &xml ,&dwFlags,&dwGrantedAccess);
wprintf( L"%s", xml);
}/*if FASLSE == isHavingProfile*/
/*part four, connect to target ssid */
connParam.pDot11Ssid= NULL;
connParam.strProfile= availableNetworkList->Network[iii].strProfileName;
connParam.wlanConnectionMode = wlan_connection_mode_profile;
connParam.pDesiredBssidList=NULL;
connParam.dot11BssType= availableNetworkList->Network[iii].dot11BssType;
connParam.dwFlags = 0;
//wprintf( L"%s", &iInterfaceGuid,wifiList->Network[iii].strProfileName);
result = WlanConnect(iWifiHandle, &iInterfaceGuid, &connParam, NULL);
if(ERROR_SUCCESS != result)
result = -7;
Exit_ConnectToTargetSSID:
if(NULL != availableNetworkList)
WlanFreeMemory(availableNetworkList);
if(NULL != iAvailableInterfaces)
WlanFreeMemory(iAvailableInterfaces);
if(NULL != iWifiHandle)
WlanCloseHandle(iWifiHandle, NULL);
return result;
}/*ConnectToTargetWifiSSID*/
int main(int argc, char *argv[])
{
ConnectToTargetWifiSSID("SUPERONLINE-WiFi_24811", "pass123");
return 0;
}/*main*/

C how to run a loop in the background

I am making a "Clicker-Game". It's my first real game that I'm doing alongside school. I got all of the game code complete but I want to have a loop in the background that adds geldps(money per second) after every second.
I tried threads but I don't really understand it and we won't learn that until next year, so I´m asking, if anyone can either tell me a better way to make a loop in the background that runs independent from the main program, and can just add geldps to geld every second. Thanks.
PS: I am sorry for the German variables. Ask me if you don't know what sth means or anything, and it´s probably not very well organised and everything.
#include <stdio.h>
int geldps=0,geld=0;
int main()
{
int stand=0, oil=0, Mine=0, Bank=0,standzahl=100, Minezahl=500, Bankzahl=1000, oilzahl=10000, Werkzeug=0, Werkzeugzahl=10;
char input, input2;
float faktor;
do
{
system("cls");
faktor=1+Werkzeug/10;
printf("%c%c%c%c%c%c%c%c%c%c%c\n",201,205,205,205,205,205,205,205,205,205,187);
printf(" %d$\n",geld);
printf("%c%c%c%c%c%c%c%c%c%c%c\n",200,205,205,205,205,205,205,205,205,205,188);
printf(" Space to get money\n U to go to Upgrades\n Escape to leave");
input=getch();
if(input==32)
{
geld=geld+faktor;
continue;
}
if(input == 117 || input == 85)
{
system("cls");
do
{
system("cls");
printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\n 1 - Lemon Stands(%d)(%d$)\n 2 - Mines(%d)(%d$)\n 3 - Banks(%d)(%d$)\n 4 - Oil Refinerys(%d)(%d$)\nBackspace to go back", Werkzeug, Werkzeugzahl, stand, standzahl, Mine, Minezahl, Bank, Bankzahl, oil, oilzahl);
input2=getch();
if(input2== 48)
{
if(geld<Werkzeugzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Werkzeugzahl,geld);
system("pause");
continue;
}
geld=geld-Werkzeugzahl;
Werkzeug++;
Werkzeugzahl=Werkzeugzahl+Werkzeugzahl/10;
}
if(input2== 49)
{
if(geld<standzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",standzahl,geld);
system("pause");
continue;
}
geld=geld-standzahl;
stand++;
standzahl=standzahl+standzahl/10;
}
if(input2== 50)
{
if(geld<Minezahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Minezahl,geld);
system("pause");
continue;
}
geld=geld-Minezahl;
Mine++;
Minezahl=Minezahl+Minezahl/10;
geldps=geldps+1;
}
if(input2== 51)
{
if(geld<Bankzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",Bankzahl,geld);
system("pause");
continue;
}
geld=geld-Bankzahl;
Bank++;
Bankzahl=Bankzahl+Bankzahl/10;
geldps=geldps+10;
}
if(input2== 52)
{
if(geld<oilzahl)
{
system("cls");
printf("Not enough money(%d/%d$)\n",oilzahl,geld);
system("pause");
continue;
}
geld=geld-oilzahl;
oil++;
oilzahl=oilzahl+oilzahl/10;
geldps=geldps+100;
}
}
while(input2!=8);
}
}
while(input!=27);
return 0;
}
update: I was procrastinating and cleaned and improved your code. At the end of this answer.
If all you need is for a number to be consistently incremented based on time, add a function that updates a value based on time.
Here's an example showing not only how to do that but also how to compartmentalize your code into functions and how to use better code formatting and variable names.
#include <stdio.h> // printf()
#include <time.h> // time()
#include <stdlib.h> // random()
#include <unistd.h> // sleep()
int updateValue(int lastValue, int amountPerSecond) {
static time_t lastTime = -1;
time_t currentTime = time(NULL);
int newValue = lastValue;
if (lastTime != -1) {
newValue += amountPerSecond * (currentTime - lastTime);
}
lastTime = currentTime;
return newValue;
}
void seedRandom() {
// Don't use this in production code.
srandom(time(NULL));
}
int sleepRandomly() {
const int SLEEP_RANGE_IN_SECS = 5;
// sleep( 0..5 seconds )
int timeToSleep = random() % (SLEEP_RANGE_IN_SECS + 1);
sleep(timeToSleep);
return timeToSleep;
}
int main() {
const int AMOUNT_PER_SECOND = 5;
int value = 0;
// How many times to run the loop
int numCycles = 5;
seedRandom();
// Initialize the updateValue() start time
value = updateValue(value, AMOUNT_PER_SECOND);
while (numCycles--) {
int amountSlept = sleepRandomly();
int newValue = updateValue(value, AMOUNT_PER_SECOND);
printf("Slept %d seconds.", amountSlept);
printf("Value updated: %10d + (%d secs * %4d amount/secs) = %10d\n",
value, amountSlept, AMOUNT_PER_SECOND, newValue);
value = newValue;
}
return 0;
}
Cleaned up version of your code, and then I just kept improving it.
#include <stdio.h> // printf()
#include <string.h> // strlen()
#include <stdarg.h> // vsnprintf()
#include <unistd.h> // STDIN_FILENO
#include <sys/time.h> // gettimeofday()
#include <time.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
// TODO: convert the menus to tables:
// key - desc count cost effect
// TODO: add all income sources in a list so it's easy to add more
// without changing code
// TODO: the current pricing is off
// TODO: convert to C++ so we can use classes
// TODO: only use one menu, it's nicer to use
// one global value so we can ensure that we restore
// stdin's terminal settings
struct termios g_oldStdinTermios;
int g_keepGoing = 1;
typedef struct {
int count;
int zahl;
int zahlIncrement;
int geldPerSecondIncrement;
} IncomeSource;
typedef struct {
char lastMessage[100];
// try to avoid global variables, pass them instead
// one variable per line
int geld;
int geldPerSecond;
int geldPerClick;
IncomeSource werkzeug;
IncomeSource stand;
// Use consistent capitalization: sound be "mine"
IncomeSource mine;
IncomeSource bank;
IncomeSource oil;
} Values;
void setLastMessage(Values *values, const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
(void) vsnprintf(values->lastMessage, sizeof(values->lastMessage), fmt, ap);
va_end(ap);
}
void clearLastMessage(Values *values) {
// clear lastMessage after valid choice
values->lastMessage[0] = '\0';
}
void initializeValues(Values *values) {
clearLastMessage(values);
// use spaces around assignment and operators
values->geldPerSecond = 0;
values->geld = 10000;
// count, cost, cost increment (1/n), geldPerSecond increment
values->werkzeug = (IncomeSource){0, 10, 10, 0};
// BUG: number of stands doesn't increase geld per second
// or geld per click
values->stand = (IncomeSource){0, 100, 10, 0};
values->mine = (IncomeSource){0, 500, 10, 1};
values->bank = (IncomeSource){0, 1000, 10, 10};
values->oil = (IncomeSource){0, 10000, 10, 100};
values->geldPerClick = 1 + values->werkzeug.count / 10;
}
void clearScreen() {
// use ANSI escape sequences
const char *ANSI_MOVE_TO_1_1 = "\x1B[1;1H";
const char *ANSI_CLEAR_SCREEN = "\x1B[2J";
printf("%s%s", ANSI_CLEAR_SCREEN, ANSI_MOVE_TO_1_1);
}
char upcase(char c) {
if (c < 'a' || c > 'z') {
return c;
}
return 'A' + (c - 'a');
}
void setNonBlockingBufferingStdinTermios() {
struct termios new_;
tcgetattr(STDIN_FILENO, &g_oldStdinTermios);
new_ = g_oldStdinTermios;
new_.c_lflag &= ~ICANON;
tcsetattr(STDIN_FILENO, TCSANOW, &new_);
}
void restoreStdinTermios() {
tcsetattr(STDIN_FILENO, TCSANOW, &g_oldStdinTermios);
}
long getElapsedTimeInMs(struct timeval *start) {
struct timeval now;
gettimeofday(&now, NULL);
// in microseconds
long elapsed = ((now.tv_sec - start->tv_sec) * 1000000
+ now.tv_usec - start->tv_usec);
return elapsed / 1000;
}
char getCharacter() {
struct timeval start;
gettimeofday(&start, NULL);
char input = -1;
while (read(STDIN_FILENO, &input, 1) == -1
&& errno == EAGAIN
&& getElapsedTimeInMs(&start) < 500) {
}
return upcase(input);
}
void updateGeld(Values *values) {
static time_t lastTime = -1;
time_t currentTime = time(NULL);
if (lastTime != -1) {
values->geld += values->geldPerSecond * (currentTime - lastTime);
}
lastTime = currentTime;
}
void printHeader(Values *values) {
const char *UPPER_LEFT = "\u2554";
const char *UPPER_RIGHT = "\u2557";
const char *LOWER_LEFT = "\u255a";
const char *LOWER_RIGHT = "\u255d";
const char *HORIZONTAL = "\u2550";
const char *VERTICAL = "\u2551";
updateGeld(values);
// Automatically expand the box as the size
// of geld grows.
const int BORDER_WIDTH = 3;
char geldStr[20];
snprintf(geldStr, sizeof(geldStr), "$ %d", values->geld);
// Move code used more than once into its own function
clearScreen();
printf("%s", UPPER_LEFT);
for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
printf("%s", HORIZONTAL);
}
printf("%s\n", UPPER_RIGHT);
// use spaces around commas
printf("%s %s %s %s\n",
VERTICAL, geldStr, VERTICAL, values->lastMessage);
printf("%s", LOWER_LEFT);
for (int i = 0; i < (2 * BORDER_WIDTH + strlen(geldStr)); i++) {
printf("%s", HORIZONTAL);
}
printf("%s\n", LOWER_RIGHT);
}
void upgrade(Values *values, IncomeSource *source) {
if (values->geld < source->zahl) {
setLastMessage(values, "Not enough money(%d/%d$)",
source->zahl, values->geld);
return;
}
clearLastMessage(values);
values->geld -= source->zahl;
source->count++;
source->zahl += source->zahl / source->zahlIncrement;
values->geldPerSecond += source->geldPerSecondIncrement;
}
char getUpgradeInput(Values *values) {
clearScreen();
printHeader(values);
printf(" 0 - Tools(10 for 1 more Money)(%d)(%d$)\t\t+%d/click\n",
values->werkzeug.count, values->werkzeug.zahl, values->geldPerClick);
printf(" 1 - Lemon Stands(%d)(%d$)\t\t\t+%d/sec\n",
values->stand.count, values->stand.zahl,
values->stand.count * values->stand.geldPerSecondIncrement);
printf(" 2 - Mines(%d)(%d$)\t\t\t\t+%d/sec\n",
values->mine.count, values->mine.zahl,
values->mine.count * values->mine.geldPerSecondIncrement);
printf(" 3 - Banks(%d)(%d$)\t\t\t\t+%d/sec\n",
values->bank.count, values->bank.zahl,
values->bank.count * values->bank.geldPerSecondIncrement);
printf(" 4 - Oil Refinerys(%d)(%d$)\t\t\t+%d/sec\n",
values->oil.count, values->oil.zahl,
values->oil.count * values->oil.geldPerSecondIncrement);
printf(" Q - Back to main menu\n");
printf("> ");
fflush(stdout);
return getCharacter();
}
void upgradeLoop(Values *values) {
char input = ' ';
while (input != 'Q' && g_keepGoing) {
input = getUpgradeInput(values);
switch (input) {
case '0':
upgrade(values, &values->werkzeug);
values->geldPerClick = 1 + values->werkzeug.count / 10;
break;
case '1':
upgrade(values, &values->stand);
break;
case '2':
upgrade(values, &values->mine);
break;
case '3':
upgrade(values, &values->bank);
break;
case '4':
upgrade(values, &values->oil);
break;
case 'Q':
break;
default:
break;
}
}
}
char getMainInput(Values *values) {
printHeader(values);
// make this easier to read in the code...
printf(" _ - [Space] get money\n");
printf(" U - Upgrades\n");
printf(" Q - Quit\n");
printf("> ");
fflush(stdout);
return getCharacter();
}
void mainLoop(Values *values) {
char input = ' ';
// while..do is easier to read and understand than do..while
while (input != 'Q' && g_keepGoing) {
// Encapsulate code in functions to make your program's logic
// easier to follow
input = getMainInput(values);
// Use a switch statement here and use character values
// rather than integers
switch (input) {
case ' ':
values->geld += values->geldPerClick;
clearLastMessage(values);
break;
case 'U':
upgradeLoop(values);
clearLastMessage(values);
case 'Q':
break;
default:
break;
}
};
}
void sigintHandler(int signal) {
printf("SIGINT received, cleaning up.\n");
restoreStdinTermios();
g_keepGoing = 0;
}
int main() {
Values values;
initializeValues(&values);
setNonBlockingBufferingStdinTermios();
signal(SIGINT, sigintHandler);
mainLoop(&values);
restoreStdinTermios();
return 0;
}

Commands to execute functions in C

I'm using the LXLE 14.04 distribution of Linux.
I want to write a C program to read commands, interpret and perform them. I'd like the program to be efficient, and I do not want to use
a linked list.
The commands are operations on sets.
Each set can contain any of the values from 0 through 127 inclusive.
I decided to represent a set as an array of characters, containing 128 bits.
If bit at position pos is turned on then the number pos is in the set and if the bit at position pos is turned off then the number pos is
not present in the set. For example, if the bit at position 4 is 1, then the number 4 is present in the set, if the bit at position 11 is 1 then the number
11 is present in the set.
The program should read commands and interpret them in a certain way.
There are a few commands: read_set, print_set, union_set, intersect_set, sub_set and halt.
For example, the command read_set A,1,2,14,-1 in the terminal will cause the reading of values of the list into the specified set in the command.
In this case the specified set in the command is A. The end of the list is represented by -1. So after writing this command, the set A will contain the elements 1,2,14.
This is what I have so far.
Below is the file set.h
#include <stdio.h>
typedef struct
{
char array[16]; /*Takes 128 bits of storage*/
}set;
extern set A , B , C , D , E , F;
This is the file main.c
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
void read_set(set s,char command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
void print_set(set s)
{
unsigned int flag = 1; int in_set = 0;
int i = 0;
while(s.array[i] != -1)
{
if(s.array[i] & flag)
{
in_set = s.array[i];
printf("%d,",in_set );
}
i++;
flag = 1;
}
}
int main()
{
#define CMD_LENGTH 256
char command[CMD_LENGTH]; char* letter;
printf("Please enter a command");
gets(command);
letter = strtok(command,"read_set ,");
switch(*letter)
{
case 'A':
{
read_set(A,command);
break;
}
case 'B':
{
read_set(B,command);
break;
}
case 'C':
{
read_set(C,command);
break;
}
case 'D':
{
read_set(D,command);
break;
}
case 'E':
{
read_set(E,command);
break;
}
case 'F':
{
read_set(F,command);
break;
}
}
return 0;
}
Clearly, it is not a good practice to write a bunch of switch statements and using strtok for each command, and repeating the code written in the main function for each command in order to call the different functions. I thought about using a pointer to a generic function, but since each function receives different parameters,
I do not think this is going to work.
Is there a better way of doing this?
Thanks in advance!
Update #1:
Here's the code. I've made some changes to it.
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
set sets[6];
/*Below I want to initialize sets so that set[0] = A set[1] = B etc*/
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
void read_set(set s,char all_command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
typedef struct
{
char *command;
void (*func)(set,char*);
} entry;
entry chart[] = { {"read_set",&read_set} };
void (*getFunc(char *comm) ) (set,char*)
{
int i;
for(i=0; i<2; i++)
{
if( strcmp(chart[i].command,comm) == 0)
return chart[i].func;
}
return NULL;
}
int main()
{
#define PER_CMD 256
char all_comm[PER_CMD]; void (*ptr_one)(set,char*) = NULL; char* comm; char* letter;
while( (strcmp(all_comm,"halt") != 0 ) & (all_comm != NULL))
{
printf("Please enter a command");
gets(all_comm);
comm = strtok(all_comm,", ");
ptr_one = getFunc(comm);
letter = strtok(NULL,",");
ptr_one(A,all_comm);
all_comm[0] = '\0';
letter[0] = '\0';
}
return 0;
}
I get the following compile error:
main.c:9:8: error: expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
What's my mistake? How can I fix this?
Thanks a lot! #Claim Yang
However,in your case, using switch is almost the best solution to this.
Another way without switch is using a simple way to get an index. Here is a simple solution.
set sets[6];
read_set(sets[*letter - 'A'], command);
Then if you need to read a command, another array of pointers to functions is needed. Like below:
void (*functions[3])(set,char[]);
functions[0] = read_set;
And so on.
The point is coverting your string to an int, so it can be seen as an index of an array.
Then call functions like functions[string_to_int(string)](set,char[]);

Refactoring: Very similar switch cases

I have several struct declared which contain different data. I also have an enum that corresponds to those structures. There are several places in my code where I need to access information about the structures and I'm doing it via the enum. This results in few switch statements that return this information.
I've enclosed those switch statements in their own functions in order to re-use wherever possible. This resulted in three functions that look very similar.
Example psuedo-code:
#include <stdio.h>
typedef struct
{
int varA;
char varB;
} A;
typedef struct
{
int varA;
int varB;
int varC;
} B;
typedef struct
{
int varA;
short varB;
} C;
typedef enum { structA, structB, structC } STRUCT_ENUM;
int returnSize(STRUCT_ENUM structType)
{
int retVal = 0;
switch(structType)
{
case structA:
retVal = sizeof(A);
break;
case structB:
retVal = sizeof(B);
break;
case structC:
retVal = sizeof(C);
break;
default:
break;
}
return retVal;
}
void printStructName(STRUCT_ENUM structType)
{
switch(structType)
{
case structA:
printf("Struct: A\r\n");
break;
case structB:
printf("Struct: B\r\n");
break;
case structC:
printf("Struct: C\r\n");
break;
default:
break;
}
}
void createDataString(STRUCT_ENUM structType, char* output, unsigned char* input)
{
switch(structType)
{
case structA:
{
A a = *(A*)input;
sprintf(output, "data: %d, %d", a.varA, a.varB);
break;
}
case structB:
{
B b = *(B*)input;
sprintf(output, "data: %d, %d, %d", b.varA, b.varB, b.varC);
break;
}
case structC:
{
C c = *(C*)input;
sprintf(output, "data: %d, %d", c.varA, c.varB);
break;
}
default:
break;
}
}
int main(void) {
char foobar[50];
printf("Return size: %d\r\n", returnSize(structA));
printStructName(structB);
C c = { 10, 20 };
createDataString(structC, foobar, (unsigned char*) &c);
printf("Data string: %s\r\n", foobar);
return 0;
}
Those free functions basically contain the same switch with different code placed in the cases. With this setup, adding new struct and enum value results in three places in the code that needs changing.
The question is: is there a way to refactor this into something more maintainable? Additional constraint is that the code is written in C.
EDIT: online example: http://ideone.com/xhXmXu
You can always use static arrays and use STRUCT_ENUM as the index. Given the nature of your functions, I don't really know if you would consider it more maintainable, but it's an alternative I usually prefer, examples for names and sizes:
typedef enum { structA, structB, structC, STRUCT_ENUM_MAX } STRUCT_ENUM;
char *struct_name[STRUCT_ENUM_MAX] = {[structA] = "Struct A", [structB] = "Struct B", [structC] = "Struct C"};
size_t struct_size[STRUCT_ENUM_MAX] = {[structA] = sizeof(A), [structB] = sizeof(B), [structC] = sizeof(C)};
for printing content you can keep a similar array of functions receiving a void * that will print the value of this argument.
Edit:
Added designated initializers as per Jen Gustedt's comment.
You can make it into a single function and a single switch, with an additional parameter. Like so
int enumInfo(STRUCT_ENUM structType, int type) // 1 = returnSize 2 = printStructName
{
int retVal = 0;
switch(structType)
{
case structA:
If ( type == 1 ) { retVal = sizeof(A); }
else { printf("Struct: A"); }
break;
case structB:
If ( type == 1 ) { retVal = sizeof(B); }
else { printf("Struct: B"); }
break;
case structC:
If ( type == 1 ) { retVal = sizeof(C); }
else { printf("Struct: C"); }
break;
default:
break;
}
return retVal;
}

How to create AT Commands Parser in C to get the incoming string from USART1?

I want to get the string from USART1 of STM32VLDiscovery (STM32F100X4) and write an AT Command Parser from the string received from USART1.
Below are the concept that I have developed but I am not sure whether it's correct or not.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dosomethinga.h"
void dosomethingB();
void GET_AT_COMMAND(char*);
void takecommand(char *, char *);
int quit;
int main()
{ char buff[15];
char command = '\0';
quit = 0;
while(!quit)
{
printf("Enter your command: ");
scanf("%s", &buff);
if (buff[0] == 'A' && buff[1] == 'T' && buff[2] == '+')
{
GET_AT_COMMAND(buff);
}
}
}
void dosomethingB()
{
printf("dosomethingB called \n");
}
void GET_AT_COMMAND(char *text)
{
int command;
char temp[10] = "";
/*if(text[3] == 'A')
command = 1;
else if(text[3] == 'B')
command = 2;
else if(text[3] == 'Z')
command = 3;
*/
takecommand(text,temp);
if (strcmp(temp, "CALLA") == 0)
command = 1;
if (strcmp(temp, "CALLB") == 0)
command = 2;
if (strcmp(temp, "Z") == 0)
command = 3;
switch(command)
{
case 1:
dosomethingA();
break;
case 2:
printf("herehere.... \n");
dosomethingB();
break;
case 3:
printf("Exiting program.... \n");
quit = 1;
break;
default:
printf("Nothing to do here \n");
}
}
void takecommand(char *mycmd, char *hold)
{
int i;
for(i = 0; i < 10 ; i++)
{
hold[i] = mycmd[i+3];
}
}
Can anyone explain on the steps that I should do? Thanks.
Basicly you should wait an attention "AT" from the input and ignore anything before it.
For example inputs "XYZATZ\r" and "AaatZ\r" should be both handled as a "ATZ" command.
There can also be short pause between 'A' and 'T' (and all other chars of commands too), because human may type those commands.
By the default all commands end to "\r" character.
See more about AT commands from ITU-T documentation. For example from V.250 standard.
There are probably many alternative ways to implement that. The best alternative depends on your needs. If you are going to implement all AT-commands of mobile-terminal, then you should spend more time for the parser. If you want make some test application for few commands, then your implementation could be simple as your provided one.
I have developed this AT command parser, this could be use for reference.
When you get data from UART1 just call this method at_wait_msg() to parse the AT message
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
static const char *AT_HEADER = "AT";
static const char *AT_DEVICE_PROFILE = "DR";
static const char *AT_SET_DEVICE = "SD";
static const char AT_EOF = '\r';
typedef enum {
DeviceProfile,
SetDevice,
Error
} AT_Msg_Type;
typedef struct {
char header[3];
char command[3];
char data[128];
} AT_Msg_Data;
static void at_wait_msg(char text);
static void at_wait_msg_complete(char *text);
static void at_parse_msg(AT_Msg_Data *data);
static AT_Msg_Type at_check_format(AT_Msg_Data *data);
static char _rx_data[512];
static uint16_t _rx_index = 0;
int main()
{
//example data getting from UART1
char text[] = "ATDR\rATSD123456abchelloworld\r1123ATssa\r";
for (int i = 0; i < strlen(text) + 1; i++) {
//to simulate getting data from UART1 byte per byte
at_wait_msg(text[i]);
}
return 0;
}
static void at_wait_msg(char text)
{
_rx_data[_rx_index++] = text;
if (text == AT_EOF) {
at_wait_msg_complete(_rx_data);
_rx_index = 0;
}
}
static void at_wait_msg_complete(char *text)
{
AT_Msg_Data data;
int result = sscanf_s(_rx_data, "%2s%2s%s\r",
data.header, sizeof(data.header),
data.command, sizeof(data.command),
data.data, sizeof(data.data));
if (result >= 2) {
at_parse_msg(&data);
}
}
static void at_parse_msg(AT_Msg_Data *data)
{
AT_Msg_Type type = at_check_format(data);
switch (type) {
case DeviceProfile:
printf("device profile\r\n");
break;
case SetDevice:
printf("settings %s\r\n", data->data);
break;
case Error:
default:
printf("Error\r\n");
break;
}
}
static AT_Msg_Type at_check_format(AT_Msg_Data *data)
{
if (strcmp(data->header, AT_HEADER) != 0) {
return Error;
}
if (strcmp(data->command, AT_DEVICE_PROFILE) == 0) {
return DeviceProfile;
}
if (strcmp(data->command, AT_SET_DEVICE) == 0) {
return SetDevice;
}
return Error;
}

Resources