C语言读取/etc/passwd提取用户名与Shell的代码问题求助
问题修复:读取/etc/passwd提取用户名与Shell的C程序
原代码的核心问题
- 参数传递错误:main中调用
customized_print("%s", outbuff),但函数定义要求传入待处理的缓冲区buff和输出缓冲区outbuff,传参完全不匹配。 - 逐字节读取逻辑错误:每次只读1字节就调用处理函数,无法获取完整行数据,自然没法正确解析字段。
- 运算符优先级错误:
outbuff[j++]=buff[i++] == ':'中,==优先级高于=,实际是把布尔值(0/1)赋值给输出缓冲区,而非目标字符。 - 未处理行边界:没有累积字符到换行符,导致无法按行解析
/etc/passwd的结构。 - 输出缓冲区未初始化:
outbuff每次使用前未清空,可能残留垃圾数据。
修复后的完整代码
#include <unistd.h> #include <fcntl.h> // 自定义printf原型(假设环境提供该函数实现) int printf(const char *text, ...); void parse_passwd_line(char* line, char* outbuff); int main(void) { int fd; char line[512]; char outbuff[512]; int size; int pos = 0; fd = open("/etc/passwd", O_RDONLY); if (fd < 0) { printf("Error opening file\n"); return -1; } // 累积读取字符,直到换行或缓冲区满 while ((size = read(fd, &line[pos], 1)) > 0) { if (line[pos] == '\n' || pos >= 511) { line[pos] = '\0'; // 终止字符串 parse_passwd_line(line, outbuff); printf("%s\n", outbuff); pos = 0; // 重置位置,处理下一行 } else { pos++; } } // 处理文件末尾无换行的剩余内容 if (pos > 0) { line[pos] = '\0'; parse_passwd_line(line, outbuff); printf("%s\n", outbuff); } close(fd); return 0; } void parse_passwd_line(char* line, char* outbuff) { int i = 0, j = 0; int colon_count = 0; // 清空输出缓冲区 for (int k = 0; k < 512; k++) { outbuff[k] = '\0'; } // 提取第一个冒号前的用户名 while (line[i] != '\0' && line[i] != ':') { outbuff[j++] = line[i++]; } outbuff[j++] = ':'; // 添加分隔符 // 跳过前5个冒号,定位到第六个冒号后的Shell部分 while (line[i] != '\0' && colon_count < 5) { if (line[i++] == ':') { colon_count++; } } // 提取Shell部分 while (line[i] != '\0' && line[i] != '\n') { outbuff[j++] = line[i++]; } }
修复说明
- 按行读取:在main中累积字符直到换行符,确保每次处理的是完整的一行数据。
- 修正参数传递:调用
parse_passwd_line时传入完整行缓冲区和输出缓冲区,匹配函数定义。 - 修复运算符问题:直接复制字符,避免错误的优先级导致的赋值错误。
- 初始化输出缓冲区:每次处理前清空
outbuff,避免垃圾数据干扰。 - 处理文件末尾:针对文件最后一行无换行的情况,确保剩余内容也能被解析。
- 重命名函数:将
customized_print改为parse_passwd_line,更符合功能语义。
内容的提问来源于stack exchange,提问作者Mozart
相关产品推荐
相关产品推荐

