如何处理Node客户端中数量未知的<neighbourAddress>:<weight>命令行参数?
处理可变数量的
<neighbourAddress>:<weight>命令行参数 要搞定这种可重复出现的键值对参数,核心思路就是遍历命令行里从第3位开始的所有剩余参数,对每个参数做字符串分割,把地址和权重提出来后存起来。下面是具体的实现方案,包括代码修改和细节说明:
步骤1:定义邻居数据结构(可选但推荐)
先用结构体把邻居的地址和权重封装起来,代码会更清晰、好维护:
typedef struct { int address; int weight; } Neighbour;
步骤2:遍历并分割参数
从argc的第3个索引(也就是i=3)开始,逐个处理每个<addr>:<weight>格式的参数。这里给你两种靠谱的字符串分割方法:
方法1:用strchr分割(直观可控)
strchr能快速定位冒号的位置,分割后转成整数就行。要是不想修改原始argv的内容,记得先把参数复制到缓冲区里:
#include <stdio.h> #include <stdlib.h> #include <string.h> #include "print_lib.h" int port; int ownAddress; typedef struct { int address; int weight; } Neighbour; int main(int argc, char *argv[]){ if(argc >= 3){ // 原有port和ownAddress的处理逻辑 port = atoi(argv[1]); if((port <= 1024 || port >= 65535) && port != 0){ fprintf(stderr, "Port number has to be between 1024 and 65535.\n"); exit(EXIT_FAILURE); } ownAddress = atoi(argv[2]); if(ownAddress >= 1024 && ownAddress != 0){ fprintf(stderr, "Node's address has to be less than 1024.\n"); exit(EXIT_FAILURE); } // 初始化动态数组存邻居信息 Neighbour *neighbours = NULL; int neighbourCount = 0; // 处理所有邻居参数 for(int i = 3; i < argc; i++){ char paramBuf[256]; // 复制参数到缓冲区,避免修改原始argv strncpy(paramBuf, argv[i], sizeof(paramBuf) - 1); paramBuf[sizeof(paramBuf)-1] = '\0'; // 找冒号的位置 char *colon = strchr(paramBuf, ':'); if(colon == NULL){ fprintf(stderr, "Invalid neighbour format: %s (missing colon)\n", argv[i]); exit(EXIT_FAILURE); } // 分割字符串:把冒号换成结束符,拆分地址和权重 *colon = '\0'; int neighAddr = atoi(paramBuf); int neighWeight = atoi(colon + 1); // 验证邻居地址合法性(和自身地址规则一致) if(neighAddr >= 1024 && neighAddr != 0){ fprintf(stderr, "Neighbour address %d is invalid (must be <1024)\n", neighAddr); exit(EXIT_FAILURE); } // 验证权重为正数(可根据你的业务需求调整) if(neighWeight <= 0){ fprintf(stderr, "Weight for neighbour %d must be positive\n", neighAddr); exit(EXIT_FAILURE); } // 动态扩容数组,存储邻居信息 neighbourCount++; neighbours = realloc(neighbours, neighbourCount * sizeof(Neighbour)); if(neighbours == NULL){ perror("Failed to allocate memory for neighbours"); exit(EXIT_FAILURE); } neighbours[neighbourCount - 1].address = neighAddr; neighbours[neighbourCount - 1].weight = neighWeight; } // 示例:打印所有邻居信息 printf("Found %d neighbours:\n", neighbourCount); for(int i = 0; i < neighbourCount; i++){ printf("- Address: %d, Weight: %d\n", neighbours[i].address, neighbours[i].weight); } // 记得释放动态分配的内存,避免泄漏 free(neighbours); } else { fprintf(stderr, "Too few arguments\n"); exit(EXIT_FAILURE); } return 0; }
方法2:用strtok分割(简洁但要注意线程安全)
strtok能自动分割字符串,但它会修改原始字符串,而且不是线程安全的。要是不需要保留原始argv内容,可以用这种方式:
// 替换上面的循环部分 for(int i = 3; i < argc; i++){ // 第一次调用strtok,用':'当分割符 char *addrStr = strtok(argv[i], ":"); if(addrStr == NULL){ fprintf(stderr, "Invalid neighbour format: %s\n", argv[i]); exit(EXIT_FAILURE); } int neighAddr = atoi(addrStr); // 第二次调用strtok传NULL,表示继续分割上一个字符串 char *weightStr = strtok(NULL, ":"); if(weightStr == NULL){ fprintf(stderr, "Missing weight for neighbour: %s\n", argv[i]); exit(EXIT_FAILURE); } int neighWeight = atoi(weightStr); // 后续的验证、存储逻辑和方法1完全一致 }
关键细节提醒
- 动态数组存储:因为邻居数量不确定,用
realloc动态扩容是最灵活的,不会被固定大小的数组限制住。 - 合法性校验:一定要对邻居地址和权重做检查,比如地址范围、权重是否为正,不然无效输入可能搞崩程序。
- 内存泄漏:动态分配的
neighbours数组,用完一定要用free释放掉。 - 字符串安全:用
strncpy代替strcpy,防止缓冲区溢出;如果参数可能很长,也可以用malloc动态分配缓冲区。
内容的提问来源于stack exchange,提问作者novicekiddo5131
相关产品推荐
相关产品推荐

