C ++ Многомерные массивы, генерирующие ошибки сегментации? - PullRequest
0 голосов
/ 26 июля 2011

Я пишу сценарий, который должен скопировать некоторые имена в многомерный массив, распечатать содержимое массива, а затем освободить память и завершиться.У меня проблема в том, что когда я запускаю скрипт, он печатает только введенную фамилию.Вот что я сделал.Любая помощь будет отличной!Заранее спасибо!

#include <iostream>
#include <string.h>

using namespace std;

void createArray(int n);
void addDetail(char*& name, char*& surname);
void printArray();
void clear();

char ***details;
int used;
int size;

int main()
{
    createArray(3);

    char* tmpName = new char[20];
    char* tmpSurName = new char[120];

    strcpy(tmpName, "nameA");
    strcpy(tmpSurName, "surnameA");
    addDetail(tmpName,tmpSurName);

    strcpy(tmpName, "nameB");
    strcpy(tmpSurName, "surnameB");
    addDetail(tmpName,tmpSurName);

    strcpy(tmpName, "nameC");
    strcpy(tmpSurName, "surnameC");
    addDetail(tmpName,tmpSurName);

    clear();
    return 0;
}

void createArray(int n)
{
    details= new char**[n];
    for(int i=0; i<n; i++)
        details[i] = new char*[2];
    size = n;
    used = 0;
}

void addDetail(char*& name, char*& surname)
{
    if(occupation < size)
    {
        details[used][0] = name;
        details[used][1] = surname;
        used++;
    }else{
        cout << "Array Full " << endl;
    }
}

void printArray()
{
    for(int i=0; i<used; i++)
        cout << details[i][0] << " " << details[i][1] << endl;
}

void clear()
{
    for(int i=0; i<size; i++)
    {
        delete [] details[i];
        details[i] = 0;
    }
    delete [] details;
    details=0;
}

Ответы [ 4 ]

1 голос
/ 26 июля 2011

Вы не выделили память для details[used][0] и details[used][1], поэтому она использует любой случайный адрес, который был в этих местах.

Поскольку это C ++, вы можете вместо этого использовать строку?std::string **details;.Это должно работать с вашим существующим кодом, за исключением того, что это приведет к утечке памяти.

Еще лучше использовать вектор векторов.

Что-то вроде: std::vector<std::vector<std::string> > details;

Тогдафункция createArray может полностью исчезнуть, а addDetail становится проще:

std::vector<string> newName;
newName.push_back(name);
newName.push_back(surname);
details.push_back(newName);
0 голосов
/ 26 июля 2011

Вы продолжаете перезаписывать свои временные буферы вместо создания новых буферов для каждой записи в массиве.В результате выживают только последние данные, записанные в буфер.

Вот примерное руководство по одному способу его исправления, хотя в этом примере могут быть некоторые проблемы - я не пытался скомпилировать или протестировать это.

Эта часть main принадлежит addDetail:

char* tmpName = new char[20];
char* tmpSurName = new char[120];

strcpy(tmpName, "nameA");
strcpy(tmpSurName, "surnameA");

Итак, ваш новый addDetail будет выглядеть примерно так:

void addDetail(char*& name, char*& surname)
{
    if(occupation < size)
    {
        details[used][0] = new char[20];
        details[used][1] = new char[120];
        strcpy(details[used][0], name);
        strcpy(details[used][1], surname);
        used++;
    }else{
        cout << "Array Full " << endl;
    }
}

И будет вызываться из main как:

addDetail("nameA", "surnameA");

Вам нужно будет обновить clear, чтобы правильно очистить выделения, сделанные в addDetail.

0 голосов
/ 26 июля 2011

Похоже, происходит то, что вы не добавляете строку в массив, вы добавляете указатель на имя и фамилию.Каждый экземпляр указывает на эту переменную, поэтому, когда вы спрашиваете массив, что он содержит, он спрашивает имя и фамилию, которая будет содержать только последнее значение.

Также этот массив, вы уверены, что он работает так, как вы?хотите, чтобы это работало?Массивы - это ... конкретные вещи.По сути, вы говорите: «Я хочу 5 из них, они будут такими большими (в зависимости от типа, который вы вводите)», и компьютер тихо отключается: «Хорошо, я выделю место для тех, кто здесь, и вы можете положить их, когда будете готовы.».Когда ваш код помещает эти имена туда, на самом деле нет никакой подготовки к тому, где их хранить.Если вы заполняете это пространство и выходите за пределы, вы идете в плохие места.Так что вам следует сделать, чтобы последний * символ char *** был указателем на символ [120], чтобы вы знали (по крайней мере, для ваших целей), что он никогда не будет заполнен.Сделайте это в вашей функции createArray после того, как вы создали внешние массивы.

0 голосов
/ 26 июля 2011

Это потому, что каждый раз вы эффективно сохраняете указатель tmpName и tmpSurName в массиве details.Затем на следующей итерации вы перезаписываете содержимое памяти, на которое указывают tmpName и tmpSurName, поэтому в конце у вас будет список, содержащий n раз фамилию / фамилию.

Чтобы решить эту проблему, вам необходимо перераспределить tmpName и tmpSurName перед каждым вызовом addDetail.

Кстати, зачем вам нужно использовать (ewww) char***, и можете 'например, STL?

...