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

如何用void函数实现字符串动态分配及相关DMA问题

C语言动态内存分配问题解答

1. 改写为void版的动态字符串创建函数

要实现create_string(&str)的调用方式,需要传递指针的指针作为参数——因为我们要修改外部指针变量str的指向,而非指针指向的内容。具体代码如下:

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

void create_string(char **dest) {
    // 初始化动态内存,初始大小为0
    *dest = malloc(0 * sizeof(char));
    if (*dest == NULL) { // 内存分配失败直接返回
        return;
    }
    unsigned int size = 0;
    char c;

    while (1) {
        scanf("%c", &c);
        // 遇到空格或换行停止读取
        if (c == ' ' || c == '\n') {
            break;
        }
        size++;
        // 用临时变量接收realloc返回值,避免分配失败丢失原内存地址
        char *temp = realloc(*dest, size * sizeof(char));
        if (temp == NULL) {
            free(*dest);
            *dest = NULL;
            return;
        }
        *dest = temp;
        (*dest)[size - 1] = c;
    }
    // 分配额外空间存储字符串结束符'\0'
    char *temp = realloc(*dest, (size + 1) * sizeof(char));
    if (temp == NULL) {
        free(*dest);
        *dest = NULL;
        return;
    }
    *dest = temp;
    (*dest)[size] = '\0';
}

int main() {
    char *str = NULL;
    create_string(&str);
    if (str != NULL) {
        printf("读取的字符串:%s\n", str);
        printf("字符串长度:%lu\n", strlen(str));
        free(str); // 记得释放内存
    }
    return 0;
}

关键说明:

  • char **dest接收外部指针的地址,通过*dest直接修改外部指针的指向
  • 新增内存分配失败的错误处理,避免内存泄漏或程序崩溃
  • 每次realloc用临时变量过渡,防止分配失败时丢失原内存地址

2. 二维数组的动态内存分配实现

C语言中二维数组的动态分配主要有两种常用方式:

方式1:行指针数组(每行可不等长)

先分配存储指针的数组,再为每个指针单独分配行内存,适合每行长度不同的场景:

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

int main() {
    int rows = 3;
    int cols[] = {2, 4, 3}; // 每行列数可自定义

    // 步骤1:分配行指针数组
    int **arr = malloc(rows * sizeof(int*));
    if (arr == NULL) {
        return 1;
    }

    // 步骤2:为每行分配内存并初始化
    for (int i = 0; i < rows; i++) {
        arr[i] = malloc(cols[i] * sizeof(int));
        if (arr[i] == NULL) {
            // 分配失败时回滚已分配的内存
            for (int j = 0; j < i; j++) {
                free(arr[j]);
            }
            free(arr);
            return 1;
        }
        for (int j = 0; j < cols[i]; j++) {
            arr[i][j] = i * 10 + j;
        }
    }

    // 打印数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols[i]; j++) {
            printf("%d ", arr[i][j]);
        }
        printf("\n");
    }

    // 释放内存:先释放每行,再释放指针数组
    for (int i = 0; i < rows; i++) {
        free(arr[i]);
    }
    free(arr);

    return 0;
}

方式2:连续内存的二维数组(模拟静态数组)

一次性分配连续内存块,通过偏移量访问元素,内存更紧凑,适合行列固定的场景:

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

int main() {
    int rows = 3;
    int cols = 4;

    // 步骤1:分配连续内存块,总大小为rows*cols个int
    int *arr = malloc(rows * cols * sizeof(int));
    if (arr == NULL) {
        return 1;
    }

    // 步骤2:通过偏移量访问元素,等价于静态数组的arr[i][j]
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            arr[i * cols + j] = i * 10 + j;
        }
    }

    // 打印数组
    for (int i = 0; i < rows; i++) {
        for (int j = 0; j < cols; j++) {
            printf("%d ", arr[i * cols + j]);
        }
        printf("\n");
    }

    // 释放内存:只需一次free
    free(arr);

    return 0;
}

如果想用arr[i][j]的语法访问连续内存,可以额外分配指针数组映射行地址:

int **arr_ptr = malloc(rows * sizeof(int*));
for (int i = 0; i < rows; i++) {
    arr_ptr[i] = arr + i * cols;
}
// 此时可用arr_ptr[i][j]访问元素
// 释放时先释放arr_ptr,再释放arr

3. 输入特定字符串停止扫描(支持多类型)

核心思路:先读取整行输入,判断是否为停止标记(如"STOP"),若是则终止;否则将输入转换为对应数据类型。对于结构体等复杂类型,可先解析各字段再判断停止条件。

示例1:读取int直到输入"STOP"

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

int main() {
    char buffer[100];
    int num;

    while (1) {
        printf("输入整数或STOP停止:");
        fgets(buffer, sizeof(buffer), stdin);
        // 去掉fgets读取的换行符
        buffer[strcspn(buffer, "\n")] = '\0';

        if (strcmp(buffer, "STOP") == 0) {
            break;
        }

        // 转换为int并验证格式
        if (sscanf(buffer, "%d", &num) == 1) {
            printf("读取到整数:%d\n", num);
        } else {
            printf("输入格式错误,请重新输入\n");
        }
    }

    printf("已停止输入\n");
    return 0;
}

示例2:读取自定义结构体直到输入"STOP"

假设结构体包含姓名和年龄:

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

typedef struct {
    char name[50];
    int age;
} Person;

int main() {
    char buffer[100];
    Person p;

    while (1) {
        printf("输入姓名+年龄(空格分隔),或输入STOP停止:");
        fgets(buffer, sizeof(buffer), stdin);
        buffer[strcspn(buffer, "\n")] = '\0';

        if (strcmp(buffer, "STOP") == 0) {
            break;
        }

        // 解析结构体字段并验证格式
        if (sscanf(buffer, "%s %d", p.name, &p.age) == 2) {
            printf("读取到人员信息:姓名=%s,年龄=%d\n", p.name, p.age);
        } else {
            printf("输入格式错误,请重新输入\n");
        }
    }

    printf("已停止输入\n");
    return 0;
}

注意事项

  • 用fgets读取整行输入,避免scanf残留的换行符干扰后续读取
  • strcspn用于去除换行符,确保字符串比较准确
  • 对于bool类型,可将输入转换为0/1或"true"/"false"后再判断停止条件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 05:25:51