C ++,从函数返回字符串; boost :: asio读/写

时间:2014-12-31 04:58:12

标签: c++ string boost boost-asio

我得到一个编译错误,另外我不能在不给它数组元素的情况下提升:: asio :: read buf。

std::string eport::read_data (void)
{
    io_service io;  // create the I/O service that talks to the serial device
    serial_port port (io, PORT);    // create the serial device, note it takes the io service and the port name
    error_code ec;  // address used for error checking
    std::string buf [100];  // data with crc on end

    try
    {
        read (port, buffer (buf), ec);
        std::cout << "eport::read: result: " << buf << std::endl;
    }
    catch (error_code &ec)
    {
        std::cout << "eport::read: ERROR: " << ec << std::endl; 
        return "error";
    }

    std::cout << "eport::read: SUCCESS" << std::endl;

    return buf;

错误:

eport.cc:83:9: error: could not convert ‘(std::string*)(& buf)’ from ‘std::string* {aka std::basic_string<char>*}’ to ‘std::string {aka std::basic_string<char>}’

该函数是否需要转换为const char *?我不确定是什么问题。感谢任何帮助,谢谢。

更新代码

这是我的代码。我希望它可以帮助某人,因为asio缺乏网上的好例子。我知道我的写功能可以写得更好,而且这段代码还没有经过测试,所以我不确定我是否做得对。感谢。

#include "../include/main.H"
#include <boost/asio.hpp>   // asynchronous input/output
#include <boost/crc.hpp>    // cyclic redundancy code (for data checking)

using namespace::boost::system;
using namespace::boost::asio;

const char *PORT = "/dev/ttyS0";

// serial port communication setup
serial_port_base::baud_rate BAUD (9600);    // what baud rate do we communicate at (default is 9600)
serial_port_base::character_size C_SIZE (8);    // how big is each "packet" of data (default is 8 bits)
serial_port_base::flow_control FLOW (serial_port_base::flow_control::none); // what flow control is used (default is none)
serial_port_base::parity PARITY (serial_port_base::parity::none);   // what parity is used (default is none)
serial_port_base::stop_bits STOP (serial_port_base::stop_bits::one);    // how many stop bits are used (default is one)

int eport::initialize (void)
{
    io_service io;  // create the I/O service that talks to the serial device
    serial_port port (io, PORT);    // create the serial device, note it takes the io service and the port name

    // set serial port options
    port.set_option (BAUD);
    port.set_option (C_SIZE);
    port.set_option (FLOW);
    port.set_option (PARITY);
    port.set_option (STOP);

    return 0;
}

int eport::write_data (std::string data)
{
    io_service io;  // create the I/O service that talks to the serial device
    serial_port port (io, PORT);    // create the serial device, note it takes the io service and the port name
    error_code ec;  // address used for error checking
    boost::crc_32_type crcresult;   // used for communication checking
    char buf [1024];    // buffer to hold data
    int crc;    // holds crc value
    std::ostringstream convert; // used to convert int to string
    std::string data_crc;   // data with crc on end
    std::stringstream ss;   // used to add strings

    strncpy (buf, data.c_str(), sizeof(buf));   // put data into buffer
    buf [sizeof(buf) - 1] = 0;  // make sure the last element has a null

    crcresult.process_bytes (buf, sizeof(buf)); // get crc value from buffer contents
    crc = crcresult.checksum(); // put crc value into integer
    convert << crc; // convert integer to string
    ss << data << convert.str ();   // add crc string to data string
    data_crc = ss.str ();   // data string with crc appended to be used in reading / writing
    std::cout << "eport::write: data with crc: " << data_crc << std::endl; 

    std::cout << "eport::write: writing: " << data_crc << std::endl; 
    write (port, buffer (data_crc, sizeof(data_crc)), ec);  // write data with crc to serial device

    if (ec) // if error code is true, print and return
    {
        std::cout << "eport::write: ERROR: " << ec << std::endl; 
        return -1;
    }

    std::cout << "eport::write: SUCCESS" << std::endl;

    return crc;
}

std::string eport::read_data (void)
{
    io_service io;  // create the I/O service that talks to the serial device
    serial_port port (io, PORT);    // create the serial device, note it takes the io service and the port name
    error_code ec;  // address used for error checking
    streambuf sb;   // asio stream buffer to hold read data
    std::string buf;    // read buffer will be put into this string

    size_t transferred = read (port, sb, ec);   // read data from serial device
    buf.resize (transferred);   // resize the string to the read data size
    sb.sgetn (&buf[0], buf.size ());    // stores characters from the stream to the array
    std::cout << "eport::read: result: " << buf << std::endl;

    if (ec)
    {
        std::cout << "eport::read: ERROR: " << ec << std::endl; 
        return "error";
    }

    std::cout << "eport::read: SUCCESS" << std::endl;

    return buf;
}

3 个答案:

答案 0 :(得分:1)

bufstd::string的数组。您应该更改原型或只返回一个字符串。例如buf[0]

你最想要的可能是:

std::string buf;  // No [100]

答案 1 :(得分:1)

您的代码存在问题需要回答,更具体地说,您如何知道将发送到read函数的字符数?

但是,您的问题的一般答案是使用字符数组,然后将其作为std :: string返回:

std::string eport::read_data (void)
{
    io_service io;  // create the I/O service that talks to the serial device
    serial_port port (io, PORT);    // create the serial device, note it takes the io service and the port name
    error_code ec;  // address used for error checking
    char buf [100];  // data with crc on end

    try
    {
        read (port, buf, ec);
        std::cout << "eport::read: result: " << buf << std::endl;
    }
    catch (error_code &ec)
    {
        std::cout << "eport::read: ERROR: " << ec << std::endl; 
        return "error";
    }

    std::cout << "eport::read: SUCCESS" << std::endl;

    return buf;
}

std::string构造函数将最后将buf复制到std :: string。

现在,如果有办法确定读取的字符数,则必须以不同方式编写函数。大多数read函数都有一个参数,指定要读取的最大字符数,并在某处返回读取的字符数。

假设您可以重写(或调用)具有这两个属性的不同读取函数,代码将如下所示:

std::string eport::read_data (void)
{
    io_service io;  // create the I/O service that talks to the serial device
    serial_port port (io, PORT);    // create the serial device, note it takes the io service and the port name
    error_code ec;  // address used for error checking
    char buf [100];  // data with crc on end
    int numCharsRead = 0;
    try
    {
        numCharsRead = read2 (port, buf, 100, ec);
        std::cout << "eport::read: result: " << buf << std::endl;
    }
    catch (error_code &ec)
    {
        std::cout << "eport::read: ERROR: " << ec << std::endl; 
        return "error";
    }

    std::cout << "eport::read: SUCCESS" << std::endl;

    return std::string(buf, numCharsRead);
}

请注意return的差异。 std :: string是从字符数组构造的,但最多只能有numCharsRead个字符。

答案 2 :(得分:1)

  1. 最通用的方法是使用asio::streambuf

    streambuf sb;
    size_t transferred = read (port, sb, ec);
    

    根据文件:

      

    此函数用于从流中读取一定数量的字节数据。该调用将阻塞,直到满足下列条件之一:

         
        
    • 提供的缓冲区已满(即已达到最大大小)。
    •   
    • 发生错误。
    •   
         

    此操作是根据对流read_some函数的零次或多次调用实现的。

    然后,将其复制到字符串:

    std::string buf;
    buf.resize(transferred);
    sb.sgetn(&buf[0], buf.size());
    

  2. 或者,预分配预期大小的缓冲区:

    std::string buf(100u, '\0');
    size_t transferred = read (port, buffer(buf), ec);
    buf.resize(transferred);
    

  3. 对于更复杂的方案,请使用read_until

    streambuf sb;
    size_t transferred = read_until(port, sb, "\r\n", ec);
    

    这将在"\r\n"遇到read_some之前阅读(注意:可能会阅读更多内容,但在看到分隔符后又不会再次调用ec。)


  4. 更复杂的停止条件可以使用overload that takes a MatchCondition functor

  5. 关于异常处理的注意事项

    如果您通过error_code接收{{1}},则不会抛出任何例外