C中的字符串动态分配

string dynamic allocation in C

我正在编写一个函数,需要:

  1. 从用户那里得到一个完整的句子

  2. 为每个单词动态分配一个可以包含它的内存块

  3. 复制到里面,保存地址到*words指针数组

我写了一个循环,在每次迭代中从用户插入的句子中获取一个词,但我无法正确地动态分配它。 这是我的:

char str[50];
while(scanf("%s", str) != EOF)
{
    int len = strlen(str);
    char *words = (char*) malloc((len+1)*sizeof(char));
}

我还需要确保:

条件 while(scanf("%s", str) != EOF) 是一个潜在的无限循环,只有当您通过命令行向程序提供 EOF 信号时才会停止。

对于包含所有单词的单个字符串,您需要在每次读取时重新分配内存以增加保存字符串的内存space。

你可以这样做:

Live demo

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

int ret_words(char **words) { //double pointer argument
    char str[50];
    char *temp = malloc(1); //first allocation required
    int count = 0;

    if(temp == NULL){       //allocation error
        return -1;
    }
    do{
        temp = realloc(temp, strlen(str) + strlen(temp) + 2); //reallocate space on
                                                              //each iteration
        if(temp == NULL){                                      
            return -1;
        }
        count++; //count words
    } while (scanf("%49s", str) == 1 && strcat(temp, str) //scan str and append to temp
      && getchar() != '\n' && strcat(temp, " "));         //with spaces between

    *words = temp; //assign temp to words
    return count; //return word count
}
int main() {

    int ret;
    char *words; //pointer to the array of strings
    puts("Enter the string");
    putchar('>');
    ret = ret_words(&words); //returned number of words on success, -1 on error

    printf("Inputed string: %s\nNumber of words: %d", words, ret); //test print
}

约束:在循环结束的最后一个输入单词之后不能有任何 spaces。

现在,如果您想要像结构这样的二维数组,不仅为单词本身动态分配,而且为指向这些字符串的指针动态分配,您将需要一些更特殊的东西,一个三重指针。

将其视为指向字符串数组的指针,这是您需要作为函数参数的内容,以便使调用函数(在本例中为主函数)中的更改永久生效。

Live demo

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

int ret_words(char ***words) { //triple pointer argument
    char str[50];
    int count = 0;
    char **temp = malloc(sizeof *temp); //allocate a pointer to pointer to char

    if(temp == NULL){       //allocation error
        return -1;
    }
    do {
        temp = realloc(temp, (count + 1) * sizeof *temp); //reallocate space at every scan
        if(temp == NULL){
            return -1;
        } 
        temp[count] = malloc(strlen(str) + 1);
        count++;
    } while (scanf("%49s",temp[count - 1]) == 1 //scan str and append to temp
      && getchar() != '\n');                    //with spaces between

    *words = temp; //assing the allocated array of pointer to the argument
    return count; //return word count
}
int main()
{ 
    char **words; // pointer to pointer to navigate the array of strings

    int ret;
    puts("Enter the string");
    putchar('>');
    ret = ret_words(&words); //returned number of words on success, -1 on error

    for(int i = 0; i < ret; i++) //print each stored one word string
        printf("Word %d: %s\n",i + 1, words[i]);

    printf("Word count: %d", ret); //print the number of words
}

约束:在循环结束的最后一个输入单词之后不能有任何 spaces。

请注意,由于这些赋值是通过函数的参数进行的,因此存在额外的间接级别,如果它们要在适当的位置使用或由函数返回,您只需要一个简单的指针,在第一个样本中,在第二个样本中是双指针。

假设以下限制已嵌入到您的代码片段中:

  • 最大字长为49字节,
  • 用户在句子结束后发出文件结束信号。

这是一个构造指针数组的简单函数:

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

struct context {
    char **array;
    int count;
};

int read_sentence(struct context *cp) {
    char buf[50];

    cp->array = NULL;
    cp->count = 0;

    while (scanf("%49s", buf) == 1) {
        // another word was read
        char **new_array = realloc(cp->array, (cp->count + 1) * sizeof(*new_array));
        char *p = strdup(buf);
        if (new_array == NULL || p == NULL) {
            // allocation error: free previously allocated memory and return -1
            free(p);
            if (new_array != NULL) {
                cp->array = new_array;
            }
            while (cp->count > 0) {
                free(cp->array[--cp->count]);
            }
            free(cp->array);
            cp->array = NULL;
            return -1;
        }
        cp->array = new_array;
        cp->array[cp->count++] = p;
    }
    return cp->count;
}