如何访问结构

时间:2015-07-30 16:23:48

标签: c++ arrays pointers struct

我试图用这种结构创建一个指针数组:

struct No {
    int decimal;
    char *binary;
    char *octal;
    char *hexadecimal;
};

我有两个函数来构造数组并打印出数组:

void constructArray (No *Number, int size) {
    No **temp = new No *[size];

    for (int i = 0; i < size; i++)
    {
        temp[i] = new No;

        temp[i]->decimal = rand() % 1000;
        temp[i]->binary = "0";
        temp[i]->octal = "0";
        temp[i]->hexadecimal = "0";
    }
}

void printArray (No *Number, int size) {
    cout << "Decimal\t" << "Binary\t\t\t" << "Octal\t\t" << "Hexadecimal" << endl;
    No **temp = new No *[size];

    for (int i = 0; i < size; i++) {
        temp[i] = new No;

        cout << temp[i]->decimal << "\t"
            << temp[i]->binary << "\t\t\t"
            << temp[i]->octal << "\t\t"
            << temp[i]->hexadecimal << endl;
    }
}

然后我在主函数中调用它们:

int main() {
    No n;
    No *nPtr = NULL;

    nPtr = &n;

    int size = (rand() % 9) + 1;

    constructArray(nPtr,size);

    printArray(nPtr,size);
}

我觉得我的printArray函数有问题,因为当我注释掉这个函数然后程序工作但是我不确定数组是否正确生成。那么如何修复此函数以便它可以在创建的结构中打印出元素的值?顺便说一句,我在main函数中的初始化是否正确?感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

实际上并不需要所有这些指针和动态分配。

只需生成如下数字:

std::size_t size = 10;
std::vector<int> vector;
std::generate_n(back_inserter(vector), size, []() { return rand(); });

然后用:

打印出来
for (auto const& i : vector)
    std::cout << i << "\t"
              << std::bitset<CHAR_BIT * sizeof(int)>(i) << "\t\t\t"
              << std::oct << i << "\t\t"
              << std::hex << i << "\n"
              << std::dec;

现场演示

或类似的东西。

答案 1 :(得分:0)

在数组构造中。

而不是尝试通过参数传回结果返回函数的结果。

void constructArray (No *Number, int size) {
                     ^^^^^^^^^^  Looks like you want this to be an out parameter.
                                 But you never use it.

修复:

No** constructArray (int size) {
     // STUFF
     return temp;
}

然后在主要:

No** nPtr = constructArray(size);

在您的打印中,您应该使用传入的参数。

void printArray (No *Number, int size) {
                 ^^^^^^^^^^    Never used.

将其更改为:

 void printArray (No** temp, int size) {

然后删除这些行:

 //    DELETE THIS:   No **temp = new No *[size];

 //    DELETE THIS:    temp[i] = new No;

答案 2 :(得分:0)

constructArray实际上没有做任何相关的事情,留出泄漏的记忆。 printArray相同。
我猜你在很久以前就开始使用c ++编写代码,你编写的代码执行以下操作:

void constructArray (No *Number, int size) {
  // allocates enough memory to store n=size pointers to No then constructs them
  // stores the address of that memory in temp
  No **temp = new No *[size];

  // for each pointer to No *temp, *(temp+1), ..., *(temp+size-1)
  for (int i = 0; i < size; i++)
  { 
    // allocates enough space to store a No, constructs a No, and assigns
    // its address to *(temp+i)
    temp[i] = new No;
    // initializes the values of the newly allocated No
    temp[i]->decimal = rand() % 1000;
    temp[i]->binary = "0";
    temp[i]->octal = "0";
    temp[i]->hexadecimal = "0";
  }
  // discards temp, effectively leaking the memory allocated in this function
}

void printArray (No *Number, int size) {
  // prints a string
  cout << "Decimal\t" << "Binary\t\t\t" << "Octal\t\t" << "Hexadecimal" << endl;
  // allocates enough memory to store n=size pointers to No then constructs them
  // stores the address of that memory in temp
  No **temp = new No *[size];

  // for each pointer to No *temp, *(temp+1), ..., *(temp+size-1)
  for (int i = 0; i < size; i++) {
    // allocates enough space to store a No, constructs a No, and assigns
    // its address to *(temp+i)
    temp[i] = new No;
    // prints the content of the newly allocated No
    cout << temp[i]->decimal << "\t"
        << temp[i]->binary << "\t\t\t"
        << temp[i]->octal << "\t\t"
        << temp[i]->hexadecimal << endl;
  }
  // discards temp, effectively leaking the memory allocated in this function
}

您的代码存在一些奇怪和许多问题:

  • 作为评论中所述的melpomene,您没有使用函数的某些参数(有时,它实际上用于定义未使用的参数,但在这种情况下不是这样)

  • 您忘记返回或删除您在函数中动态分配的内容

  • 您进行了太多动态分配(特别是在printArray中,不需要动态分配)

  • 您将字符串文字分配给char*,您应该将它们存储在const char*中或手动分配内存(字符串文字将存储在数据段中,数据段不应该这是不可变的,这就是为什么标准禁止它的原因)一些编译器会接受警告,但它不是很干净

  • 使用指向No的指针来动态分配No的数组

  • 您还无法在std::cout次调用中拆分字符串,并将No的初始化委托给constructArray而不是No的构造函数

我认为你真正想写的是以下内容:

#include <iostream>
#include <ctime>

using namespace std; // i usually avoid this

struct No {
  // No constructor, each time you "construct" a No instance, this function will
  // be called (the No() : var(value), ... syntax is called a member
  // initializer list, it's specific to constructors)
  No() : 
  decimal(rand() % 1000),
  binary("0"),
  octal("0"),
  hexadecimal("0")
  {}

  int decimal;
  const char *binary;
  const char *octal;
  const char *hexadecimal;
};

void constructArray (No*& arrayDestination, int size) {
  // allocates enough memory for n=size No and constructs them
  // then stores the address of this allocated memory in arrayDestination
  arrayDestination = new No[size];
  // NOTE: arrayDestination is a reference to a pointer to No, which means
  //       that you'll actually modfiy the parameter used by the caller
  // in other words:
  //
  // No* ptr = nullptr;
  // constructArray(ptr, size);
  //
  // will actually modify ptr, another way would be to return the pointer
  // with the return value of constructArray

  // no need to initialize the No allocated here, new[] already called the
  // constructor
}

void printArray (No* array, int size) {
  // no need to split the string here...
  cout << "Decimal\tBinary\t\t\tOctal\t\tHexadecimal" << endl;
  // don't reallocate an array, the array has always been constructed, why would
  // you want another one? (plus an uninitialized one...)
  for (int i = 0; i < size; i++) {
    // actually use the first parameter!
    // NOTE: now, this isn't a reference (No* instead of No*&) because we
    //       don't need to modify this parameter, the parameter is actually
    //       copied when we call the function
    cout << array[i].decimal << "\t"
    << array[i].binary << "\t\t\t"
    << array[i].octal << "\t\t"
    << array[i].hexadecimal << endl;
  }
}

int main() {
  // if you use rand, you should call srand first to initialize the random
  // number generator (also note that rand is deprecated)
  srand(time(nullptr));
  // NOTE: time(nullptr) returns the current timestamp
  //       it's sometimes used as a pseudo-random "seed" to initialize a
  //       generator

  // this will be a pointer to the first element of our "arrray"
  No *array = nullptr;
  // this instruction is valid and will give you an integer between 1 and 9
  int size = (rand() % 9) + 1;
  // now we call the corrected functions
  constructArray(array, size);
  printArray(array, size);
  // you should actually release the array once you're finished using it
  // the clean way would be to implement a "releaseArray" function, 
  // but i'm lazy, so i'll just do it here:
  delete[] array;
  // don't forget main returns an int! 0 is usually the code for "nothing bad happened"
  return 0;
}

更好的是,将动态分配的No数组替换为std::vector<No>,将const char*替换为std::string(如果您希望它们是可变的)。这样你就不再需要一个函数来构建/释放数组了。

编辑:嗯,我花了太多时间发布