Search code examples
c++matlabcsvmatlab-coder

MATLAB to C++: csvread() not supported by MATLAB Coder


I need to port a MATLAB script, which uses .csvs to read and write configs and data with csvread(), to C++.

Obvious choice was to use the Coder app in MATLAB but csvread() is not supported by Coder.

What would be the best course of action to get the conversion going?

I tried reading the file via fileread() or fread() to parse the file in MATLAB but functions like textscan() aren't supported by Coder either.

Also it seems like coder.ceval() cannot return arrays - at least the manual says so - how would a parser have to look like in C++? I was planning on returning a nested vector.


Solution

  • If you're set on using Coder, once you read the file, you can use a combination of the MATLAB function strtok and a coder.ceval call to the C sscanf to do the parsing. My answer here shows an example of doing this for parsing CSV data.

    Data

    1, 221.34
    2, 125.36
    3, 98.27
    

    Code

    function [idx, temp, outStr] = readCsv(fname)
    % Example of reading in 8-bit ASCII data in a CSV file with FREAD and
    % parsing it to extract the contained fields.
    NULL = char(0);
    f = fopen(fname, 'r');
    N = 3;
    fileString = fread(f, [1, Inf], '*char'); % or fileread
    outStr = fileString;
    % Allocate storage for the outputs
    idx = coder.nullcopy(zeros(1,N,'int32'));
    temp = coder.nullcopy(zeros(1,N));
    k = 1;
    while ~isempty(fileString)
        % Tokenize the string on comma and newline reading an
        % index value followed by a temperature value
        dlm = [',', char(10)];
        [idxStr,fileString] = strtok(fileString, dlm);
        fprintf('Parsed index: %s\n', idxStr);
        [tempStr,fileString] = strtok(fileString, dlm);
        fprintf('Parsed temp: %s\n', tempStr);
        % Convert the numeric strings to numbers
        if coder.target('MATLAB')
            % Parse the numbers using sscanf
            idx(k) = sscanf(idxStr, '%d');
            temp(k) = sscanf(tempStr, '%f');
        else
            % Call C sscanf instead.  Note the '%lf' to read a double.
            coder.ceval('sscanf', [idxStr, NULL], ['%d', NULL], coder.wref(idx(k)));
            coder.ceval('sscanf', [tempStr, NULL], ['%lf', NULL], coder.wref(temp(k)));
        end
        k = k + 1;
    end
    fclose(f);