2015-07-23 17 views
5

Używam Matlab Coder do konwersji niektórych kod Matlab na C++, jednak mam problemy z konwersją intergers do ciągów.Konwertuj liczbę całkowitą na ciąg z funkcją kompatybilną z C++ dla Matlab Coder

int2str() nie jest obsługiwany do generowania kodu, więc muszę znaleźć inny sposób konwersji int do ciągów. Próbowałem googling, bez powodzenia. Czy to możliwe?

+1

Czy obsługiwany jest 'num2str'? Jest to najbardziej ogólna funkcja tego typu. – buzjwa

+0

num2str nie jest niestety nieobsługiwany. – ein123

Odpowiedz

8

Można to zrobić ręcznie (bardzo bolesne, choć)

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

Myślę, że musisz zmienić warunek 'while' na' n> 0' –

+1

@LuisMendo oczywiście. dzięki za spostrzeżenie. – Shai

+1

Tak, to działa! Dziękuję bardzo! – ein123

6

sprintf to kolejny bardzo podstawową funkcją, więc być może działa w C++, a także:

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

Jest także instrumentem bazowym funkcja używana przez int2str.


Według tego comprehensive list of supported functions, jak podkreślił Matt w komentarzach, sprintf nie jest obsługiwany, co jest zaskakujące. Jednak nie jest nieudokumentowana funkcja pomocnika (dlatego nie ma na liście) sprintfc który wydaje się działać i mogą być stosowane równoważnie:

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

Tak też myślałem. Zanim napisałem odpowiedź, sprawdziłem listę [tutaj] (http://ch.mathworks.com/help/coder/ug/functions-supported-for-code-generation--alphabetical-list.html) i 'sprintf' nie wydaje się być obsługiwane. – Matt

+1

sprintf nie jest również obsługiwany. – ein123

+1

@ ein123 co powiesz na nieudokumentowane 'sprintfc' - czy możesz to sprawdzić? – thewaywewalk

1

Można również zadzwonić runtime C sprintf lub snprintf korzystając coder.ceval. Ma to tę zaletę, że ułatwia również wprowadzanie wspomagających sygnałów zmiennoprzecinkowych. Możesz również zmienić formatowanie według potrzeb, modyfikując ciąg formatu.

Zakładając, że kompilator zapewnia snprintf jeden mógłby użyć:

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 

Zauważ, że będziesz prawdopodobnie musiał dostosować ciąg formatu w celu dopasowania do sprzętu, na którym używasz ponieważ zakłada, że ​​long long jest dostępny i mapuje do niej 64-bitowe liczby całkowite.

1

używam następujące obejścia w celu umożliwienia sprintf do ogólnego użytku z Matlab Coder:

1) Utwórz następujący m-plik o nazwie „sprintf.m”, najlepiej w folderze nie na swojej drodze 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) Upewnić się, że sprintf nie jest określony jako zewnętrzne poprzez coder.extrinsic

3) Określ folder zawierający nowo utworzoną „sprintf.m” jako dodatkowy zawierać katalog podczas generowania kodu. Jeśli używasz funkcji codegen, można to zrobić za pomocą przełącznika -I. Jeśli korzystasz z aplikacji Coder, można to zrobić w "Więcej ustawień -> Kod niestandardowy -> Dodatkowe katalogi" z zakładki "Generuj".

4) Konwersja z int na ciąg w następujący sposób: s=sprintf('%d',int32(n));

Uwagi:

  • Określona „sprintf.m” cienie wbudowanej sprintf funkcji i wykonuje zamiast wbudowanej funkcji za każdym razem, gdy wywołujesz sprintf z wygenerowanego kodu.Umieszczając ten plik w folderze, który nie znajduje się na ścieżce Matlaba, unikasz wywoływania go z innego kodu wykonanego w Matlabie. Wywołanie coder.target pomaga także wrócić do wbudowanej funkcji na wypadek, gdy zostanie to wywołane podczas normalnej sesji Matlab lub z pliku MEX.
  • Powyższy kod ogranicza wynik do 1023 znaków (na końcu wymagane jest zero z zakończeniem). Wywołanie sprintf_s instruuje kompilator C++, aby wyrzucił wyjątek środowiska wykonawczego, jeśli wynik przekroczy tę wartość. Zapobiega to uszkodzeniu pamięci, które często jest pobierane znacznie później i jest trudniejsze do prześledzenia wstecznego połączenia. Ten limit można zmodyfikować zgodnie z własnymi wymaganiami.
  • Typy liczbowe należy przenieść na właściwą klasę przed przekazaniem ich do sprintf, np. Przesyłaj do int32, aby dopasować %d w ciągu formatującym. To wymaganie jest takie samo w przypadku korzystania z programu Matlab Coder pod numerem fprintf. Jednak w przypadku fprintf program Matlab Coder przechwytuje błędy typu. W przypadku sprintf kompilator C++ może zawieść lub wynikowy ciąg może zawierać błędy.
  • Argumenty łańcuchowe muszą być zakończone NULL ręcznie, aby mogły być używane w wywołaniach C, ponieważ program Matlab Coder nie robi tego automatycznie (dla Ryana Livingstona za wskazanie tego). Powyższy kod zapewnia, że ​​ciąg formatu f jest zakończony NULL, ale kończenie wartości NULL innych argumentów ciągu pozostaje w gestii funkcji wywołującej.
  • Ten kod został przetestowany na platformie Windows z kompilatorem Visual Studio C++ i Matlab R2016a (Matlab Coder 3.1), ale powinien działać również w większości innych środowisk.
+1

Nie zapomnij o zerowym końcu żadnych argumentów, które będą łańcuchami C: 'cf = [f, 0]; coder.ceval (..., coder.rref (cf (1)); '. MATLAB Coder produkowane tablice znaków nie są zakończone null. Niewykonanie tej czynności spowoduje niezdefiniowane zachowanie w wygenerowanym kodzie. –

Powiązane problemy