C ++无法将类型为“ char”的值分配给类型为“ char *”的实体

时间:2018-11-12 22:20:36

标签: c++ multidimensional-array char

当我尝试初始化二维数组时,标题出现错误。

//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char** B;

InitializeTable(&B, m, n);

//function below
InitializeTable(char***B, int m, int n)
{
for (int i = 0; i < m; i++)
{
    for (int j = 0; j < n; i++)
    {
        B[i][j] = ' '; //getting the error on the equals sign
    }
}

我认为我很想念一些简单的事情。谢谢!

4 个答案:

答案 0 :(得分:1)

这样想:每套[]都会删除一个*。一个简单的例子:char *string = "fred"; string[0]删除了一个[],因此您得到了数据(f)

您有***BB[i][j],所以还有一个*要去...

您尚未初始化任何内存的事实也是一个问题...

您还应该提供一个Date.prototype.toLocaleString

答案 1 :(得分:1)

您的 “ Doahh ....” 时刻是:

for (int j = 0; j < n; i++)

您为什么在i++循环中使用j

除了拼写错误,您通常只希望将mn传递给InitializeTable,将B声明为InitializeTable的本地对象,分配{{1 }}指针,然后是m个字符,并将每个char分配的起始地址分配给连续指针,然后返回n并在B中返回返回值。 [1] 这样可以防止将 {em> main()地址作为参数传递,从而成为三星级程序员(不是赞扬)。就是说,练习中有教育目的。

B中声明char **B;时,main()是指向char的指针的统一指针。。它有自己的地址(指针B),但没有指向任何地方(实际上,B持有的地址是不确定的,可能与当时B的地址一样)除了分配已正确初始化的另一个B指针的地址外,您目前无法将B用于其他目的。

例如,当您将{em> char **地址传递给B时,例如

InitializeTable

InitializeTable (&B, m, n); 接收地址,您必须分配B指针,并为指针分配起始地址作为{em> m持有的值(而不是3星指针地址)。为此,您必须在B中取消引用B。 (就像您声明InitializeTable然后用int *a, b = 5;使a指向b一样,要更改a = &b所指向的值,您将取消引用并赋值,例如b)示例:

*b = 10;

通过使用void InitializeTable (char ***B, int m, int n) { *B = new char*[m]; 运算符,您为new指针(m)分配了存储,并为char*中的指针B分配了起始地址。 ,{{1}中的main()

现在,您需要为每个指针分配*B个字符,并为每个指针分配每个块的开始地址。但是,由于我们是三星级的程序员,并且要处理一个更高级别的间接寻址,而不是分配给InitializeTable,所以我们必须首先取消引用n-但是,C ++ Operator Precedence 导致B[i]的绑定比B解除引用运算符的绑定更紧密(优先级更高),因此必须首先将[]括在括号中,例如'*'和:

*B

现在,您可以将空格分配为字符,以初始化(*B)[i]中的字符值,例如

     for (int i = 0; i < m; i++) {
        (*B)[i] = new char[n];

注意:循环定义中的所有(*B)[i]

仅此而已。总而言之,您可以这样做:

        for (int j = 0; j < n; j++)
            (*B)[i][j] = ' ';

(别忘了释放保存字符的内存以及分配的指针)

使用/输出示例

j

内存使用/错误检查

在您编写的任何动态分配内存的代码中,对于任何分配的内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要它时可以释放

当务之急是使用一个内存错误检查程序来确保您不会尝试访问内存或在已分配的块的边界之外/之外进行写入,不要试图以未初始化的值读取或基于条件跳转,最后,以确认您释放了已分配的所有内存。

对于Linux,#include <iostream> #include <string> void InitializeTable (char ***B, int m, int n) { *B = new char*[m]; for (int i = 0; i < m; i++) { (*B)[i] = new char[n]; for (int j = 0; j < n; j++) (*B)[i][j] = ' '; } } int main (void) { std::string strX = "cats", strY = "dogs"; //strX and strY are strings int m = strX.length(); int n = strY.length(); //declare two dynamic 2-Dimensional array of variable length B is m X n char **B; InitializeTable (&B, m, n); for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) std::cout << " '" << B[i][j] << "'"; std::cout << '\n'; delete[] B[i]; /* free each block of characters */ } delete[] B; /* free pointers */ } 是正常选择。每个平台都有类似的内存检查器。它们都很容易使用,只需通过它运行程序即可。

$ ./bin/threestarc++      '''''''      '''''''      '''''''      '''''''

$ ./bin/threestarc++
 ' ' ' ' ' ' ' '
 ' ' ' ' ' ' ' '
 ' ' ' ' ' ' ' '
 ' ' ' ' ' ' ' '

始终确认已释放已分配的所有内存,并且没有内存错误。

脚注:

1。实际上,您可能想声明一个向量valgrind的向量(例如$ valgrind ./bin/threestarc++ ==784== Memcheck, a memory error detector ==784== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al. ==784== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info ==784== Command: ./bin/threestarc++ ==784== ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ' ==784== ==784== HEAP SUMMARY: ==784== in use at exit: 0 bytes in 0 blocks ==784== total heap usage: 8 allocs, 8 frees, 72,810 bytes allocated ==784== ==784== All heap blocks were freed -- no leaks are possible ==784== ==784== For counts of detected and suppressed errors, rerun with: -v ==784== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) 中的<char>并将引用传递给std::vector<std::vector<char>>进行初始化,让C ++为您处理内存管理。

答案 2 :(得分:0)

当传递多维数组时,我认为将它们视为引用会更容易。因此,在InitializeTable()中,您可以声明B为对char**的引用,即。 char**&

//strX and strY are strings
int m = strX.length();
int n = strY.length();

//declare two dynamic 2-Dimensional array of variable length B is m X n
char** B;

InitializeTable(B, m, n);               // Just pass in B, which will be a reference to char**.

//function below
InitializeTable(char**&B, int m, int n) // Declare B to be a refernce to char**.
{
    B = new char * [m];                 // Allocate for first dimension, note these are pointers.
    for (int i = 0; i < m; i++)
    {
        B[i] = new char[n];             // Allocate for second dimension, note these are chars.
        for (int j = 0; j < n; j++)     // Note: you had i++ here.
        {
            B[i][j] = ' ';
        }
    }
}

答案 3 :(得分:0)

InitializeTable()内,需要先解除对B的引用,然后才能索引数组。另外,您不会为该阵列分配任何内存。尝试这样的事情:

void InitializeTable(char** *B, int m, int n)
{
    *B = new char*[m];

    for (int i = 0; i < m; i++)
    {
        (*B)[i] = new char[n];

        for (int j = 0; j < n; i++)
        {
            (*B)[i][j] = ' ';
        }
    }
}

...

int m = strX.length();
int n = strY.length();

char** B;
InitializeTable(&B, m, n);

...

for (int i = 0; i < m; ++i)
    delete[] B[i];
delete[] B;

或者,通过引用而不是通过指针传递B

void InitializeTable(char** &B, int m, int n)
{
    B = new char*[m];

    for (int i = 0; i < m; i++)
    {
        B[i] = new char[n];

        for (int j = 0; j < n; i++)
        {
            B[i][j] = ' ';
        }
    }
}

...

int m = strX.length();
int n = strY.length();

char** B;
InitializeTable(B, m, n);

...

for (int i = 0; i < m; ++i)
    delete[] B[i];
delete[] B;

话虽如此,更好的解决方案是根本不使用原始指针。您应该改用std::vector

void InitializeTable(std::vector<std::vector<char>> &B, int m, int n)
{
    B.resize(m);

    for (int i = 0; i < m; i++)
    {
        B[i].resize(n);

        for (int j = 0; j < n; i++)
        {
            B[i][j] = ' ';
        }
    }

    // alternatively:
    // B = std::vector<std::vector<char>>(m, std::vector<char>(n, ' '));
}

...

int m = strX.length();
int n = strY.length();

std::vector<std::vector<char>> B;
InitializeTable(B, m, n);

...