Qt无法响应std::string类型信号参数问题

使自定义类型可用于信号槽机制

当信号和槽使用非 Qt 内置类型(如 std::string)作为参数时,必须使用 qRegisterMetaType 注册该类型:

```cpp

// 注册 std::string 类型

qRegisterMetaType<std::string>("std::string");

 

// 现在可以在信号槽中使用 std::string

connect(sender, &Sender::textSignal, receiver, &Receiver::textSlot);

服务器 #include <iostream> #include <string> #include <unordered_map> #include <vector> #include <thread> #include <mutex> #include <winsock2.h> #include <ws2tcpip.h> #include <sstream> #include <random> #include <chrono> #include <algorithm> #pragma comment(lib, "ws2_32.lib") #define PORT 8888 struct User { std::string username; std::string password; std::string rank = "青铜"; }; std::unordered_map<std::string, User> users; std::vector<std::tuple<SOCKET, std::string>> matchQueue; // 只保存 socket 和 username std::mutex mtx; std::vector<std::string> generateQuestions() { std::vector<std::string> questions; std::random_device rd; std::mt19937 gen(rd()); std::uniform_int_distribution<> num(1, 100); std::uniform_int_distribution<> op(0, 3); for (int i = 0; i < 10; ++i) { int a = num(gen), b = num(gen); int oper = op(gen); char ops[] = {'+', '-', '*', '/'}; questions.push_back(std::to_string(a) + " " + ops[oper] + " " + std::to_string(b)); } return questions; } void handleClient(SOCKET clientSocket) { char buffer[1024]; int bytesReceived; while ((bytesReceived = recv(clientSocket, buffer, sizeof(buffer) - 1, 0)) > 0) { buffer[bytesReceived] = '\0'; std::string request(buffer); if (request.find("REGISTER") == 0) { std::istringstream iss(request); std::string cmd, username, password; iss >> cmd >> username >> password; if (users.find(username) != users.end()) { std::string response = "REGISTER_FAIL 用户已存在"; send(clientSocket, response.c_str(), response.size(), 0); } else { User newUser; newUser.username = username; newUser.password = password; users[username] = newUser; std::string response = "REGISTER_SUCCESS 注册成功"; send(clientSocket, response.c_str(), response.size(), 0); } } else if (request.find("LOGIN") == 0) { std::istringstream iss(request); std::string cmd, username, password; iss >> cmd >> username >> password; if (users.find(username) != users.end() && users[username].password == password) { std::string response = "LOGIN_SUCCESS " + username + " " + users[username].rank; send(clientSocket, response.c_str(), response.size(), 0); } else { std::string response = "LOGIN_FAIL 登录失败"; send(clientSocket, response.c_str(), response.size(), 0); } } else if (request.find("MATCH") == 0) { std::istringstream iss(request); std::string cmd, username; iss >> cmd >> username; { std::lock_guard<std::mutex> lock(mtx); matchQueue.push_back(std::make_tuple(clientSocket, username)); std::cout << username << " 进入匹配队列,当前人数:" << matchQueue.size() << std::endl; } if (matchQueue.size() >= 2) { SOCKET c1Socket, c2Socket; std::string c1User, c2User; { std::lock_guard<std::mutex> lock(mtx); c1Socket = std::get<0>(matchQueue[0]); c1User = std::get<1>(matchQueue[0]); c2Socket = std::get<0>(matchQueue[1]); c2User = std::get<1>(matchQueue[1]); matchQueue.erase(matchQueue.begin(), matchQueue.begin() + 2); } std::cout << "创建房间:" << c1User << " vs " << c2User << std::endl; auto questions = generateQuestions(); // 向两个客户端发送题目 std::string qStr; for (auto& q : questions) qStr += q + "|"; std::string msg = "QUESTIONS " + qStr; send(c1Socket, msg.c_str(), msg.size(), 0); send(c2Socket, msg.c_str(), msg.size(), 0); // 接收两个客户端的成绩 char res1[1024], res2[1024]; recv(c1Socket, res1, sizeof(res1), 0); recv(c2Socket, res2, sizeof(res2), 0); std::istringstream iss1(res1), iss2(res2); std::string cmd1, cmd2; int correct1 = 0, correct2 = 0; double time1 = 0.0, time2 = 0.0; iss1 >> cmd1 >> correct1 >> time1; iss2 >> cmd2 >> correct2 >> time2; std::cout << c1User << " 正确数:" << correct1 << ",耗时:" << time1 << std::endl; std::cout << c2User << " 正确数:" << correct2 << ",耗时:" << time2 << std::endl; // 判定胜负 std::string result1 = "RESULT Win", result2 = "RESULT Lose"; if (correct1 < correct2 || (correct1 == correct2 && time1 > time2)) { result1 = "RESULT Lose"; result2 = "RESULT Win"; } send(c1Socket, result1.c_str(), result1.size(), 0); send(c2Socket, result2.c_str(), result2.size(), 0); // 关闭连接 closesocket(c1Socket); closesocket(c2Socket); } } } closesocket(clientSocket); } int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed.\n"; return 1; } SOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverSocket == INVALID_SOCKET) { std::cerr << "Socket creation failed.\n"; WSACleanup(); return 1; } sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_port = htons(PORT); if (bind(serverSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { std::cerr << "Bind failed.\n"; closesocket(serverSocket); WSACleanup(); return 1; } if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR) { std::cerr << "Listen failed.\n"; closesocket(serverSocket); WSACleanup(); return 1; } std::cout << "服务器已启动,正在监听端口 " << PORT << " ...\n"; while (true) { sockaddr_in clientAddr; int clientAddrLen = sizeof(clientAddr); SOCKET clientSocket = accept(serverSocket, (sockaddr*)&clientAddr, &clientAddrLen); if (clientSocket != INVALID_SOCKET) { std::cout << "客户端已连接。\n"; CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)handleClient, (LPVOID)clientSocket, 0, nullptr); } } closesocket(serverSocket); WSACleanup(); return 0; } 客户端 #include <iostream> #include <string> #include <vector> #include <sstream> #include <winsock2.h> #include <ws2tcpip.h> #include <cmath> // 修正 abs -> std::abs #include <chrono> #include <thread> #pragma comment(lib, "ws2_32.lib") #define SERVER_PORT 8888 #define BUFFER_SIZE 1024 SOCKET clientSocket; // 解析服务器发来的题目 std::vector<std::string> parseQuestions(const std::string& data) { std::vector<std::string> questions; std::stringstream ss(data); std::string item; while (std::getline(ss, item, '|')) { if (!item.empty()) questions.push_back(item); } return questions; } // 计算表达式(只支持 + - * /) double evaluate(const std::string& expr) { std::istringstream iss(expr); double a, b; char op; iss >> a >> op >> b; switch (op) { case '+': return a + b; case '-': return a - b; case '*': return a * b; case '/': return b != 0 ? a / b : 0; default: return 0; } } // 开始答题逻辑 void startQuiz(const std::vector<std::string>& questions) { int correct = 0; int totalAttempts = 0; auto startTime = std::chrono::high_resolution_clock::now(); for (const auto& question : questions) { int attempts = 0; bool answered = false; std::cout << "\n题目: " << question << std::endl; while (!answered && attempts < 15) { std::cout << "请输入答案(尝试次数: " << (15 - attempts) << "): "; std::string userAnswer; std::cin >> userAnswer; // 简单验证 try { double userAns = std::stod(userAnswer); double correctAns = evaluate(question); if (std::abs(userAns - correctAns) < 1e-6) { // 使用 std::abs std::cout << "回答正确!\n"; correct++; answered = true; } else { std::cout << "回答错误,正确答案是: " << correctAns << std::endl; attempts++; } } catch (...) { std::cout << "输入无效,请输入数字。\n"; attempts++; } } if (!answered) { std::cout << "本题失败,跳过。\n"; } } auto endTime = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> duration = endTime - startTime; std::cout << "\n答题结束!共答对: " << correct << " 题,耗时: " << duration.count() << " 秒\n"; // 发送答题结果 std::string result = "RESULT " + std::to_string(correct) + " " + std::to_string(duration.count()); send(clientSocket, result.c_str(), result.size(), 0); } int main() { WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { std::cerr << "WSAStartup failed.\n"; return 1; } clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (clientSocket == INVALID_SOCKET) { std::cerr << "Socket creation failed.\n"; WSACleanup(); return 1; } sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(SERVER_PORT); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(clientSocket, (sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) { std::cerr << "连接失败.\n"; closesocket(clientSocket); WSACleanup(); return 1; } std::cout << "连接服务器成功!\n"; char buffer[BUFFER_SIZE]; std::string username; // 登录/注册循环 while (true) { std::cout << "请选择操作: 1.注册 2.登录\n"; int choice; std::cin >> choice; std::string username, password; std::cout << "请输入用户名: "; std::cin >> username; std::cout << "请输入密码: "; std::cin >> password; if (choice == 1) { std::string regMsg = "REGISTER " + username + " " + password; send(clientSocket, regMsg.c_str(), regMsg.size(), 0); int bytes = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0); if (bytes > 0) { buffer[bytes] = '\0'; std::string response(buffer); std::cout << "服务器响应: " << response << std::endl; if (response.find("REGISTER_SUCCESS") != std::string::npos) continue; } } else { std::string loginMsg = "LOGIN " + username + " " + password; send(clientSocket, loginMsg.c_str(), loginMsg.size(), 0); int bytes = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0); if (bytes > 0) { buffer[bytes] = '\0'; std::string response(buffer); std::cout << "服务器响应: " << response << std::endl; if (response.find("LOGIN_SUCCESS") != std::string::npos) { std::istringstream iss(response); std::string cmd, user, rank; iss >> cmd >> user >> rank; username = user; break; } } } } // 发送匹配请求 std::string matchMsg = "MATCH " + username; send(clientSocket, matchMsg.c_str(), matchMsg.size(), 0); std::cout << "等待匹配中...\n"; // 接收题目 int bytes = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0); if (bytes > 0) { buffer[bytes] = '\0'; std::string request(buffer); if (request.find("QUESTIONS") == 0) { std::vector<std::string> questions = parseQuestions(request.substr(10)); startQuiz(questions); } } // 接收胜负结果 bytes = recv(clientSocket, buffer, BUFFER_SIZE - 1, 0); if (bytes > 0) { buffer[bytes] = '\0'; std::string result(buffer); std::cout << "比赛结果: " << result << std::endl; } closesocket(clientSocket); WSACleanup(); return 0; }
09-14
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值