2015-07-23 16 views
5

Sto usando Matlab Coder per convertire un codice Matlab in C++, tuttavia ho problemi a convertire gli interger in stringhe.Converti numeri interi in stringa con funzione compatibile C++ per Matlab Coder

int2str() non è supportato per la generazione del codice, quindi devo trovare un altro modo per convertire le stringhe in stringhe. Ho provato a cercarlo su google, senza successo. È possibile?

+1

È supportato 'num2str'? È la funzione più generale di questo tipo. – buzjwa

+0

num2str purtroppo non è supportato. – ein123

risposta

8

Questo può essere fatto manualmente (molto doloroso, però)

function s = thePainfulInt2Str(n) 
s = ''; 
is_pos = n > 0; % //save sign 
n = abs(n); %// work with positive 
while n > 0 
    c = mod(n, 10); % get current character 
    s = [uint8(c+'0'),s]; %// add the character 
    n = (n - c)/10; %// "chop" it off and continue 
end 
if ~is_pos 
    s = ['-',s]; %// add the sign 
end 
+1

Penso che sia necessario cambiare la condizione 'while' per' n> 0' –

+1

@LuisMendo ovviamente. grazie per aver individuato questo. – Shai

+1

Sì, funziona! Grazie mille! – ein123

6

sprintf è un'altra funzione molto semplice, quindi eventualmente funziona in C++ così:

x = int64(1948) 
str = sprintf('%i',x) 

È anche il sottostante funzione utilizzata da int2str.


Secondo questa comprehensive list of supported functions, come sottolineato da Matt nei commenti, sprintf non è supportata, che è sorprendente. Tuttavia, v'è la funzione di supporto non documentata (quindi non in lista) sprintfc che sembra funzionare e può essere utilizzato in modo equivalente:

str = sprintfc('%i',x) 
+0

Questo è quello che pensavo anch'io. Prima di scrivere una risposta, ho controllato l'elenco [qui] (http://ch.mathworks.com/help/coder/ug/functions-supported-for-code-generation--alphabetical-list.html) e 'sprintf' non sembra essere supportato – Matt

+1

sprintf non è supportato neanche. – ein123

+1

@ ein123 che ne dici di 'sprintfc' non documentato? Puoi controllare? – thewaywewalk

1

Si potrebbe anche chiamare il runtime C sprintf o snprintf usando coder.ceval. Questo ha il vantaggio di rendere facile anche il supporto degli ingressi in virgola mobile. È inoltre possibile modificare la formattazione come desiderato modificando la stringa di formato.

Supponendo che il compilatore fornisce snprintf si potrebbe usare:

function s = cint2str(x) 
%#codegen 
if coder.target('MATLAB') 
    s = int2str(x); 
else 
    coder.cinclude('<stdio.h>'); 
    assert(isfloat(x) || isinteger(x), 'x must be a float or an integer'); 
    assert(x == floor(x) && isfinite(x), 'x must be a finite integer value'); 
    if isinteger(x) 
     switch class(x) 
      % Set up for Win64, change to match your target 
      case {'int8','int16','int32'} 
       fmt = '%d'; 
      case 'int64' 
       fmt = '%lld'; 
      case {'uint8','uint16','uint32'} 
       fmt = '%u'; 
      otherwise 
       fmt = '%llu'; 
     end 
    else 
     fmt = '%.0f'; 
    end 
    % NULL-terminate for C 
    cfmt = [fmt, 0]; 

    % Set up external C types 
    nt = coder.opaque('int','0'); 
    szt = coder.opaque('size_t','0'); 
    NULL = coder.opaque('char*','NULL'); 

    % Query length 
    nt = coder.ceval('snprintf',NULL,szt,coder.rref(cfmt),x); 
    n = cast(nt,'int32'); 
    ns = n+1; % +1 for trailing null 

    % Allocate and format 
    s = coder.nullcopy(blanks(ns)); 
    nt = coder.ceval('snprintf',coder.ref(s),cast(ns,'like',szt),coder.rref(cfmt),x); 
    assert(cast(nt,'int32') == n, 'Failed to format string'); 
end 

Nota che avrete probabilmente bisogno di modificare la stringa di formato per abbinare l'hardware su cui si sta eseguendo dal momento che questo presuppone che long long è disponibile e mappa ad esso interi a 64 bit.

1

ho utilizzare la seguente soluzione per abilitare sprintf per uso generale con Matlab Coder:

1) Creare il seguente m-file denominato "sprintf.m", preferibilmente in una cartella non sul vostro cammino Matlab:

function s = sprintf(f, varargin) 

if (coder.target('MATLAB')) 
    s = builtin('sprintf',f,varargin{:}); 
elseif (coder.target('MEX')) 
    s = builtin('sprintf',f,varargin{:}); 
else 
    coder.cinclude('stdio.h'); 
    s = char(zeros(1024,1)); 
    cf = [f,0]; % NULL-terminated string for use in C 
    coder.ceval('sprintf_s', coder.ref(s(1)), int32(1024), coder.rref(cf(1)), varargin{:}); 
end 

2) Assicurarsi che sprintf non è specificato come estrinseca attraverso coder.extrinsic

3) Specificare la cartella contenente il appena creata "sprintf.m", come ulteriore includono directory quando la generazione del codice. Se si utilizza la funzione codegen, è possibile farlo tramite lo switch -I. Se si utilizza l'app Coder, questa operazione può essere eseguita in "Altre impostazioni -> Codice personalizzato -> Altre directory di inclusione" dalla scheda "Genera".

4) Convertire da int stringa come segue: s=sprintf('%d',int32(n));

Note:

  • Il specificato "sprintf.m" ombre incorporata sprintf funzione ed esegue invece della funzione incorporata ogni volta che chiami sprintf dal codice generato.Inserendo questo file in una cartella che non si trova nel percorso Matlab, si evita di chiamarlo da un altro codice creato per essere eseguito in Matlab. La chiamata coder.target aiuta anche a tornare alla funzione built-in nel caso in cui venga richiamata in una normale sessione Matlab o da un file MEX.
  • Il codice sopra limita il risultato a 1023 caratteri (alla fine è richiesto uno zero finale). La chiamata a sprintf_s ordina al compilatore C++ di generare un'eccezione di runtime se il risultato supera questo valore. Ciò impedisce il danneggiamento della memoria, che spesso viene rilevato solo molto tempo dopo ed è più difficile rintracciare la chiamata in questione. Questo limite può essere modificato in base alle proprie esigenze.
  • I tipi numerici devono essere convertiti nella classe corretta prima di passarli a sprintf, ad es. cast to int32 per abbinare un %d nella stringa di formato. Questo requisito è lo stesso quando si utilizza fprintf con Matlab Coder. Tuttavia, nel caso fprintf, Matlab Coder rileva errori di tipo per te. Per sprintf, il compilatore C++ potrebbe non riuscire o la stringa risultante potrebbe contenere errori.
  • Gli argomenti stringa devono essere terminati con NULL manualmente per essere utilizzati nelle chiamate C, in quanto Matlab Coder non lo fa automaticamente (credito a Ryan Livingston per averlo indicato). Il codice sopra assicura che la stringa di formato f sia terminata con NULL, ma la terminazione NULL di altri argomenti di stringa rimane responsabilità della funzione di chiamata.
  • Questo codice è stato testato su una piattaforma Windows con un compilatore Visual Studio C++ e Matlab R2016a (Matlab Coder 3.1), ma è previsto che funzioni anche nella maggior parte degli altri ambienti.
+1

Non dimenticare di terminare in modo nullo gli argomenti che saranno stringhe C: 'cf = [f, 0]; coder.ceval (..., coder.rref (cf (1))); '. Le matrici di caratteri prodotte dal codificatore MATLAB non hanno una terminazione nulla. In caso contrario, si verificherà un comportamento indefinito nel codice generato. –