使用C ++兼容函数将整数转换为字符串,用于Matlab Coder

时间:2015-07-23 07:52:07

标签: string matlab type-conversion matlab-coder

我使用 Matlab Coder 将一些Matlab代码转换为C ++,但是我无法将整数转换为字符串。

代码生成不支持

int2str(),因此我必须找到一些其他方法将int转换为字符串。我试过谷歌搜索,没有成功。这甚至可能吗?

4 个答案:

答案 0 :(得分:8)

这可以手动完成(但非常痛苦)

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 :(得分:6)

sprintf是另一个非常基本的函数,所以它也可以在C ++中起作用:

#my-wrapper {
Width:700px;

}

#sidebar-wrapper {
width:200px;
display:none;
}

它也是x = int64(1948) str = sprintf('%i',x) 使用的基础功能。

根据这个comprehensive list of supported functions,正如Matt在评论中指出的那样,int2str不受支持,这是令人惊讶的。然而,有一个未记录的辅助函数(因此不在列表中)sprintfc似乎有用,可以等效使用:

sprintf

答案 2 :(得分:1)

Edit: As of MATLAB R2018a, sprintf is supported for code generation by MATLAB Coder.

Pre R2018a Answer

You could also call the C runtime sprintf or snprintf using coder.ceval. This has the benefit of making supporting floating point inputs easy as well. You can also change the formatting as desired by tweaking the format string.

Supposing that your compiler provides snprintf one could use:

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

Note that you'll possibly need to tweak the format string to match the hardware on which you're running since this assumes that long long is available and maps 64-bit integers to it.

答案 3 :(得分:1)

I use the following workaround to enable sprintf for general use with Matlab Coder:

1) Create the following m-file named "sprintf.m", preferably in a folder NOT on your Matlab path:

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) Ensure that sprintf is not specified as extrinsic via coder.extrinsic

3) Specify the folder containing the newly created "sprintf.m" as additional include directory when generating code. If you use the codegen function, this can be done via the -I switch. If you use the Coder App, this can be done under "More Settings -> Custom Code -> Additional include directories" from the "Generate" tab.

4) Convert from int to string as follows: s=sprintf('%d',int32(n));

Notes:

  • The specified "sprintf.m" shadows the built-in sprintf function and executes instead of the built-in function every time you call sprintf from generated code. By placing this file in a folder that is not on the Matlab path, you avoid calling it from other code made to run in Matlab. The coder.target call also helps to navigate back to the built-in function in case this gets called in a normal Matlab session or from a MEX file.
  • The code above limits the result to 1023 characters (a terminating zero is required at the end). The call to sprintf_s instructs the C++ compiler to throw a runtime exception if the result exceeds this value. This prevents memory corruption that is often only caught much later and is harder to trace back to the offending call. This limit can be modified to your own requirements.
  • Numeric types must be cast to the correct class before passing them to sprintf, e.g. cast to int32 to match a %d in the format string. This requirement is the same when using fprintf with Matlab Coder. However, in the fprintf case, Matlab Coder catches type errors for you. For sprintf, the C++ compiler may fail or the resulting string may contain errors.
  • String arguments must be NULL-terminated manually to be used in C calls, as Matlab Coder does not do this automatically (credit to Ryan Livingston for pointing this out). The code above ensures that the format string f is NULL-terminated, but NULL-termination of other string arguments remains the responsibility of the calling function.
  • This code was tested on a Windows platform with a Visual Studio C++ compiler and Matlab R2016a (Matlab Coder 3.1), but is expected to work in most other environments as well.