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

使用strtok分割字符串并存入union时,前序货币名称被异常覆盖的问题

问题:使用Union存储货币数据时,后续输入覆盖之前的名称

我写了一个程序,每行输入货币名称和数值,想把数据存入coin联合数组里。但运行时发现,第一行输入能正确存入,但输入第二行后,之前存的货币名称会被错误修改。

原代码

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <math.h>

int main() {
    int number_coin, index; 
    union coin {
        char name[20]; 
        float value; 
        float amount;
    };
    union coin coins[1000];
    scanf("%d", &number_coin);
    getchar();
    for (index = 0; index < number_coin; index++) {
        char input[40];
        fgets(input, 40, stdin);
        input[strcspn(input, "\n")] = 0; // delete \n in end of input string
        char *token = strtok(input, " ");
        while (token != NULL) {
            strcpy(coins[index].name, token);
            token = strtok(NULL, " ");
            coins[index].value = atof(token);
            token = strtok(NULL, " ");
        }
    }
    return 0;
}

输入示例

2
jibcoin 2
bitcoin 5

问题原因

核心问题是Union的内存共享特性:Union中的所有成员共用同一块内存空间,同一时间只有一个成员的数据是有效的。你在循环中先给name赋值,紧接着又给value赋值,这会直接覆盖name所在的内存区域,导致第一次存储的货币名称被破坏。

比如第一次循环中,coins[0].name存入jibcoin后,马上给coins[0].value赋值2,此时name的内存已经被value的二进制数据覆盖;第二次循环操作coins[1]时,coins[0]的名称已经因为内存共享被破坏,看起来像是被第二行输入修改了。

解决方案

你需要同时存储名称和数值,这种场景应该用**结构体(struct)**替代联合(union)——结构体的每个成员拥有独立的内存空间,不会互相覆盖。

修改后的代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main() {
    int number_coin, index; 
    // 将union改为struct,成员独立分配内存
    struct coin {
        char name[20]; 
        float value; 
        float amount;
    };
    struct coin coins[1000];
    scanf("%d", &number_coin);
    getchar();
    for (index = 0; index < number_coin; index++) {
        char input[40];
        fgets(input, 40, stdin);
        input[strcspn(input, "\n")] = 0; // 去除换行符
        char *token = strtok(input, " ");
        if (token != NULL) {
            strcpy(coins[index].name, token);
            token = strtok(NULL, " ");
            if (token != NULL) {
                coins[index].value = atof(token);
            }
        }
    }
    // 验证存储结果
    for (index = 0; index < number_coin; index++) {
        printf("货币名称:%s,数值:%.1f\n", coins[index].name, coins[index].value);
    }
    return 0;
}

额外优化说明

  • 移除了无意义的头文件(ctype.h、math.h)
  • 把原代码的while循环改为if判断,避免strtok返回NULL时访问非法内存
  • 添加了打印验证逻辑,方便确认数据是否正确存储

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:13:12