C语言:如何将char转字符串传strcpy?活动网卡接口名传strcpy失败如何解决?
C语言问题解答
问题1:单个char类型字符转字符串用于strcpy
strcpy函数要求传入的源参数是以'\0'结尾的字符串,而单个char只是一个独立字符,没有终止符,直接使用会导致strcpy读取越界(因为它会一直找'\0'直到内存里的随机位置)。这里有几种简单可靠的解决方法:
方法1:手动构建长度为2的字符串数组
直接把字符放到数组第一个位置,第二个位置手动添加终止符:char c = 'X'; char str_buf[2]; str_buf[0] = c; str_buf[1] = '\0'; // 必须添加终止符 strcpy(your_dest_str, str_buf);方法2:用sprintf格式化生成字符串
利用格式化函数自动生成带终止符的字符串,写法更灵活:char c = 'Y'; char temp_str[2]; sprintf(temp_str, "%c", c); // 自动在末尾补'\0' strcpy(your_dest_str, temp_str); // 也可以直接写入目标缓冲区(确保目标有足够空间) sprintf(your_dest_str, "%c", c);方法3:直接写入目标缓冲区并补终止符
如果目标缓冲区已有预留空间,也可以这么写:char c = 'Z'; char dest[2]; dest[0] = c; dest[1] = '\0';
问题2:活动网络接口名传入后无法获取MAC地址的问题
核心原因
你用fgets读取接口名时,会把输入的换行符\n也一起读进interface数组里!比如你打印看到的interface :: wlp1s0,实际上内存里的内容是"wlp1s0\n\0",而手动写的"wlp1s0"是没有换行符的。内核的网络接口识别逻辑会把带换行的字符串当成无效接口名,所以ioctl调用失败。
解决方法
只需要在读取后移除换行符即可,这里推荐两种可靠的方式:
方式1:用strcspn快速移除换行符(最简洁)
strcspn会返回字符串中第一个匹配指定字符的位置,我们直接把这个位置设为'\0',不管有没有换行都安全:
while (fgets(interface, 100, f) != NULL) { // 移除换行符(包括可能的回车符) interface[strcspn(interface, "\n\r")] = '\0'; }
方式2:用strchr查找换行符并替换
如果需要更明确的逻辑,可以用strchr定位换行符:
while (fgets(interface, 100, f) != NULL) { char *newline = strchr(interface, '\n'); if (newline != NULL) { *newline = '\0'; // 把换行符替换成终止符 } }
额外优化建议
另外注意:<linux/if.h>中定义了IFNAMSIZ(通常是16),这是内核允许的网络接口名最大长度,你可以把interface数组的长度设为IFNAMSIZ,避免不必要的内存浪费,同时防止过长的接口名导致溢出。
修改后的完整健壮代码(关键部分优化):
#include <string.h> #include <stdio.h> #include <stdlib.h> #include <sys/socket.h> #include <sys/ioctl.h> #include <linux/if.h> #include <netdb.h> #define MAX_IF_NAME_LEN IFNAMSIZ // 使用内核定义的最大接口名长度 char interface[MAX_IF_NAME_LEN] = {0}; char reader_mac[13] = {0}; int main() { FILE *f = popen("ip addr show | awk '/inet.*brd/{print $NF}'", "r"); if (f == NULL) { // 检查popen是否成功 perror("popen failed"); return 1; } if (fgets(interface, MAX_IF_NAME_LEN, f) != NULL) { interface[strcspn(interface, "\n\r")] = '\0'; } printf("interface :: %s\n", interface); pclose(f); struct ifreq s; int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); if (fd == -1) { // 检查socket创建是否成功 perror("socket failed"); return 1; } strncpy(s.ifr_name, interface, IFNAMSIZ-1); // 用strncpy更安全,防止溢出 s.ifr_name[IFNAMSIZ-1] = '\0'; // 确保终止符存在 if (0 == ioctl(fd, SIOCGIFHWADDR, &s)) { int i; for (i = 0; i < 6; ++i){ unsigned char data = s.ifr_addr.sa_data[i]; sprintf(reader_mac+(i*2), "%02x", data); } reader_mac[12] = '\0'; printf("reader_mac ::: %s\n",reader_mac); } else { perror("ioctl failed"); // 打印错误信息,方便调试 } close(fd); // 别忘了关闭socket return 0; }
内容的提问来源于stack exchange,提问作者Mahamutha M
相关产品推荐
相关产品推荐

