You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将逗号分隔的双精度字符串转为数组:如何保持精度?

JSON-C v0.11 保留双精度数字原始格式输出的解决方案

问题描述

使用JSON-C Library v0.11生成JSON时,需要将逗号分隔的双精度数字字符串转为数组输出。现有字符串:

const char* doubles = "0.1234, 0.5678, 1.1234, 1.5678";

期望输出的JSON数组为:

"doubles": [0.1234, 0.5678, 1.1234, 1.5678]

但使用json_object_new_double时,库会自动为数字添加尾随零,无法保留原始格式。现有处理代码如下:

char *token = strtok(doubles, ",");
while (token != NULL) {
    double current = atof(token);
    json_object_array_add(my_array, json_object_new_double(current));
    token = strtok(NULL, ",");
}
// Add the key-value pair as an array
json_object_object_add(root_obj, "my_array", my_array);

解决方案

方法1:直接解析原始数字字符串为JSON对象

将字符串转为double时会丢失原始格式信息,甚至可能引入精度误差。可以跳过atof转换,直接将修剪后的数字字符串解析为JSON数字对象:

#include <string.h>
#include <ctype.h>
#include <json/json.h>

// 去除字符串两端空格的辅助函数
char* trim_whitespace(char* str) {
    while (isspace((unsigned char)*str)) str++;
    if (*str == 0) return str;
    
    char* end = str + strlen(str) - 1;
    while (end > str && isspace((unsigned char)*end)) end--;
    end[1] = '\0';
    
    return str;
}

// 核心处理逻辑
char *token = strtok((char*)doubles, ",");
while (token != NULL) {
    char* trimmed = trim_whitespace(token);
    // 直接解析原始字符串为JSON数字对象
    json_object* num_obj = json_object_parse(trimmed);
    if (num_obj != NULL) {
        json_object_array_add(my_array, num_obj);
    }
    token = strtok(NULL, ",");
}
json_object_object_add(root_obj, "doubles", my_array);

此方法生成的JSON数组会严格保留原始数字的格式,不会添加多余的尾随零。

方法2:自定义double类型序列化函数

如果必须先将字符串转为double类型,可以通过自定义序列化函数控制输出格式,需要提前保存每个数字的原始字符串:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <json/json.h>

// 自定义序列化函数:使用原始字符串输出数字
int custom_double_serialize(struct json_object* obj, struct json_object_serializer* ser,
                           struct json_object* jso, int depth) {
    const char* original_str = json_object_get_userdata(obj);
    if (original_str) {
        return json_object_serializer_string(ser, original_str, strlen(original_str));
    }
    // 若获取不到原始字符串,使用默认序列化逻辑
    return json_object_double_serialize(obj, ser, jso, depth);
}

// 去除字符串两端空格的辅助函数
char* trim_whitespace(char* str) {
    while (isspace((unsigned char)*str)) str++;
    if (*str == 0) return str;
    
    char* end = str + strlen(str) - 1;
    while (end > str && isspace((unsigned char)*end)) end--;
    end[1] = '\0';
    
    return str;
}

// 核心处理逻辑
char *token = strtok((char*)doubles, ",");
while (token != NULL) {
    char* trimmed = trim_whitespace(token);
    double current = atof(trimmed);
    json_object* num_obj = json_object_new_double(current);
    
    // 将原始字符串保存到JSON对象的userdata中
    json_object_set_userdata(num_obj, strdup(trimmed));
    // 设置自定义序列化函数
    json_object_set_serializer(num_obj, custom_double_serialize, NULL, NULL);
    
    json_object_array_add(my_array, num_obj);
    token = strtok(NULL, ",");
}
json_object_object_add(root_obj, "doubles", my_array);

// 注意:需手动释放userdata中的字符串,避免内存泄漏
int array_len = json_object_array_length(my_array);
for (int i = 0; i < array_len; i++) {
    json_object* elem = json_object_array_get_idx(my_array, i);
    free((void*)json_object_get_userdata(elem));
}

内容的提问来源于stack exchange,提问作者spiderwebdev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 07:27:35