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

C语言中无最大长度限制的不同长度元素填充缓冲区方案咨询

C语言动态长度字符串栈的实现修正

原问题代码

void push(struct Stack *stack, void *element)
{
    if (stack->len < stack->size)
    {
        memcpy(stack->arr + stack->len * sizeof(stack->elem_size), element, strlen((char*) element));
        printf("Pushed: %s\n", (char *)element);
        stack->len++;
    }
    else
    {
        printf("Stack is full.\n");
    }
}

void display(struct Stack *stack)
{
    char** arr = (char**) stack->arr;
    for (int i = 0; i < stack->len; i++)
    {
        printf("[%s]\n", stack->arr + i * stack->elem_size);
    }
    printf("Done\n");
}

核心问题分析

  1. 指针算术错误:void*类型不支持直接进行指针算术,且sizeof(stack->elem_size)取的是elem_size变量自身的大小(比如size_t类型通常占8字节),而非元素的实际长度,导致元素存储位置计算完全错误。
  2. 字符串存储不完整:memcpy仅复制了strlen(element)字节,未包含字符串终止符\0,后续打印会出现乱码。
  3. 遍历逻辑错误:display中将stack->arr强制转为char**(指针数组),但实际我们是直接在缓冲区存储字符串内容,而非指针,且固定步长的指针偏移完全不适应动态长度的字符串。

解决方案:带长度前缀的缓冲区存储

要在固定大小的缓冲区中存储动态长度字符串,需在每个元素前存储其长度,以此准确定位每个元素的位置。同时调整Stack结构体,增加缓冲区已使用字节的偏移量跟踪。

调整后的Stack结构体

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

typedef struct Stack {
    void *arr;          // 固定大小的缓冲区(比如1024字节)
    size_t size;        // 缓冲区总大小(如1024)
    size_t len;         // 元素个数
    size_t offset;      // 当前缓冲区已使用的字节偏移量
} Stack;

修正后的push函数

void push(struct Stack *stack, void *element)
{
    char *str = (char*)element;
    size_t str_len = strlen(str);
    // 计算当前元素需要的总空间:长度前缀(size_t) + 字符串内容 + 终止符
    size_t total_size = sizeof(size_t) + str_len + 1;

    // 检查缓冲区剩余空间是否足够
    if (stack->offset + total_size <= stack->size)
    {
        // 写入长度前缀
        *(size_t*)((char*)stack->arr + stack->offset) = str_len;
        // 复制字符串(含终止符)
        memcpy((char*)stack->arr + stack->offset + sizeof(size_t), str, str_len + 1);
        
        printf("Pushed: %s\n", str);
        stack->len++;
        stack->offset += total_size;
    }
    else
    {
        printf("Stack is full. Remaining space: %zu bytes\n", stack->size - stack->offset);
    }
}

修正后的display函数

void display(struct Stack *stack)
{
    size_t current_offset = 0;
    for (int i = 0; i < stack->len; i++)
    {
        // 读取当前元素的长度
        size_t str_len = *(size_t*)((char*)stack->arr + current_offset);
        // 定位字符串起始地址
        char *str = (char*)stack->arr + current_offset + sizeof(size_t);
        printf("[%s]\n", str);
        // 偏移到下一个元素的起始位置
        current_offset += sizeof(size_t) + str_len + 1;
    }
    printf("Done\n");
}

关键调整说明

  • 指针算术转换:将void*转为char*进行指针偏移,确保按字节单位计算位置,适配动态长度元素。
  • 长度前缀存储:在每个字符串前写入其长度,遍历可通过长度值准确定位下一个元素的起始位置。
  • 完整字符串存储:复制时包含\0终止符,保证字符串能正常打印和使用。
  • 剩余空间检查:基于已使用偏移量计算剩余空间,而非元素个数,符合动态长度存储的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 00:13:14