繁体   English   中英

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

[英]C++ , return string from function; boost::asio read / write

我收到一个编译错误,另外,我在没有给它数组元素的情况下也无法boost :: 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;
}

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

您最可能想要的是:

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

您的代码中有一些问题需要回答,更具体地说,您如何知道将发送给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字符。

  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 )。


  4. 更复杂的停止条件可以使用带有MatchCondition函数重载

关于异常处理的注意事项

如果您通过ec来接收error_code ,则不会引发任何异常

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM