Проблема с массивами в VC6.0
for (num=0;num<h;num++)
{
b[num]=Vict(a,num);
}
где функция Vict возвращает значения массива, компилятор ругается error C2440: '=' : cannot convert from 'int' to 'int *' . Работаю в VS6.0. Помогите как избежать этой ошибки.
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) Ну собственно, если ты меняешь местами элементы двух линейных массивов, как я понял, то не проще ли написать так
..............................
Type FirstArray[10];
Type SecondArray[10];
for(int i = 0; i < 10; ++i) swap(FirstArray , SecondArray);
;)?
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) в зависимости от представления матрицы
имхо - так проще , ни указателей, память не забудешь освободить
и т.д.Вот примерчик в Visual Studio2003, а в 6 - й заголовочные
файлы #include "iostream.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";
}
}
файлы #include "iostream.h" и т.д.
Дезинформация. В любой <iostream> и т.д.
{
char *t = new char[strlen(s) + 1];
CharToOem(s,t);
return t;
}
Memory leak!
vector< vector<int> > mass(n);
// заполняем случ.числами
for(int j = 0;j<n;++j){
for(int i = 0;i<n;++i)
mass.push_back(rand()%10);
}
Элегантнее и производительнее будет так:
for(int i = 0;i<n;++i){
for(int j = 0;j<n;++j)
mass[j] = rand()%10;
}
assert(row1>=0&&row1<n&&row2>=0&&row2<n);
Если сделать n, row1 и row2 не int, а unsigned int, проверок будет меньше.
Кроме того, ты отдаешь себе отчет, что проверка будет выполняться только в режиме отладки?
{
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?
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 — 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.
С memory ты меня поймал - называется я предостерег автора,
чтоб память не забывал освобождать и ... сам забыл.Да после
return t;надо добавить delete t;
По поводу assert - спорить не буду, наверно я иногда автоматом
втавляю( так учили, или Липпмана перечитал,он почти везде так
проверяет , ну и я ...)А что ты предлагаешь ? не давать
возможности вводить неправильное число или исключение ?
По поводу оператора << : поясни чем он будет лучше,inline ф-ии,я
вот ее упростил,по твоему совету,имхо - просто получается.
Если,как ты говоришь,в 6-й студии(я давно не делал в ней ) можно
писать <iostream> - то так и надо.И еще - я согласен с тобой
в том,что код должен быть,именно,элегантным.
Вот код с учетом твоих замечаний(кроме assert и <<) :
#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 написал,сейчас прочту.Т.е. Вы оба хотите
сказать что в данном случае << более оправдан и эффективен ?
{
char *t = new char[strlen(s) + 1];
CharToOem(s,t);
return t;
delete t;
}
А что ты предлагаешь ? не давать возможности вводить неправильное число или исключение ?
Что ты имеешь в виду, под "не давать возможности"? Не дать ввести пользователю значение - это можно в GUI-приложении (поставив нужный валидатор на виджет ввода, например:)). А тут можно лишь не дать функции запуститься с невалидными данными.
По поводу оператора << : поясни чем он будет лучше,inline ф-ии,я
вот ее упростил,по твоему совету,имхо - просто получается.
Вот вижу Zorkusоб inline написал,сейчас прочту.Т.е. Вы оба хотите
сказать что в данном случае << более оправдан и эффективен ?
Тут нету связи, между использованием перегруженного оператора для вывода, и тем, inline- функция нужна, или не inline. Я кинул сюда кусок про них, чтобы прояснить себе, что такое inline, если кто-нибудь захочет, а не как рекомендацию их использовать/не использовать (подчеркну только тут, что они никак не влияют на архитектуру класса, как оператор, например, а только дают возможность экспериментировать с производительностью).
В данном случае оператор станет для класса, как бы сказать, логичным дополнением до какой-то модели, еще одним приближением к ней. Поэтому тут, может, стоит предпочесть его. По скорости работы (если ты это понимаешь под эффективностью) использование оперетатора не будет иметь преимуществ перед обычной функцией вывода.
А так , извини не понял юмора . Или это ты - " про вообще..." ?
Вот можно так, какая разница ?
char message[100];
CharToOem(str,message);
cout<<message;
}
2Zorkus : не использовать inline, до тех пор пока не доказана необходимость.Интересный вопрос,использовать/не ипользовать, еще у Саттера об этом есть( рекомендует не использовать без крайней
необходимости, но как то не очень убедительно ).Не давать возможность вводить неправильные значения - я имел ввиду.
// вводим только положителные
do{
cin>>n;
}while(n<0);
имхо большего конкретная задача и не требует, понятно что пользователь гипотетически может ввести что угодно.Но так мы отвлекаемся от задачи ( упрощаем код и усложняем проверку данных? ). Это уже другая история . А чем assert тут плох ?
char message[100];
CharToOem(str,message);
cout<<message;
}
Вот зачем тут везде лепить Oem? Человеку, как я понимаю, нужен был алгоритм, а не способ перевода кодировок. То, что ты знаешь способы их перевода - это хорошо, но в данной задаче это только загромождает логику, может, именно поэтому Арчи и не понравился предложенный код:)
2Zorkus : не использовать inline, до тех пор пока не доказана необходимость.Интересный вопрос,использовать/не ипользовать, еще у Саттера об этом есть( рекомендует не использовать без крайней
необходимости, но как то не очень убедительно ).
Я бы сказал не так. Просто надо экспериментировать перед использованием, если возможность такая есть.
Не давать возможность вводить неправильные значения - я имел ввиду.
// вводим только положителные
do{
cin>>n;
}while(n<0);
Не давать вводить - это именно валидатор, тут так не получится. Тут все, что можно - это не дать использовать их.
имхо большего конкретная задача и не требует, понятно что пользователь гипотетически может ввести что угодно.Но так мы отвлекаемся от задачи ( упрощаем код и усложняем проверку данных? ). Это уже другая история . А чем assert тут плох ?
Ты сам же сказал, что не нужно злоупотреблять проверками. Зачем тут он нужен?:)
А так , извини не понял юмора . Или это ты - " про вообще..." ?
Вот можно так, какая разница ?
Отвечу за Archie.
Код
{
char *t = new char[strlen(s) + 1];
CharToOem(s,t);
return t;
delete t;
}
в корне неверный. Инстукции после return выполняться не будут, т.о. от memory leak это не избавляет.
Возвращать указатель на объект созданный внутри этой функции - плохая практика (за исключением "фабрик", - функций, специально для этого предназначенных).
Вариантов решения может быть несколько, в т.ч. и тот что ты предложил в своем крайнем посте. Но я солидарен здесь с Zorkus. Зачем эти дополнительные run-time преобразования, если они могут быть выполнены на этапе компиляции, да и в данной задаче они не являются сутью.
По поводу оператора <<.
Он не прибавляет производительности и т.п., но выглядит элегантнее.
Согласись, что запись
выглядит симпатичнее и читабельнее, чем
По поводу assert.
Он плох тем, что проверка осуществляется лишь в режиме отладки, а как результат проверки - exeption.
Т.о. ты проверяешь, как разработчик, сам себя. А никто не сомневается, что ты умный разработчик и вводишь правильные данные.
А проверять надо данные которые вводит сторонний пользователь и выдавать ему внятный ответ, что он делает неверно.
что за него Green ответил,но это GreenЧто имел ввиду сам Archie еще вопрос?Сейчас то уже понятно - теперь и мне забавно.
2Green : ты вмешался и все( ! ) прояснил. Эту ф-ию можно вообще убрать,
она к данной задаче отношения не имеет( или взять 2 вариант ).Я о ней как то и не думал,поэтому 2-й вариант и написал. Спасибо что заметил.
с assert тоже понял - да ты прав.Но а что делать то?
Да, с << выглядит элегантней, ты это имел ввиду ?
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;
Не обижайся. Я хотел, что бы ты сам нашел у себя ошибку ;) И не особо близко воспринимай критику, ведь главное, чтобы твой код корректно работал. А каким образом осуществлять ввод/вывод - это уже эстетика. Я вот, например, printf()-ом часто пользуюсь по привычке :)
Да, с << выглядит элегантней, ты это имел ввиду ?
Да, именно
в данной задаче с возможностью неправильного ввода данных.
Исключения ?
do {
cout << "введите номера строк (значения от 0 до " << n << ")" << endl;
cin >> row1 >> row2;
} while(row1>n || row2 >n);
Или, чтобы дать понять пользователю, что именно он делает неправильно, так:
cout << "введите номера строк (значения от 0 до " << n << ")" << endl;
while(row1 > n || row2 > n) {
cout << "Неверный ввод. Значения должны быть в диапазоне от 0 до " << n << ")" << endl;
cout << "Повторите ввод номеров строк" << endl;
cin >> row1 >> row2;
}