如何从文件输入行提取带空格产品名与数量并校验有效性
问题描述
输入格式规则:
- 有效格式:
<产品名称>: <数量>,产品名称可包含空格 - 无效格式:数量后附带多余内容(如
笔记本电脑: 5 多余文字)
示例有效输入:
Dell Xps Zt15: 20 Lenovo Wana8Banna: 10 Mac ProPeanuts: 1
现有代码使用sscanf解析时遇到两个问题:
%s只能读取空格前的内容,无法完整提取带空格的产品名- 解析逻辑无法正确校验无效行(数量后有多余内容的情况)
现有代码片段:
while (fgets(line, MAX_LINE_LENGTH,f) ) { sscanf(line,"%s: %d %s",name,&quantity,checker); if (checker[0]!='\0') { fprintf(stderr, ERROR INVALID_LINE); } if (checker[0]=='\0') { root = add_product (root, name, quantity); } }
需求:正确解析产品名、数量,并完成无效行校验。
解决方案
可以通过定位冒号分割字符串的方式解决,步骤如下:
- 定位冒号位置:用
strchr找到行中的冒号:,如果找不到直接判定为无效行 - 提取产品名:从行首到冒号前的部分就是产品名,去掉冒号前可能的末尾空白字符,同时确保产品名非空
- 处理数量及校验多余内容:从冒号后提取整数数量,检查剩余部分是否只有空白字符(换行、空格、制表符等),若有非空白字符则判定为无效行
修改后的代码示例:
#include <string.h> #include <ctype.h> while (fgets(line, MAX_LINE_LENGTH, f)) { // 移除行尾换行符 size_t len = strlen(line); if (len > 0 && line[len-1] == '\n') { line[len-1] = '\0'; len--; } // 查找冒号位置,无冒号则为无效行 char *colon_pos = strchr(line, ':'); if (!colon_pos) { fprintf(stderr, ERROR_INVALID_LINE); continue; } // 提取产品名并清理末尾空白 *colon_pos = '\0'; char *product_name = line; while (colon_pos > product_name && isspace((unsigned char)*(colon_pos-1))) { colon_pos--; *colon_pos = '\0'; } // 校验产品名非空 if (strlen(product_name) == 0) { fprintf(stderr, ERROR_INVALID_LINE); continue; } // 处理数量部分,跳过冒号后空白 char *quantity_part = colon_pos + 1; while (isspace((unsigned char)*quantity_part)) { quantity_part++; } // 提取整数数量,校验有效性 int quantity; char *end_ptr; quantity = strtol(quantity_part, &end_ptr, 10); if (end_ptr == quantity_part) { fprintf(stderr, ERROR_INVALID_LINE); continue; } // 校验数量后无多余内容 while (isspace((unsigned char)*end_ptr)) { end_ptr++; } if (*end_ptr != '\0') { fprintf(stderr, ERROR_INVALID_LINE); continue; } // 解析成功,添加到二叉树 root = add_product(root, product_name, quantity); }
代码说明:
- 先移除行尾换行符,避免干扰后续处理
- 用
strchr分割产品名与数量区域,确保完整提取带空格的产品名 - 借助
strtol提取数量,通过end_ptr定位提取后的剩余位置,校验是否存在非空白的多余内容 - 补充了产品名非空、数量有效等边界场景的校验
内容的提问来源于stack exchange,提问作者Ghnb Trcv
相关产品推荐
相关产品推荐

