Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Проблема с массивами в VC6.0

19K
28 января 2007 года
razer
7 / / 07.11.2006
Добрый день у меня возник вопрос. В программе есть матрица, в ней нужно поменять две строчки местами, для это я первую строчку хочу загнать в темповый массив, первой присвоить значение второй, а во вторую вставить элементы темпового массива. Проблема заключается в том, что массив темп должен быть динамический и когда я пишу строчку вида
for (num=0;num<h;num++)
{
b[num]=Vict(a,num);
}
где функция Vict возвращает значения массива, компилятор ругается error C2440: '=' : cannot convert from 'int' to 'int *' . Работаю в VS6.0. Помогите как избежать этой ошибки.
63
28 января 2007 года
Zorkus
2.6K / / 04.11.2006
Цитата: razer
Добрый день у меня возник вопрос. В программе есть матрица, в ней нужно поменять две строчки местами, для это я первую строчку хочу загнать в темповый массив, первой присвоить значение второй, а во вторую вставить элементы темпового массива. Проблема заключается в том, что массив темп должен быть динамический и когда я пишу строчку вида
for (num=0;num<h;num++)
{
b[num]=Vict(a,num);
}
где функция Vict возвращает значения массива, компилятор ругается error C2440: '=' : cannot convert from 'int' to 'int *' . Работаю в VS6.0. Помогите как избежать этой ошибки.


1) Что такое h, a, b - укажи.
2) Если ты пишешь с динам. распределением памяти - лучше для представления матрицы использовать вектор векторов. И тогда многие функции обработки этой матрицы не нужно будет писать.
3) Ну собственно, если ты меняешь местами элементы двух линейных массивов, как я понял, то не проще ли написать так

 
Код:
#include <algorithm>
..............................
Type FirstArray[10];
Type SecondArray[10];
for(int i = 0; i < 10; ++i) swap(FirstArray , SecondArray);

;)?
505
28 января 2007 года
vAC
343 / / 28.02.2006
Цитата: razer
Добрый день у меня возник вопрос. В программе есть матрица, в ней нужно поменять две строчки местами, для это я первую строчку хочу загнать в темповый массив, первой присвоить значение второй, а во вторую вставить элементы темпового массива. Проблема заключается в том, что массив темп должен быть динамический и когда я пишу строчку вида
for (num=0;num<h;num++)
{
b[num]=Vict(a,num);
}
где функция Vict возвращает значения массива, компилятор ругается error C2440: '=' : cannot convert from 'int' to 'int *' . Работаю в VS6.0. Помогите как избежать этой ошибки.



По-видимому, у тебя b - это 2D-массив, int b[..][..] и когда пишешь b[num], то он представляет собой указатель на строку/столбец. Если a-номер строки/столбца, то наверно надо написать так: b[num][a] = Vict(a,num) или b[a][num] = Vict(a,num) в зависимости от представления матрицы

320
29 января 2007 года
m_Valery
1.0K / / 08.01.2007
Делал бы ты как Zorkus советовал.Вектор векторов .
имхо - так проще , ни указателей, память не забудешь освободить
и т.д.Вот примерчик в Visual Studio2003, а в 6 - й заголовочные
файлы #include "iostream.h" и т.д.Проверял - работает.Правда не знаю
подойдет ли для студенческих задач .:)
Код:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include "windows.h"
#include <ctime>
#include <iomanip>
#include <cassert>

using namespace std;

inline char *rus(char *s)
{
  char *t = new char[strlen(s) + 1];
  CharToOem(s,t);
  return t;
}
inline void print(vector< vector<int> > mass,int n);

int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0));
    cout<<rus("введите размерность матрицы")<<endl;
            int n,row1,row2;// размер,номера строк
    cin>>n;
    //вектор векторов
    vector< vector<int> > mass(n);
    // заполняем случ.числами
    for(int j = 0;j<n;++j){
      for(int i = 0;i<n;++i)
                  mass.push_back(rand()%10);
    }
            print(mass,n);
    cout<<rus("введите номера строк")<<endl;
    cin>>row1;
    cin>>row2;
    // проверяем правильность ввода
    assert(row1>=0&&row1<n&&row2>=0&&row2<n);
    cout<<endl;
    // меняем местами
    mass[row1].swap(mass[row2]);
    print(mass,n);
    return 0;
}
inline void print(vector< vector<int> > mass,int n)
{
             typedef vector<int> vi;
    typedef vector<vi> vvi;
    typedef vi::const_iterator vit;
    typedef vvi::const_iterator vvit;
             cout<<rus("\tисходная матрица")<<"\n\n";
    for(vvit it=mass.begin();it!=mass.end();++it)
    {
       for(vit i=it->begin();i!=it->end();++i)
       {
          cout <<setw(5)<< *i;
        }
          cout << "\n\n";
    }
}
3
29 января 2007 года
Green
4.8K / / 20.01.2000
Цитата: m_Valery
а в 6 - й заголовочные
файлы #include "iostream.h" и т.д.


Дезинформация. В любой <iostream> и т.д.

Цитата: m_Valery

 
Код:
inline char *rus(char *s)
{
  char *t = new char[strlen(s) + 1];
  CharToOem(s,t);
  return t;
}


Memory leak!

Цитата: m_Valery

 
Код:
//вектор векторов
    vector< vector<int> > mass(n);
    // заполняем случ.числами
    for(int j = 0;j<n;++j){
      for(int i = 0;i<n;++i)
                  mass.push_back(rand()%10);
    }


Элегантнее и производительнее будет так:

 
Код:
vector< vector<int> > mass(n, vector<int>(n));
    for(int i = 0;i<n;++i){
      for(int j = 0;j<n;++j)
                  mass[j] = rand()%10;
    }


Цитата: m_Valery

 
Код:
// проверяем правильность ввода
    assert(row1>=0&&row1<n&&row2>=0&&row2<n);


Если сделать n, row1 и row2 не int, а unsigned int, проверок будет меньше.
Кроме того, ты отдаешь себе отчет, что проверка будет выполняться только в режиме отладки?

Цитата: m_Valery

Код:
inline void print(vector< vector<int> > mass,int n)
{
             typedef vector<int> vi;
    typedef vector<vi> vvi;
    typedef vi::const_iterator vit;
    typedef vvi::const_iterator vvit;
             cout<<rus("\tисходная матрица")<<"\n\n";
    for(vvit it=mass.begin();it!=mass.end();++it)
    {
       for(vit i=it->begin();i!=it->end();++i)
       {
          cout <<setw(5)<< *i;
        }
          cout << "\n\n";
    }
}


typedef здесь загромождают код.
Зачем передается n ?
Зачем итератор, если индекс для массива нагляднее и производительнее?

Я бы оформил это не в виде функции, а в виде operator <<

Зачем пишешь везде inline?

63
29 января 2007 года
Zorkus
2.6K / / 04.11.2006
Насчет inline -
Цитата:
Do inline functions improve performance?
Yes and no. Sometimes. Maybe.

There are no simple answers. inline functions might make the code faster, they might make it slower. They might make the executable larger, they might make it smaller. They might cause thrashing, they might prevent thrashing. And they might be, and often are, totally irrelevant to speed.

inline functions might make it faster: As shown above, procedural integration might remove a bunch of unnecessary instructions, which might make things run faster.

inline functions might make it slower: Too much inlining might cause code bloat, which might cause "thrashing" on demand-paged virtual-memory systems. In other words, if the executable size is too big, the system might spend most of its time going out to disk to fetch the next chunk of code.

inline functions might make it larger: This is the notion of code bloat, as described above. For example, if a system has 100 inline functions each of which expands to 100 bytes of executable code and is called in 100 places, that's an increase of 1MB. Is that 1MB going to cause problems? Who knows, but it is possible that that last 1MB could cause the system to "thrash," and that could slow things down.

inline functions might make it smaller: The compiler often generates more code to push/pop registers/parameters than it would by inline-expanding the function's body. This happens with very small functions, and it also happens with large functions when the optimizer is able to remove a lot of redundant code through procedural integration &#8212; that is, when the optimizer is able to make the large function small.

inline functions might cause thrashing: Inlining might increase the size of the binary executable, and that might cause thrashing.

inline functions might prevent thrashing: The working set size (number of pages that need to be in memory at once) might go down even if the executable size goes up. When f() calls g(), the code is often on two distinct pages; when the compiler procedurally integrates the code of g() into f(), the code is often on the same page.

inline functions might increase the number of cache misses: Inlining might cause an inner loop to span across multiple lines of the memory cache, and that might cause thrashing of the memory-cache.

inline functions might decrease the number of cache misses: Inlining usually improves locality of reference within the binary code, which might decrease the number of cache lines needed to store the code of an inner loop. This ultimately could cause a CPU-bound application to run faster.

inline functions might be irrelevant to speed: Most systems are not CPU-bound. Most systems are I/O-bound, database-bound or network-bound, meaning the bottleneck in the system's overall performance is the file system, the database or the network. Unless your "CPU meter" is pegged at 100%, inline functions probably won't make your system faster. (Even in CPU-bound systems, inline will help only when used within the bottleneck itself, and the bottleneck is typically in only a small percentage of the code.)

There are no simple answers: You have to play with it to see what is best. [color=red]Do not settle for simplistic answers like, "Never use inline functions" or "Always use inline functions" or "Use inline functions if and only if the function is less than N lines of code."[/color] These one-size-fits-all rules may be easy to write down, but they will produce sub-optimal results.

320
29 января 2007 года
m_Valery
1.0K / / 08.01.2007
2Creen : отличные советы!код действительно упрощается.
С memory ты меня поймал - называется я предостерег автора,
чтоб память не забывал освобождать и ... сам забыл.Да после
return t;надо добавить delete t;
По поводу assert - спорить не буду, наверно я иногда автоматом
втавляю( так учили, или Липпмана перечитал,он почти везде так
проверяет , ну и я ...)А что ты предлагаешь ? не давать
возможности вводить неправильное число или исключение ?
По поводу оператора << : поясни чем он будет лучше,inline ф-ии,я
вот ее упростил,по твоему совету,имхо - просто получается.
Если,как ты говоришь,в 6-й студии(я давно не делал в ней ) можно
писать <iostream> - то так и надо.И еще - я согласен с тобой
в том,что код должен быть,именно,элегантным.
Вот код с учетом твоих замечаний(кроме assert и <<) :
Код:
#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include <ctime>
#include <iomanip>
#include <vector>
#include <cassert>

using namespace std;

inline char *rus(char *s)
{
 char *t = new char[strlen(s) + 1];
 CharToOem(s,t);
 return t;
 delete t;
}
inline void print(vector< vector<int> > mass)
{
    for(int i = 0;i<mass.size();++i){
        for(int j = 0;j<mass.size();++j)
               cout<<setw(5)<<mass[j];
      cout<<"\n\n";
    }
}
int _tmain(int argc, _TCHAR* argv[])
{
    srand(time(0));
    cout<<rus("введите размерность матрицы")<<endl;
    unsigned int n,row1,row2;// размер,номера строк
    cin>>n;
    //вектор векторов
    // заполняем случ.числами
    vector< vector<int> > mass(n, vector<int>(n));
    for(int i = 0;i<n;++i){
      for(int j = 0;j<n;++j)
                  mass[j] = rand()%10;
    }
    print(mass);
    cout<<rus("введите номера строк")<<endl;
    cin>>row1;
    cin>>row2;
    // проверяем правильность ввода
    assert(row1>=0&&row1<n&&row2>=0&&row2<n);
    cout<<endl;
    // меняем местами
    mass[row1].swap(mass[row2]);
    print(mass);
    return 0;
}

Вот вижу Zorkusоб inline написал,сейчас прочту.Т.е. Вы оба хотите
сказать что в данном случае << более оправдан и эффективен ?
391
29 января 2007 года
Archie
562 / / 03.02.2005
Это забавно, честное слово :)
 
Код:
inline char *rus(char *s)
{
   char *t = new char[strlen(s) + 1];
   CharToOem(s,t);
   return t;
   delete t;
}
63
29 января 2007 года
Zorkus
2.6K / / 04.11.2006
Цитата: m_Valery

А что ты предлагаешь ? не давать возможности вводить неправильное число или исключение ?


Что ты имеешь в виду, под "не давать возможности"? Не дать ввести пользователю значение - это можно в GUI-приложении (поставив нужный валидатор на виджет ввода, например:)). А тут можно лишь не дать функции запуститься с невалидными данными.

Цитата: m_Valery

По поводу оператора << : поясни чем он будет лучше,inline ф-ии,я
вот ее упростил,по твоему совету,имхо - просто получается.
Вот вижу Zorkusоб inline написал,сейчас прочту.Т.е. Вы оба хотите
сказать что в данном случае << более оправдан и эффективен ?


Тут нету связи, между использованием перегруженного оператора для вывода, и тем, inline- функция нужна, или не inline. Я кинул сюда кусок про них, чтобы прояснить себе, что такое inline, если кто-нибудь захочет, а не как рекомендацию их использовать/не использовать (подчеркну только тут, что они никак не влияют на архитектуру класса, как оператор, например, а только дают возможность экспериментировать с производительностью).
В данном случае оператор станет для класса, как бы сказать, логичным дополнением до какой-то модели, еще одним приближением к ней. Поэтому тут, может, стоит предпочесть его. По скорости работы (если ты это понимаешь под эффективностью) использование оперетатора не будет иметь преимуществ перед обычной функцией вывода.

320
29 января 2007 года
m_Valery
1.0K / / 08.01.2007
2Archie : что значит забавно ? У тебя есть способ по-лучше - предложи... Обьяснись.Если не нравится - напиши свой вариант и выложи,чтоб все могли пользоваться.
А так , извини не понял юмора . Или это ты - " про вообще..." ?
Вот можно так, какая разница ?

 
Код:
void RussianMessage(char *str){
   char message[100];
   CharToOem(str,message);
   cout<<message;
}

2Zorkus : не использовать inline, до тех пор пока не доказана необходимость.Интересный вопрос,использовать/не ипользовать, еще у Саттера об этом есть( рекомендует не использовать без крайней
необходимости, но как то не очень убедительно ).Не давать возможность вводить неправильные значения - я имел ввиду.
 
Код:
int n;
// вводим только положителные
do{
 cin>>n;
}while(n<0);

имхо большего конкретная задача и не требует, понятно что пользователь гипотетически может ввести что угодно.Но так мы отвлекаемся от задачи ( упрощаем код и усложняем проверку данных? ). Это уже другая история . А чем assert тут плох ?
63
29 января 2007 года
Zorkus
2.6K / / 04.11.2006
Цитата: m_Valery

 
Код:
void RussianMessage(char *str){
   char message[100];
   CharToOem(str,message);
   cout<<message;
}


Вот зачем тут везде лепить Oem? Человеку, как я понимаю, нужен был алгоритм, а не способ перевода кодировок. То, что ты знаешь способы их перевода - это хорошо, но в данной задаче это только загромождает логику, может, именно поэтому Арчи и не понравился предложенный код:)

Цитата: m_Valery

2Zorkus : не использовать inline, до тех пор пока не доказана необходимость.Интересный вопрос,использовать/не ипользовать, еще у Саттера об этом есть( рекомендует не использовать без крайней
необходимости, но как то не очень убедительно ).


Я бы сказал не так. Просто надо экспериментировать перед использованием, если возможность такая есть.

Цитата: m_Valery

Не давать возможность вводить неправильные значения - я имел ввиду.
 
Код:
int n;
// вводим только положителные
do{
 cin>>n;
}while(n<0);


Не давать вводить - это именно валидатор, тут так не получится. Тут все, что можно - это не дать использовать их.

Цитата: m_Valery

имхо большего конкретная задача и не требует, понятно что пользователь гипотетически может ввести что угодно.Но так мы отвлекаемся от задачи ( упрощаем код и усложняем проверку данных? ). Это уже другая история . А чем assert тут плох ?


Ты сам же сказал, что не нужно злоупотреблять проверками. Зачем тут он нужен?:)

3
29 января 2007 года
Green
4.8K / / 20.01.2000
Цитата: m_Valery
2Archie : что значит забавно ? У тебя есть способ по-лучше - предложи... Обьяснись.Если не нравится - напиши свой вариант и выложи,чтоб все могли пользоваться.
А так , извини не понял юмора . Или это ты - " про вообще..." ?
Вот можно так, какая разница ?


Отвечу за Archie.
Код

 
Код:
inline char *rus(char *s)
{
   char *t = new char[strlen(s) + 1];
   CharToOem(s,t);
   return t;
   delete t;
}

в корне неверный. Инстукции после return выполняться не будут, т.о. от memory leak это не избавляет.
Возвращать указатель на объект созданный внутри этой функции - плохая практика (за исключением "фабрик", - функций, специально для этого предназначенных).

Вариантов решения может быть несколько, в т.ч. и тот что ты предложил в своем крайнем посте. Но я солидарен здесь с Zorkus. Зачем эти дополнительные run-time преобразования, если они могут быть выполнены на этапе компиляции, да и в данной задаче они не являются сутью.

По поводу оператора <<.
Он не прибавляет производительности и т.п., но выглядит элегантнее.
Согласись, что запись
 
Код:
cout << mass;

выглядит симпатичнее и читабельнее, чем
 
Код:
print(mass,n);


По поводу assert.
Он плох тем, что проверка осуществляется лишь в режиме отладки, а как результат проверки - exeption.
Т.о. ты проверяешь, как разработчик, сам себя. А никто не сомневается, что ты умный разработчик и вводишь правильные данные.
А проверять надо данные которые вводит сторонний пользователь и выдавать ему внятный ответ, что он делает неверно.
320
29 января 2007 года
m_Valery
1.0K / / 08.01.2007
Я не понимаю неконструктивных постов.Заметил ошибку - скажи.Хорошо
что за него Green ответил,но это GreenЧто имел ввиду сам Archie еще вопрос?Сейчас то уже понятно - теперь и мне забавно.
2Green : ты вмешался и все( ! ) прояснил. Эту ф-ию можно вообще убрать,
она к данной задаче отношения не имеет( или взять 2 вариант ).Я о ней как то и не думал,поэтому 2-й вариант и написал. Спасибо что заметил.
с assert тоже понял - да ты прав.Но а что делать то?
320
30 января 2007 года
m_Valery
1.0K / / 08.01.2007
2Green : В последнем варианте просто print(mass);
Да, с << выглядит элегантней, ты это имел ввиду ?
Код:
typedef vector< vector<int> > T;
ostream &operator<<(ostream &output,const T &mass)
{
     for(int i = 0;i<mass.size();++i){
          for(int j = 0;j<mass.size();++j)
               output<<setw(5)<<mass[j];
      output<<"\n\n";
    }
     return output;
}
// используется потом в main
   cout << mass;
391
30 января 2007 года
Archie
562 / / 03.02.2005
2m_Valery
Не обижайся. Я хотел, что бы ты сам нашел у себя ошибку ;) И не особо близко воспринимай критику, ведь главное, чтобы твой код корректно работал. А каким образом осуществлять ввод/вывод - это уже эстетика. Я вот, например, printf()-ом часто пользуюсь по привычке :)
320
30 января 2007 года
m_Valery
1.0K / / 08.01.2007
2Archie : я не обижаюсь. Проехали:) :) А эстетика и элегантность кода все таки тоже нужны:)
3
30 января 2007 года
Green
4.8K / / 20.01.2000
Цитата: m_Valery

Да, с << выглядит элегантней, ты это имел ввиду ?


Да, именно

320
30 января 2007 года
m_Valery
1.0K / / 08.01.2007
2Green : Спасибо тебе . Все ж дай совет-как - бы ты поступил
в данной задаче с возможностью неправильного ввода данных.
Исключения ?
3
30 января 2007 года
Green
4.8K / / 20.01.2000
Ну например так:
 
Код:
unsigned int row1, row2;
do {
    cout << "введите номера строк (значения от 0 до " << n << ")" << endl;
    cin >> row1 >> row2;
} while(row1>n || row2 >n);

Или, чтобы дать понять пользователю, что именно он делает неправильно, так:
 
Код:
unsigned int row1, row2;
cout << "введите номера строк (значения от 0 до " << n << ")" << endl;
while(row1 > n || row2 > n) {
    cout << "Неверный ввод. Значения должны быть в диапазоне от 0 до " << n << ")" << endl;
    cout << "Повторите ввод номеров строк" << endl;
    cin >> row1 >> row2;
}
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог