Создание массива типа, зависящего от времени выполнения

#c

#c

Вопрос:

… это то, что я хочу сделать. У меня есть следующий код:

 ... 
    int len = 0; 
    char c; 
    bool fp = false;

    while (infile.good()) {
            c = infile.get();
            if (c == 'n')   len;
            else if (c == '.') fp = true;
    }  

    if (fp == true){
            float Ai[N];
            float *Ao = new float [len];
    } else {
            int Ai[N];
            int *Ao = new int [len];
    }  

    for (int i=0; i<L;   i){
            for (int j=0; j<N;   j) infile >> Ai[j];
            Ao[i] = findmax(Ai);
    }
...
  

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

Я еще не проверял первый цикл, потому что я не получил его для компиляции:

 warning: unused variable ‘Ai’                                                         
warning: unused variable ‘Ao’
warning: unused variable ‘Ai’
warning: unused variable ‘Ao’
error: ‘Ai’ was not declared in this scope
error: ‘Ao’ was not declared in this scope
  

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

Итак, что не так и как исправить / исправить это с самого начала?

Комментарии:

1. Ai и Ao выходят из области видимости после завершения блока if

2. Лишь немного связано с вашим вопросом: циклы ввода, подобные вашему, часто содержат ошибки. Попробуйте while(infile.get(c)) { ... } читать входные данные по одному символу за раз.

Ответ №1:

Редактировать: как указано выше, ваша ошибка компилятора возникает из-за того, что Ao и Ai объявляются в области, отличной от той, в которой вы пытаетесь их использовать.


Вот где шаблоны действительно пригодятся.

 template<typename T>
T *findMaxes(inFile)
{
    T Ai[N];
    T *Ao = new T[len];

    for (int i = 0; i < L;   i)
    {
        for (int j = 0; j < N;   j)
            infile >> Ai[j];
        Ao[i] = findmax(Ai);
    }

    return Ao;
}




int len = 0; 
char c; 
bool fp = false;

while (infile.good()) {
        c = infile.get();
        if (c == 'n')   len;
        else if (c == '.') fp = true;
}  

if (fp)
{
    float *Ao = findMaxes<float>(inFile);

    // Do stuff with the floating point array
}
else
{
    int *Ao = findMaxes<int>(inFile);

    // Do stuff with the int array
}
  

Ответ №2:

Короткий ответ: вы не можете этого сделать.

C — это статически типизированный язык, что означает, что вы должны определить тип переменной во время компиляции (т. Е. При написании кода). Вы не можете сказать что-то вроде «объявить x тип get_type_from_user() .

С помощью полиморфизма на основе наследования вы можете настроить некоторые настройки, в которых вы обрабатываете все через ссылку на базовый класс, но фактический тип экземпляра определяется во время выполнения. Я полагаю, это почти определенно излишне для вашей установки, но это стандартный способ обработки зависимостей времени выполнения от деталей в C . Однако это не работает для примитивных типов, которые не относятся к типу class .

Вот наивный пример излишнего удаления типов:

 class NumberImpl;

class Number
{
  NumberImpl * pNum;
public:
  explicit Number(int n) : pNum(new NumberInteger(n)) { }
  explicit Number(double d) : pNum(new NumberDouble(d)) { }
  // ..
};

class NumberImpl { /* ... common implementation interface here ... */ }

class NumberInteger : public NumberImpl
{
  int n;
public:
  NumberInteger(int m) : n(m) { }
  // ...
};

// and so forth
  

Этот вид стирания типов используется boost.any shared_ptr постоянно, и у него есть некоторые преимущества. Нужно ли вам это, зависит от вас (но ответ «нет»), и вы, вероятно, можете довольствоваться только одним общим числовым типом. Если вы это сделаете long double , вы обычно получаете 64 бита интегральной точности плюс тонны диапазона масштаба.

Ответ №3:

ваша проблема связана с областью действия .. если вы объявите переменную внутри блока if, она будет существовать только внутри этого блока. К тому времени, когда вы доберетесь до своего последнего цикла for , Ao больше не существует. Вы могли бы попробовать это:

 if (fp == true)
{
    float Ai[N];
    float *Ao = new float [len];
    for (int i=0; i<L;   i)
    {
        for (int j=0; j<N;   j) infile >> Ai[j];
        Ao[i] = findmax(Ai);
    }
}
else 
{
    int Ai[N];
    int *Ao = new int [len];
    for (int i=0; i<L;   i)
    {
        for (int j=0; j<N;   j) infile >> Ai[j];
        Ao[i] = findmax(Ai);
    }
}  
  

Ответ №4:

Вы правы в отношении фундаментальной проблемы здесь. Ваши переменные Ai выходят за пределы области видимости при завершении «}». Таким образом, вам больше не разрешается использовать их впоследствии. Это также объясняет предупреждения, потому что вы никогда не используете эти переменные до их исчезновения.

C имеет статическую типизацию, поэтому вы не можете просто изменить тип переменных во время выполнения.

Вы могли бы изучить объединения, чтобы поместить в переменную либо float, либо int . Подход, более близкий к C , может включать наследование. Но вы могли бы с таким же успехом дублировать код (duck), если у вас есть только эти два случая.

Комментарии:

1. аргумент… по крайней мере, предложите использовать typesafe, гарантирующий строгое исключение boost::variant<…> вместо простых объединений ( здесь )

2. Согласен. Это гораздо более приятное решение проблемы.