stringstream和char在一起时需要注意

本文通过两个示例探讨了在C++中使用stringstream与char类型进行数据转换时可能遇到的问题。第一个示例展示了从字符到字符串转换时的异常输出;第二个示例则揭示了从stringstream读取不同类型的变量可能导致的数据读取错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

       最近碰到了一个stringstream和char联合使用的奇怪bug,  本文不具体说这个bug.


       来看看程序:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

void test(const string &s1, const string &s2)
{
	cout << s1 << endl;
	cout << s2 << endl;
	if(s1 == s2)
	{
		cout << "yes" << endl;
	}
	else
	{
		cout << "no" << endl;
	}
}

int main()
{
	int c1 = '6';
	stringstream ss1;
	ss1 << c1;

	char c2 = '6';
	stringstream ss2;
	ss2 << c2;

	test(ss1.str(), ss2.str());

	return 0;
}
     结果:

54
6
no


     呵呵, 要小心啊。 再看:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

void test(int x, int y)
{
	cout << x << endl;
	cout << y << endl;

	if(x == y)
	{
		cout << "yes" << endl;
	}
	else
	{
		cout << "no" << endl;
	}
}

int main()
{
	stringstream ss;
	ss << 2;

	int c1;
	ss >> c1;

	char c2;
	ss >> c1;

	test(c1, c2);

	return 0;
}
      结果:

2
0
no


      小心。



<think>好的,用户之前询问了如何实现一个基于TCP的局域网聊天室,并添加私聊文件上传下载功能。我之前给出了一个代码框架,现在用户说“把这些合在一起”,可能是指希望得到一个完整的、整合所有功能的代码示例,或者是想了解如何将各个模块整合在一起。 首先,我需要确认用户的需求。用户可能是在尝试整合代码遇到了问题,或者希望看到一个完整的实现。他们可能对如何将私聊、文件上传下载原有的聊天室功能结合起来感到困惑。需要确保代码结构清晰,各个功能模块协调工作。 接下来,回顾之前提供的代码。服务器端客户端都有各自的处理逻辑,比如私聊通过`/pm`命令,文件上传使用`/upload`,下载可能是`/download`。但之前的代码可能缺少部分实现细节,比如下载功能的具体处理逻辑,或者多线程处理文件传输的部分。用户现在希望所有功能整合,可能需要更完整的代码示例。 用户可能的深层需求是能够直接编译运行一个完整的聊天室程序,包含提到的所有功能。他们可能不太熟悉如何将分散的模块整合,或者如何处理多线程、同步问题。需要确保代码的结构合理,比如服务器如何处理多个客户端的连接,如何管理客户端列表,以及如何处理并发文件传输。 另外,用户可能关心代码的编译运行方法,以及测试步骤。所以,在回答中应该包含如何编译、运行服务器客户端,以及如何使用各个功能的说明。同,需要注意代码的可读性,添加必要的注释,方便用户理解。 还要考虑潜在的错误处理,比如文件不存在、传输中断、用户名重复等情况。之前的代码可能没有详细处理这些,整合需要补充。此外,线程同步问题,比如使用互斥锁保护共享资源(客户端列表),也需要确保正确性。 最后,用户可能希望代码具备扩展性,方便后续添加其他功能。因此,代码结构需要模块化,比如分离命令解析、消息处理、文件传输等部分,便于维护扩展。 总结,用户需要一份完整、可运行的代码,整合私聊、文件上传下载功能,并且结构清晰、有必要的错误处理同步机制。需要确保代码的每个部分都正确协同工作,并提供使用说明注意事项,帮助用户顺利部署测试。</think>以下是整合后的完整Linux基于TCP局域网聊天室代码实现,包含群聊、私聊、文件上传/下载功能: ```c /*-----------服务器端代码(server.c)-----------*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <pthread.h> #include <dirent.h> #define MAX_CLIENTS 20 #define BUFFER_SIZE 2048 #define FILE_BUFFER 8192 #define SERVER_FILES "./server_files/" typedef struct { int sockfd; char username[32]; int active; } ClientInfo; ClientInfo clients[MAX_CLIENTS]; pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; // 广播消息给所有客户端 void broadcast(char *msg, int exclude_sock) { pthread_mutex_lock(&mutex); for(int i=0; i<MAX_CLIENTS; i++){ if(clients[i].active && clients[i].sockfd != exclude_sock){ send(clients[i].sockfd, msg, strlen(msg), 0); } } pthread_mutex_unlock(&mutex); } // 处理私聊消息 void send_private(char *sender, char *target, char *msg) { pthread_mutex_lock(&mutex); char buffer[BUFFER_SIZE]; snprintf(buffer, sizeof(buffer), "[PM from %s] %s", sender, msg); for(int i=0; i<MAX_CLIENTS; i++){ if(clients[i].active && !strcmp(clients[i].username, target)){ send(clients[i].sockfd, buffer, strlen(buffer), 0); return; } } // 目标不在线 snprintf(buffer, sizeof(buffer), "用户 %s 不存在或已离线", target); for(int i=0; i<MAX_CLIENTS; i++){ if(clients[i].active && !strcmp(clients[i].username, sender)){ send(clients[i].sockfd, buffer, strlen(buffer), 0); break; } } pthread_mutex_unlock(&mutex); } // 处理文件上传 void handle_file_upload(int sockfd, char *filename, int filesize) { char filepath[256]; snprintf(filepath, sizeof(filepath), "%s%s", SERVER_FILES, filename); FILE *fp = fopen(filepath, "wb"); if(!fp) { char *err_msg = "文件创建失败\n"; send(sockfd, err_msg, strlen(err_msg), 0); return; } int total = 0; char buffer[FILE_BUFFER]; while(total < filesize){ int n = recv(sockfd, buffer, FILE_BUFFER, 0); if(n <= 0) break; fwrite(buffer, 1, n, fp); total += n; } fclose(fp); char msg[BUFFER_SIZE]; snprintf(msg, sizeof(msg), "[系统] 文件 %s 上传成功 (%d bytes)\n", filename, filesize); send(sockfd, msg, strlen(msg), 0); } // 处理文件下载 void handle_file_download(int sockfd, char *filename) { char filepath[256]; snprintf(filepath, sizeof(filepath), "%s%s", SERVER_FILES, filename); FILE *fp = fopen(filepath, "rb"); if(!fp) { char *err_msg = "文件不存在\n"; send(sockfd, err_msg, strlen(err_msg), 0); return; } fseek(fp, 0, SEEK_END); int filesize = ftell(fp); rewind(fp); char header[128]; snprintf(header, sizeof(header), "FILE_START %s %d ", filename, filesize); send(sockfd, header, strlen(header), 0); char buffer[FILE_BUFFER]; while(!feof(fp)){ int n = fread(buffer, 1, FILE_BUFFER, fp); send(sockfd, buffer, n, 0); } fclose(fp); } // 客户端处理线程 void *client_handler(void *arg) { int sockfd = *(int *)arg; char username[32] = {0}; char buffer[BUFFER_SIZE]; // 用户认证 if(recv(sockfd, username, 32, 0) <= 0){ close(sockfd); return NULL; } // 添加客户端到列表 pthread_mutex_lock(&mutex); for(int i=0; i<MAX_CLIENTS; i++){ if(!clients[i].active){ clients[i].sockfd = sockfd; strncpy(clients[i].username, username, 32); clients[i].active = 1; break; } } pthread_mutex_unlock(&mutex); // 广播上线通知 snprintf(buffer, sizeof(buffer), "[系统] %s 进入聊天室\n", username); broadcast(buffer, sockfd); // 消息处理循环 while(1){ int n = recv(sockfd, buffer, BUFFER_SIZE, 0); if(n <= 0) break; buffer[n] = '\0'; if(strncmp(buffer, "/pm ", 4) == 0){ char *target = strtok(buffer+4, " "); char *msg = strtok(NULL, "\n"); if(target && msg) send_private(username, target, msg); } else if(strncmp(buffer, "/upload ", 8) == 0){ char *filename = strtok(buffer+8, " "); char *size_str = strtok(NULL, " "); if(filename && size_str){ handle_file_upload(sockfd, filename, atoi(size_str)); } } else if(strncmp(buffer, "/download ", 10) == 0){ char *filename = buffer + 10; filename[strcspn(filename, "\n")] = 0; handle_file_download(sockfd, filename); } else { char formatted_msg[BUFFER_SIZE]; snprintf(formatted_msg, sizeof(formatted_msg), "%s: %s", username, buffer); broadcast(formatted_msg, sockfd); } } // 客户端断开处理 pthread_mutex_lock(&mutex); for(int i=0; i<MAX_CLIENTS; i++){ if(clients[i].sockfd == sockfd){ clients[i].active = 0; break; } } pthread_mutex_unlock(&mutex); snprintf(buffer, sizeof(buffer), "[系统] %s 离开聊天室\n", username); broadcast(buffer, sockfd); close(sockfd); return NULL; } int main(int argc, char *argv[]) { // 创建服务器目录 mkdir(SERVER_FILES, 0777); int server_fd, new_socket; struct sockaddr_in address; int addrlen = sizeof(address); // 创建TCP socket if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0){ perror("socket failed"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(8080); // 绑定端口 if(bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0){ perror("bind failed"); exit(EXIT_FAILURE); } // 开始监听 if(listen(server_fd, 5) < 0){ perror("listen failed"); exit(EXIT_FAILURE); } printf("服务器已启动,等待连接...\n"); while(1){ if((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen)) < 0){ perror("accept error"); continue; } pthread_t thread; int *client_sock = malloc(sizeof(int)); *client_sock = new_socket; if(pthread_create(&thread, NULL, client_handler, (void*)client_sock) < 0){ perror("无法创建线程"); close(new_socket); } pthread_detach(thread); } return 0; } ``` ```c /*-----------客户端代码(client.c)-----------*/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/socket.h> #include <arpa/inet.h> #include <pthread.h> #include <dirent.h> #define BUFFER_SIZE 2048 #define FILE_BUFFER 8192 #define CLIENT_FILES "./client_files/" int sockfd = 0; char username[32]; // 文件接收线程 void *file_receiver(void *arg) { char buffer[FILE_BUFFER]; while(1){ int n = recv(sockfd, buffer, FILE_BUFFER, 0); if(n <= 0) break; if(strncmp(buffer, "FILE_START ", 11) == 0){ char *filename = strtok(buffer+11, " "); char *size_str = strtok(NULL, " "); int filesize = atoi(size_str); char filepath[256]; snprintf(filepath, sizeof(filepath), "%s%s", CLIENT_FILES, filename); FILE *fp = fopen(filepath, "wb"); int received = 0; while(received < filesize){ int n = recv(sockfd, buffer, FILE_BUFFER, 0); if(n <= 0) break; fwrite(buffer, 1, n, fp); received += n; } fclose(fp); printf("\n文件 %s 下载完成 (%d bytes)\n", filename, filesize); } else { buffer[n] = '\0'; printf("\r%s\n> ", buffer); fflush(stdout); } } return NULL; } // 发送文件 void send_file(char *filepath) { FILE *fp = fopen(filepath, "rb"); if(!fp){ printf("文件打开失败\n"); return; } fseek(fp, 0, SEEK_END); int filesize = ftell(fp); rewind(fp); char filename[256]; strncpy(filename, strrchr(filepath, '/') ? strrchr(filepath, '/')+1 : filepath, 255); char header[128]; snprintf(header, sizeof(header), "/upload %s %d ", filename, filesize); send(sockfd, header, strlen(header), 0); char buffer[FILE_BUFFER]; while(!feof(fp)){ int n = fread(buffer, 1, FILE_BUFFER, fp); send(sockfd, buffer, n, 0); } fclose(fp); printf("文件 %s 上传成功\n", filename); } int main(int argc, char *argv[]) { // 创建客户端目录 mkdir(CLIENT_FILES, 0777); struct sockaddr_in serv_addr; if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ printf("Socket创建错误\n"); return -1; } serv_addr.sin_family = AF_INET; serv_addr.sin_port = htons(8080); // 设置服务器IP地址(需修改为实际地址) if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr) <= 0){ printf("无效地址\n"); return -1; } // 连接服务器 if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0){ printf("连接失败\n"); return -1; } // 用户认证 printf("输入用户名: "); fgets(username, 32, stdin); username[strcspn(username, "\n")] = 0; send(sockfd, username, strlen(username), 0); // 启动接收线程 pthread_t recv_thread; pthread_create(&recv_thread, NULL, file_receiver, NULL); printf("> "); while(1){ char buffer[BUFFER_SIZE] = {0}; fgets(buffer, BUFFER_SIZE, stdin); if(strncmp(buffer, "/pm ", 4) == 0){ send(sockfd, buffer, strlen(buffer), 0); } else if(strncmp(buffer, "/upload ", 8) == 0){ char *filepath = buffer + 8; filepath[strcspn(filepath, "\n")] = 0; send_file(filepath); } else if(strncmp(buffer, "/download ", 10) == 0){ send(sockfd, buffer, strlen(buffer), 0); } else if(strcmp(buffer, "/exit\n") == 0){ break; } else { send(sockfd, buffer, strlen(buffer), 0); } printf("> "); } close(sockfd); return 0; } ``` ### 使用说明 **编译运行:** ```bash # 编译服务器 gcc server.c -o server -lpthread # 编译客户端 gcc client.c -o client -lpthread # 运行服务器 ./server # 运行客户端(另起终端) ./client ``` **主要功能命令:** 1. **群聊消息**:直接输入文字发送 2. **私聊消息**:`/pm [用户名] [消息内容]` 3. **文件上传**:`/upload [文件路径]` 4. **文件下载**:`/download [文件名]` 5. **退出程序**:`/exit` **功能特点:** 1. 多线程处理消息文件传输 2. 支持并发客户端连接(最多20个) 3. 自动创建文件存储目录 4. 用户上线/下线广播通知 5. 文件传输进度显示 6. 基本的错误处理机制 **注意事项:** 1. 需要确保服务器客户端都有对应的文件存储目录(server_files/ client_files/) 2. 文件传输建议不超过2GB 3. 实际使用需要修改服务器IP地址 4. 建议在局域网环境下测试 5. 可通过修改端口号避免冲突 这个完整实现包含TCP通信基础框架、多线程处理、文件传输协议设计等核心要素,可根据实际需求继续扩展用户列表显示、传输加密等功能。
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值