简体   繁体   English

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

[英]C++ a value of type “char” cannot be assigned to an entity of type “char *”

I'm getting the error from the title when I try to initialize a two dimensional array. 尝试初始化二维数组时,标题出现错误。

//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
    }
}

I think is something very simple I'm missing. 我认为这很简单,我很想念。 Thank you! 谢谢!

Your "Doahh...." moment is: 您的“ Doahh ....”时刻是:

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

Why are you using i++ in a j loop? 为什么在j循环中使用i++

Beyond the typo, you would generally want to pass only m and n to InitializeTable , declare B local to InitializeTable , allocate m pointers and then n chars and assign the beginning address for each allocation of chars to the successive pointer and return B and assign the return back in main() . 除错字之外,您通常只希望将mn传递给InitializeTable ,将B声明为InitializeTable局部InitializeTable ,先分配m指针,然后分配n字符,然后将每个char分配的起始地址分配给连续指针,然后返回B并分配返回main() [1] This prevents passing the address of B as a parameter and thereby becoming a 3-Star Programmer (not a compliment). [1]这样可以防止将B地址作为参数传递,从而避免成为3星编程器 (而不是称赞)。 That said, there is educational purpose in the exercise. 就是说,练习中有教育目的。

When you declare char **B; 当您声明char **B; in main() , B is an unitialized pointer to pointer to char . main()B指向char的指针的统一指针 It has its very own address (the pointer B ), but it points nowhere (actually the address held by B is indeterminate and likely just whatever was at the address of B at the time it was declared. You cannot use B for any other purpose at this point other than assigning the address of another char ** pointer that has been properly initialized. 它有自己的地址(指针B ),但没有指向任何地方(实际上B所持有的地址是不确定的,并且可能是声明时B处的任何地址)。您不能将B用于任何其他目的此时,除了分配已正确初始化的另一个char **指针的地址外。

When you pass the address of B to InitializeTable , eg 当您将B地址传递给InitializeTable ,例如

    InitializeTable (&B, m, n);

and B receives the address, you must allocate m pointers and assign the beginning address for the pointers as the value held by B (not as the 3-star pointer address). 并且B接收到该地址,则必须分配m指针,并将指针的起始地址分配为B 保留 (而不是3星指针地址)。 To do this, you must dereference B in InitializeTable . 为此,必须在InitializeTable取消引用B (just as you would declare int *a, b = 5; and then make a point to b with a = &b , to change the value pointed to by b you would dereference and assing, eg *b = 10; ) Example: (就像将宣布int *a, b = 5;然后使aba = &b ,改变值指向b你会解除引用和assing,例如*b = 10;实施例:

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

By using the new operator, you have allocated storage for m pointers ( char* ) and assigned the beginning address to the pointer B in main() , *B in InitializeTable . 通过使用new运营商,您已分配的存储空间m的指针( char* ),并指定起始地址的指针Bmain() *BInitializeTable

Now you need to allocate n chars for each pointer and assign the beginning address for each block to each pointer. 现在,您需要为每个指针分配n字符,并为每个指针分配每个块的开始地址。 However, since we are 3-star programmers, and have one additional level of indirection to deal with, instead of assigning to B[i] , we must derefence B first -- but, C++ Operator Precedence causes [] to bind tighter (has higher precedence) than the '*' dereference operator, so you must enclose *B in parenthesis first, eg (*B)[i] with: 但是,由于我们是三星级的程序员,并且要处理一个更高级别的间接寻址,而不是分配给B[i] ,所以我们必须首先取消引用B -但是,C ++ 运算符优先级会导致[]绑定得更紧(更高的优先级),比'*'反引用运算符,因此必须附上*B括号第一,例如(*B)[i]与:

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

Now you can assign your spaces as the characters to initialize the character values in (*B)[i] , eg 现在,您可以将空格分配为字符,以初始化(*B)[i]的字符值,例如

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

( note: all j s in the loop definition) 注意:循环定义中的所有j

That's all there is to it. 这里的所有都是它的。 Putting it altogether, you could do: 综上所述,您可以执行以下操作:

#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 */
}

(don't forget to free both the memory holding the characters, as well as the pointers you allocate) (不要忘记释放保存字符的内存以及分配的指针)

Example Use/Output 使用/输出示例

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

Memory Use/Error Check 内存使用/错误检查

In any code you write that dynamically allocates memory, you have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed. 在您编写的任何可以动态分配内存的代码中,对于任何分配的内存块,您都有2个责任 :(1) 始终保留指向该内存块起始地址的指针,因此,(2)在没有内存块时可以将其释放需要更长的时间。

It is imperative that you use a memory error checking program to insure you do not attempt to access memory or write beyond/outside the bounds of your allocated block, attempt to read or base a conditional jump on an uninitialized value, and finally, to confirm that you free all the memory you have allocated. 必须使用一个内存错误检查程序来确保您不尝试访问内存或不要在已分配的块的边界之外/之外进行写入,不要尝试以未初始化的值读取或基于条件跳转,最后确定您可以释放已分配的所有内存。

For Linux valgrind is the normal choice. 对于Linux, valgrind是通常的选择。 There are similar memory checkers for every platform. 每个平台都有类似的内存检查器。 They are all simple to use, just run your program through it. 它们都很容易使用,只需通过它运行程序即可。

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

$ 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)

Always confirm that you have freed all memory you have allocated and that there are no memory errors. 始终确认已释放已分配的所有内存,并且没有内存错误。

footnotes: 脚注:

1. Actually you would want to declare a vector of vector <char> (eg std::vector<std::vector<char>> in main() and pass a reference to InitializeTable for initialization letting C++ handle the memory management for you. 1.实际上,您可能想声明一个向量<char>的向量(例如, main() std::vector<std::vector<char>> main()并传递一个对InitializeTable的引用进行InitializeTable ,从而让C ++为您处理内存管理。

Think of it like this: Each set of [] removes a * . 这样想:每套[]删除一个* Simple case: char *string = "fred"; 简单的情况: char *string = "fred"; string[0] removes a [] so you get the data (f) string[0]删除[]以便获取数据(f)

You have ***B and B[i][j] so you still have one * to go... 您有***BB[i][j]所以您还有一个*要去...

The fact that you have not initialized any memory is also a problem... 您尚未初始化任何内存的事实也是一个问题...

You should also give a SSCCE . 您还应该提供SSCCE

When passing multidimensional arrays, I think it's easier to think of them as references. 当传递多维数组时,我认为将它们视为引用会更容易。 So in InitializeTable() you can just declare B to be a reference to char** , ie. 因此,您可以在InitializeTable()声明B为对char**的引用,即。 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] = ' ';
        }
    }
}

Inside of InitializeTable() , you need to dereference B before you can then index into the array. InitializeTable()内部,您需要先解除对B引用,然后才能索引该数组。 Also, you are not allocating any memory for the array. 另外,您不会为该阵列分配任何内存。 Try something like this: 尝试这样的事情:

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;

Alternatively, pass B by reference instead of by pointer: 或者,通过引用而不是指针传递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;

That being said, a better solution would be to not use raw pointers at all, though. 话虽这么说,更好的解决方案是根本不使用原始指针。 You should use std::vector instead: 您应该改用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);

...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 不能将 const char* 类型的值分配给 char* 类型的实体? - A value of type const char* cannot be assigned to an entity of type char*? 类型“ * const char *”的值不能分配给“ char *”类型的实体 - A value of type “*const char *” cannot be assigned to an entity of type “char *” “const char *”类型的值不能分配给“char”C OOP类型的实体 - a value of type “const char *” cannot be assigned to an entity of type “char” C OOP “const char *”类型的值不能分配给“LPSTR”类型的实体 - Value of type "const char *" cannot be assigned to an entity of type "LPSTR" 需要帮助在 C++ 中将字符串转换为字符 ---- 错误“const char *”类型的值不能用于初始化“char”类型的实体 - Need help converting a string to a char in c++ ---- ERROR A value of type "const char *" cannot be used to initialize an entity of type "char" char *类型的值不能用于初始化“ char”类型的实体 - Value of type char* cannot be used to initialize an entity of type “char” 值类型const char不能用于初始化char *类型的实体 - Value type const char cannot be used to initialize an entity of type char* “const char*”类型的值不能用于初始化“char *”类型的实体 - A value of type "const char*" cannot be used to initialize an entity of type "char *" “ char *”类型的值不能用于初始化“ char”类型的实体 - A value of type “char *” cannot be used to initialize an entity of type “char” char *类型的值不能用于初始化“ char”类型的实体 - Value of type char* cannot be used to initialize an entity of type “char”
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM