将1D char *分区为2D char **

时间:2017-01-24 02:46:29

标签: c arrays c-strings

关于将2D阵列转换为1D阵列存在很多问题,但我正在尝试恰恰相反。我正在尝试将字符串分区为常量长度的子字符串,并将它们放在2D数组中。此2D矩阵的每一行应包含初始字符串的子字符串,如果要连续读取每一行并连接,则应重现初始字符串。

我几乎让它工作,但由于某种原因,我丢失了初始字符串(bin)的第一个子字符串(partitions [0] - length 8 * blockSize):

int main (void){
    char* bin = "00011101010000100001111101001101000010110000111100000010000111110100111100010011010011100011110000011010";
    int blockSize = 2; // block size in bytes
    int numBlocks = strlen(bin)/(8*blockSize); // number of block to analyze
    char** partitions = (char**)malloc((numBlocks+1)*sizeof(char)); // break text into block
    for(int i = 0; i<numBlocks;++i){
        partitions[i] = (char*)malloc((8*blockSize+1)*sizeof(char));
        memcpy(partitions[i],&bin[8*i*blockSize],8*blockSize);
        partitions[i][8*blockSize] = '\0';
        printf("Printing partitions[%d]: %s\n", i, partitions[i]);
    }
    for(int j=0; j<numBlocks;++j)
        printf("Printing partitions[%d]: %s\n", j,partitions[j]);
    return 0;
}

输出如下:

Printing partitions[0]: 0001110101000010
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100
Printing partitions[0]: Hj
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100

第一个for循环中的分区构造成功。在读出构造之后,分区[0]处的字符串包含垃圾值。任何人都可以提供一些见解吗?

2 个答案:

答案 0 :(得分:0)

他们的代码存在一些问题。

  • 您正在错误地分配**partitions

    而不是:

    char** partitions = (char**)malloc((numBlocks+1)*sizeof(char)); /* dont need +1, as numblocks is enough space. */
    

    您需要为char*指针分配空间,而不是char个字符。

    相反,这需要:

    char** partitions = malloc((numBlocks+1)*sizeof(char*));
    
  • 另请阅读Why not to cast result of malloc(),因为C中不需要它。

  • 每次都需要检查
  • malloc(),因为它可能会在失败时返回NULL

  • 完成分配的空间后,malloc()先前请求的free()内存总是好的。在程序中的某个时刻执行此操作非常重要。

以下是一些显示此内容的代码:

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

#define BLOCKSIZE 2
#define BLOCK_MULTIPLIER 8

int main(void) {
    const char *bin = "00011101010000100001111101001101000010110000111100000010000111110100111100010011010011100011110000011010";
    const size_t blocksize = BLOCKSIZE;
    const size_t multiplier = BLOCK_MULTIPLIER;
    const size_t numblocks = strlen(bin)/(multiplier * blocksize);
    const size_t numbytes = multiplier * blocksize;

    char **partitions = malloc(numblocks * sizeof(*partitions));
    if (partitions == NULL) {
        printf("Cannot allocate %zu spaces\n", numblocks);
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < numblocks; i++) {
        partitions[i] = malloc(numbytes+1);
        if (partitions[i] == NULL) {
            printf("Cannot allocate %zu bytes for pointer\n", numbytes+1);
            exit(EXIT_FAILURE);
        }
        memcpy(partitions[i], &bin[numbytes * i], numbytes);
        partitions[i][numbytes] = '\0';
        printf("Printing partitions[%zu]: %s\n", i, partitions[i]);
    }

    printf("\n");
    for(size_t j = 0; j < numblocks; j++) {
        printf("Printing partitions[%zu]: %s\n", j,partitions[j]);
        free(partitions[j]);
        partitions[j] = NULL;
    }

    free(partitions);
    partitions = NULL;

    return 0;
}

输出非垃圾值:

Printing partitions[0]: 0001110101000010
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100

Printing partitions[0]: 0001110101000010
Printing partitions[1]: 0001111101001101
Printing partitions[2]: 0000101100001111
Printing partitions[3]: 0000001000011111
Printing partitions[4]: 0100111100010011
Printing partitions[5]: 0100111000111100

答案 1 :(得分:0)

int numBlocks = strlen(bin)/(8*blockSize); // number of block to analyze
char** partitions = (char**)malloc((numBlocks+1)*sizeof(char)); // break text into block
for(int i = 0; i<numBlocks;++i){
    partitions[i] = (char*)malloc((8*blockSize+1)*sizeof(char));
    memcpy(partitions[i],&bin[8*i*blockSize],8*blockSize);
    partitions[i][8*blockSize] = '\0';
    printf("Printing partitions[%d]: %s\n", i, partitions[i]);
}

这一切对我来说都很可疑;它对于任务而言过于复杂,使其成为错误的主要嫌疑人。

  1. 由于this question的答案中解释的原因,void *返回的malloc指针以及其他函数不应该进行投标。
  2. 无需乘以1(sizeof (char) 始终 1在C中)。事实上,在您第一次致电malloc时,您应该乘以sizeof (char *)(或者更好,sizeof *partitions,如下例所示),因为它的大小是partitions指向的元素类型。
  3. malloc可能会返回NULL,当您尝试分配到其指向的位置时,会导致未定义的行为。
  4. NULLmalloccalloc返回时,其他任何内容(即不是realloc}的所有内容都需要free d不再使用,或者valgrind这样的工具(泄漏检测程序,对于习惯性地忘记free分配对象并因此导致内存泄漏的人有用)将报告误报并丢失部分内容有用性。
  5. numBlocksi或其他任何用于计算数组元素的内容都应声明为size_t以遵循标准约定(例如,检查{{ 3}},概要部分,了解如何声明strlen,注意返回值的类型是size_t)。由溢出引起的负值显然会导致程序行为异常。
  6. 我认为你还没有想到超过最后一组8个字符的任何超出部分......这不应该很难合并。
  7. 我建议使用单个分配,例如:

    #include <stddef.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define BLOCK_SIZE 8
    
    int main(void) {
        char const *bin = "00011101010000100001111101001101000010110000111100000010000111110100111100010011010011100011110000011010";
        size_t bin_length = strlen(bin),
               block_count = (bin_length / BLOCK_SIZE)
                           + (bin_length % BLOCK_SIZE > 0); // excess as per point 6 above
        char (*block)[BLOCK_SIZE + 1] = malloc(block_count * sizeof *block);
        if (!block) { exit(EXIT_FAILURE); }
        for (size_t x = 0; x < block_count; x++) {
            snprintf(block[x], BLOCK_SIZE + 1, "%s", bin + x * BLOCK_SIZE);
            printf("Printing partitions[%zu]: %s\n", x, block[x]);
        }
        for (size_t x = 0; x < block_count; x++) {
            printf("Printing partitions[%zu]: %s\n", x, block[x]);
        }
        free(block);
        exit(0);
    }