我正在尝试将函数映射到包含在其中的多个输入
使用#include <winsock2.h>
#include <windows.h>
#pragma comment(lib,"ws2_32.lib")
#include <iostream>
#include <thread>
#include <string>
#include <cstdint>
#include <stdexcept>
#include <limits>
#include <algorithm>
// The below variables are used to let the client wait for the server
// port to be opened. If you don't want to use these, especially if the
// client and server are ever run on different machines, you can omit
// these and instead just have the client call connect() in a loop
// until successful...
//
#include <mutex>
#include <condition_variable>
#include <chrono>
static std::condition_variable server_cv;
static std::mutex server_mtx;
static bool server_is_listening = false;
//
static const int num_threads = 2;
static const u_short server_port = 1111;
class winsock_error : public std::runtime_error
{
public:
int errCode;
std::string funcName;
winsock_error(int errCode, const char *funcName) : std::runtime_error("WinSock error"), errCode(errCode), funcName(funcName) {}
};
void WinSockError(const char *funcName, int errCode = WSAGetLastError())
{
throw winsock_error(errCode, funcName);
}
class connection_closed : public std::runtime_error
{
public:
connection_closed() : std::runtime_error("Connection closed") {}
};
class socket_ptr
{
public:
socket_ptr(SOCKET s) : m_sckt(s) {}
socket_ptr(const socket_ptr &) = delete;
socket_ptr(socket_ptr &&src) : m_sckt(src.m_sckt) { src.m_sckt = INVALID_SOCKET; }
~socket_ptr() { if (m_sckt != INVALID_SOCKET) closesocket(m_sckt); }
socket_ptr& operator=(const socket_ptr &) = delete;
socket_ptr& operator=(socket_ptr &&rhs) { m_sckt = rhs.m_sckt; rhs.m_sckt = INVALID_SOCKET; return *this; }
operator SOCKET() { return m_sckt; }
bool operator!() const { return (m_sckt == INVALID_SOCKET); }
private:
SOCKET m_sckt;
}
template <typename T>
T LimitBufferSize(size_t size)
{
return (T) std::min(size, (size_t) std::numeric_limits<T>::max());
}
void sendRaw(SOCKET sckt, const void *buffer, size_t buflen)
{
const char *ptr = static_cast<const char*>(buffer);
while (buflen > 0)
{
int numToSend = LimitBufferSize<int>(buflen);
int numSent = ::send(sckt, ptr, numToSend, 0);
if (numSent == SOCKET_ERROR)
WinSockError("send");
ptr += numSent;
buflen -= numSent;
}
}
void recvRaw(SOCKET sckt, void *buffer, size_t buflen)
{
char *ptr = static_cast<char*>(buffer);
while (buflen > 0)
{
int numToRecv = LimitBufferSize<int>(buflen);
int numRecvd = ::recv(sckt, ptr, numToRecv, 0);
if (numRecvd == SOCKET_ERROR)
WinSockError("recv");
if (numRecvd == 0)
throw connection_closed();
ptr += numRecvd;
buflen -= numRecvd;
}
}
void sendStr(SOCKET sckt, const std::string &str)
{
uint32_t len = LimitBufferSize<uint32_t>(str.size());
uint32_t tmp = htonl(len);
sendRaw(sckt, &tmp, sizeof(tmp));
if (len > 0)
sendRaw(sckt, str.c_str(), len);
}
std::string recvStr(SOCKET sckt)
{
std::string str;
uint32_t len;
recvRaw(sckt, &len, sizeof(len));
len = ntohl(len);
if (len > 0)
{
str.resize(len);
recvRaw(sckt, &str[0], len);
}
return str;
}
void server_thread()
{
std::cout << "[Server] Starting ..." << std::endl;
try
{
socket_ptr sListen(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (!sListen)
WinSockError("socket");
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
addr.sin_port = ::htons(server_port);
int addrlen = sizeof(addr);
if (::bind(sListen, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
WinSockError("bind");
if (::listen(sListen, 1) == SOCKET_ERROR)
WinSockError("listen");
// this is optional...
{
std::unique_lock<std::mutex> lk(server_mtx);
server_is_listening = true;
}
server_cv.notify_all();
//
std::cout << "[Server] Listening for Client ..." << std::endl;
socket_ptr newConnection(::accept(sListen, (SOCKADDR*)&addr, &addrlen));
if (!newConnection)
WinSockError("accept");
std::cout << "[Server] Client Connected!" << std::endl;
try
{
std::string a;
while (std::cin >> a)
sendStr(newConnection, a);
}
catch (const connection_closed &)
{
}
catch (const winsock_error &e)
{
std::cerr << "[Server] Client error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
std::cout << "[Server] Client Disconnected!" << std::endl;
}
catch (const winsock_error &e)
{
std::cerr << "[Server] Error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
catch (const std::exception &e)
{
std::cerr << "[Server] Unexpected Error! " << e.what() << std::endl;
}
std::cout << "[Server] Stopped!" << std::endl;
}
void client_thread()
{
std::cout << "[Client] Starting ..." << std::endl;
try
{
// this is optional, could call connect() below in a loop instead...
std::cout << "[Client] Waiting for Server ..." << std::endl;
{
std::unique_lock<std::mutex> lk(server_mtx);
if (!server_cv.wait_for(lk, std::chrono::seconds(5), []{ return server_is_listening; }))
throw std::runtime_error("Server not listening after 5 seconds!");
}
//
socket_ptr sConnection(::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
if (!sConnection)
WinSockError("socket");
SOCKADDR_IN addr = {};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = ::inet_addr("127.0.0.1");
addr.sin_port = ::htons(server_port);
if (::connect(sConnection, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR)
WinSockError("connect");
std::cout << "[Client] Connected!" << std::endl;
try
{
std::string MOTD;
while (true)
{
MOTD = recvStr(sConnection);
std::cout << "[Client] MOTD: " << MOTD << std::endl;
}
}
catch (const connection_closed &)
{
}
catch (const winsock_error &e)
{
std::cerr << "[Client] Server error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
std::cout << "[Client] Disconnected!" << std::endl;
}
catch (const winsock_error &e)
{
std::cerr << "[Client] Error: " << e.errCode << " on WinSock function: " << e.funcName << std::endl;
}
catch (const std::exception &e)
{
std::cerr << "[Client] Unexpected Error! " << e.what() << std::endl;
}
std::cout << "[Client] Stopped!" << std::endl;
}
int main()
{
WSADATA wsaData;
int ret = ::WSAStartup(MAKEWORD(2, 1), &wsaData);
if (ret != 0)
{
std::cerr << "WinSock Startup failed with error: " << ret << std::endl;
return -1;
}
std::cout << "WinSock Startup successful" << std::endl;
std::thread t[num_threads];
t[0] = std::thread(server_thread);
t[1] = std::thread(client_thread);
for (int i = 0; i < num_threads; ++i) {
t[i].join();
}
::WSACleanup();
return 0;
}
的数据帧的行。我有一个purrr::pmap
下方:
reprex
由reprex package(v0.2.0)于2018-07-16创建。
可以看出,我真的很想创建一个简单的输出
逐行在此给出比率library(tidyverse)
# Create dummy data
e <- 0.3
f <- 1:3
g <- 1:3
df <- tidyr::crossing(e = e, f = f, g = g)
# Create a simple function to use
new_ratio <- function(x, y, z){
return(x/(y + z))
}
# Apply pmap across rows of the dataframe `df` - not working as intended
purrr::pmap(df, ~ new_ratio(x = e, y = f, z = g))
#> [[1]]
#> [1] 0.150 0.075 0.050
#>
#> [[2]]
#> [1] 0.150 0.075 0.050
#>
#> [[3]]
#> [1] 0.150 0.075 0.050
#>
#> [[4]]
#> [1] 0.150 0.075 0.050
#>
#> [[5]]
#> [1] 0.150 0.075 0.050
#>
#> [[6]]
#> [1] 0.150 0.075 0.050
#>
#> [[7]]
#> [1] 0.150 0.075 0.050
#>
#> [[8]]
#> [1] 0.150 0.075 0.050
#>
#> [[9]]
#> [1] 0.150 0.075 0.050
简单的例子。该函数不断返回相同的值
用于不同的输入。在第一行中,我希望
输出e/(f+g)
,在第二行中
0.3/(1 + 1) = 0.15
等
任何人都可以显示如何对此进行更正吗?我不太
从文档中了解如何应用0.3/(1 + 2) = 0.1
答案 0 :(得分:1)
我们可以将列名称更改为参数名称,它应该可以工作
pmap_dbl(setNames(df, c('x', 'y', 'z')), new_ratio)
#[1] 0.150 0.100 0.075 0.100 0.075 0.060 0.075 0.060 0.050
或者,如果我们打算使用~
,则参数为..
,后跟数字
pmap_dbl(df, ~ new_ratio(x = ..1, y= ..2, z = ..3))
#[1] 0.150 0.100 0.075 0.100 0.075 0.060 0.075 0.060 0.050