Ru-Board.club
← Вернуться в раздел «Прикладное программирование»

» Вопросы по программированию на C/С++

Автор: DoctorLans
Дата сообщения: 09.11.2006 20:58
Qraizer
спасибо за разъяснение!
Автор: DoctorLans
Дата сообщения: 10.11.2006 10:25
Столкнулся с такой проблемой.
Простенький класс (пример из книги).


Код: #include <iostream>
using namespace std;

class test {
private:
    //Конструктор
    test() {
        a = 5;
    }
    int a, b;
public:    
    aShow() {
        cout<<"a: "<<a<<endl;
    }    
};


int main() {
    test::aShow();    
    return 0;
}
Автор: RedLord
Дата сообщения: 10.11.2006 11:44
DoctorLans
warning C4183 связан с тем, что нужно обявить ее как void aShow()

error C2352: 'test::aShow' - все верно. ошибка. с таким синтаксисом идет обращение к статическим мемберам класса. aShow - объявлена не как static.
в приведеном коде обращение должно было быть такое:

test t; // при приватном конструкторе будет здесь ошибка.
t.aShow();

вывод: пример не должен работать.
Автор: SaDFromSpb
Дата сообщения: 10.11.2006 12:38
DoctorLans

Код: char* pch;
char charr[10];
pch = charr;
Автор: DoctorLans
Дата сообщения: 10.11.2006 13:22
RedLord,
SaDFromSpb
спасибо за разъяснения.

Автор: rain87
Дата сообщения: 10.11.2006 16:36
SaDFromSpb
Цитата:

Код: char* pch;
char charr[10];
pch = charr;
Прекрасно компилится gcc
Автор: Jokerjar
Дата сообщения: 11.11.2006 10:20
rain87, вот так:

Код: char* pch;
char charr[10];
StrPCopy(charr,pch);
Автор: rain87
Дата сообщения: 11.11.2006 12:09
Jokerjar
ну а я о чём и говорю. тот код, что я написал работать не будет, т.к. charr - статический указатель (ака массив), и в него присвоить ничего нельзя - он жёстко ассоциируется компилятором с массивом.

т.е. pch указывает на поинтер (2 или 4 байта), и в него как в поинтер можно чего-нить присвоить (в частности адрес charr)

а charr указывает на 10 байт, туда поинтер при всём желании не запомнишь
Автор: Qraizer
Дата сообщения: 11.11.2006 16:37
SaDFromSpb
Цитата:
Безусловно, массив и указатель - две разные сущности (с этим не поспоришь =) ), а вот charr и pch - следует воспринимать как одно и то же после строчки pch = char.
Что значит "воспринимать как одно и то же"? Что их сущности станут одинаковыми?? И почему "после строчки"? Наверное, я отстал от новых стандартов в C++, в которых отменён принцип неизменности типа объекта, а оператор присваивания копирует тип вместе со значением...
Цитата:
Ну вся разница в том, что sizeof(charr)==10, а sizeof(pch)==4.
И всё???
Цитата:
Компилятор работает так, что он преобразует обращение к charr в &charr[0],
Ошибаешься. Компилятор работает по стандарту, а он говорит, что допустимо неявное кастование T[] в T const* и присваивание константых объектов неконстантным, если для них определена семантика присваивания. Поэтому ты и можешь присвоить pch=charr
Цитата:
а при обращении к pch - просто выдает ее содержимое, которое после приравнивания тоже будет содержать &charr[0].
Не давай себя запутать!
Не запутывайся сам, да не запутаешь и других.
Автор: SaDFromSpb
Дата сообщения: 11.11.2006 19:53
Qraizer

Цитата:
Что значит "воспринимать как одно и то же"? Что их сущности станут одинаковыми??
Я не имел ввиду, что их сущности станут одинаковыми, я имел ввиду, что после приравнивания pch к charr, не будет разницы, обращаешся ли ты к элементам массива через pch или через charr.

Цитата:
. Компилятор работает по стандарту, а он говорит, что допустимо неявное кастование T[] в T const* и присваивание константых объектов неконстантным
Это несколько абстрактная фраза и, по-моему, она еще не доказывает, что я ошибаюсь. Расскажи, что конкретно происходит при операции charr[3] = 'a'? Как работает компилятор? Ведь он рассчитывает смещение, равное 3 от адреса первого элемента?

Цитата:
Не запутывайся сам, да не запутаешь и других.
Извини, если задел, но, мне кажется не стоило говорить, что во всех учебниках про массивы пишут ложь. Так или иначе в них доносится мысль, что имя массива можно воспринимать как указатель на его первый элемент (в некоторых, может быть, это делается плохо). И между int и float аналогия совсем не та.
Вообще, я только сейчас заметил, что DoctorLans пытался присвоить массиву значение указателя, а не наоборот . Если бы я заметил это сразу - ничего бы не отвечал.
Автор: ervi
Дата сообщения: 12.11.2006 13:02
DoctorLans

Цитата:
aShow() {
cout<<"a: "<<a<<endl;
}


заменить на
void aShow() {
cout<<"a: "<<a<<endl;
}
а вызывать так:
int main() {
test t;
t.aShow();
return 0;
}
Автор: Qraizer
Дата сообщения: 13.11.2006 21:30
SaDFromSpb
Цитата:
Я не имел ввиду, что их сущности станут одинаковыми, я имел ввиду, что после приравнивания pch к charr, не будет разницы, обращаешся ли ты к элементам массива через pch или через charr.
Я так и подумал, но не факт, что так же подумали и другие. Поэтому и обратил твоё внимание на двусмысленность (если не сказать "ошибочность") фразы. Если получилось резковато - каюсь, не хотел.
Цитата:

Цитата: Компилятор работает по стандарту, а он говорит, что допустимо неявное кастование T[] в T *const и присваивание константых объектов неконстантным...

Это несколько абстрактная фраза и, по-моему, она еще не доказывает, что я ошибаюсь.
Автор: xdude
Дата сообщения: 14.11.2006 09:47
Qraizer
Я прошу прощения, что вмешиваюсь в вашу беседу, но нельзя ли ссылочку на стандарт, да желательно на русском языке чтоб было (хотя, английский тоже приемлем)
Заранее спасибо.

Добавлено:
А то всю жизнь кодирую на помеси C и C++, причем, в принципе, успешно, но все же хотелось бы как-то еще при этом и по стандартам
Автор: Bender_R
Дата сообщения: 14.11.2006 10:55
xdude
с вашего позволения отвечу я:

CPP

здесь лежит ISO+IEC+14882-2003 - стандарт 2003 года (2.3М пдф)

в парент лежит и стандарт по ANSI C

C
Автор: SaDFromSpb
Дата сообщения: 14.11.2006 11:36
Qraizer
Ок. Согласен. Понял, что не достаточно разбираюсь(лся) в теме. Уже давно изучаю паттерны проектирования, и, оказывается, не до конца понимаю такие базовые вещи про преобразования типов =((. Спасибо за развернутый ответ =).
Только у меня вопрос:
Вот здесь:
Цитата:
выполняется операция operator[](char const*, int) (которая эквивалентна *(operator+(char const *, int)))
. Неужели, эта операция вызывается по-честному? То есть, при передаче параметров по значению в функцию, в памяти создается временная переменная-указатель, содержащая значение адреса первого элемента и так же копия int. При многократных обращениях к элементам это слегка накладнее, чем operator[](char const*&, int&)
Автор: Qraizer
Дата сообщения: 14.11.2006 12:31
Нет, конечно. Во-первых операция ptr[index] в стандарте определена через выражение *(ptr+index), но не говорится, что она обязана и выполняться через неё. В конце концов операция умножения тоже определеляется через сложение... Во-вторых, даже если бы и так, для компилятора это встроенная операция, которую он и так знает как выполнять, поэтому он вполне сможет встроить её код прямо по месту, ибо определение этой операции ему всегда доступно. В-третьих, даже пользовательские функции компилятор даже с весьма посредственным оптимизатором умеет встраивать, если это приводит к выгоде, и если определение функции ему доступно. При этом убираются и вызовы/возвраты, и дублирование параметров на стеке с заменой их на оригиналы, раз они не изменяются функцией, и код встоенной функции оптимизируется совместно с кодом вызывающей... Что ж тогда говорить о стандартных функциях и операторах.

P.S. Я здорово косякнул в своём посте. Везде где имел в виду T * const понаписал T const*. Извинияюсь и уже поправил.
Автор: Elf23
Дата сообщения: 14.11.2006 12:47
Товарищи будте людьми, но хоть кто нибудь подскажите где можно достать любую литературу по Winforms!!!!
Умоляю!!!!!!
Автор: xdude
Дата сообщения: 14.11.2006 13:25
Bender_R
Спасибо за ссылки.

А все-таки в русском переводе никто не встречал стандарта С++? Ну или хотя-бы C?
Автор: IFIT Horror
Дата сообщения: 14.11.2006 14:32
Товарищи, подскажите пож, как можно реализовать построчное считывание с файла? При том что строки должны выводиться на экран в произвольном порядке.Если использовать fgets(), то он то считывает по строчно, но строки идут по порядку, а нужно ,чтоб в хаотичном порядке выдавались
Автор: distance
Дата сообщения: 14.11.2006 15:29
либо считать весь файл в заранее выделенный массив строк и выводить на экран строки в случайном порядке уже из массива, либо каждый раз сбрасывать файловый указатель (fseek, _lseek) в начало и "пропускать" рандомное число строк (тем же fgets'ом)
Автор: Jokerjar
Дата сообщения: 14.11.2006 15:29
IFIT Horror, загружай текст в StringList, а там уже мути со сторками. Если надо, могу подкинуть алгоритм случайного заполнения массива неповторяющимися числами. Можно использовать для перемешивания строк.


Добавлено:
Вот написал (правда на Delphi, не посмотрел тему ). Если не поймешь, скажи перепишу. Немного коряво, но работает:


Код: procedure ReadRndFile(FileName: string; Memo: TMemo);
var
SourcList, DestList: TStringList;
Indexes: array of Integer;
i: integer;
procedure FillArray(var A: array of Integer);
var
I, S, R: Integer;
begin
for I := 0 to High(A) do
A[I] := I;
for i := High(A) downto 0 do
begin
R := Random(I);
S := A[R];
A[R] := A[I];
A[I] := S;
end;
end;
begin
if not FileExists(FileName) then Exit;
SourcList := TStringList.Create;
DestList := TStringList.Create;
SourcList.LoadFromFile(FileName);
DestList.Text := SourcList.Text;
SetLength(Indexes,SourcList.Count);
Randomize;
FillArray(Indexes);
for i := 0 to SourcList.Count - 1 do
DestList.Strings[Indexes[i]] := SourcList.Strings[i];
Memo.Clear;
Memo.Lines := DestList;
SourcList.Free;
DestList.Free;
end;
Автор: abrakadabra13
Дата сообщения: 14.11.2006 23:21
помогите плиз... новичку...
знаю что в с++ можно создавать динамические массивы объектов:
int n;
cin>>n;
myclass *ob;
ob = new myclass[n];

вроде так...
а как сделать двумерные динамические массивы?
у меня компилятор такой мат выдаёт, когда я пытаюсь двумерные делат
Автор: kopachev
Дата сообщения: 15.11.2006 01:14
abrakadabra13


Код: int width = 3, height = 2;
int *ptr = new int[width*height];

for(int i=0; i<height; i++)
for(int j=0; j<width; j++)
ptr[i*width+j] = i+j; // работаем с элементом (i,j)

for( int i = 0; i < 2; i++)
{
for( int j = 0; j < width; j++)
printf(" %d ", ptr[i*width+j]);
printf("\n");
}

// Удаляем массив
delete [] ptr;
Автор: Mickey_from_nsk
Дата сообщения: 15.11.2006 09:41
abrakadabra13
Один из вариантов написал kopachev - это когда двумерный массив линеаризуется в одномерный. Можно делать и классический двумерный массив, который с т.з. использования памяти менее эффективен, но более читабелен.

Код:
int width = 3;
int height = 2;

int *array[] = new int*[width];
for (int i=0; i<width; i++)
{
array[i] = new int[height];
// Если надо - инициализация
for (int j=0; j<height; j++)
array[i][j] = 0;
}
// Работаем с массивом
...
// Теперь можем удалять.
for (int i=0; i<width; i++)
{
delete [] array[i];
}
delete [] array;
Автор: andreww
Дата сообщения: 15.11.2006 11:22
Народ, извините за возможный оффтоп, но:
стоит задача "переложить" программу, созданную на Фортране, на С++. Стоит ли этим заниматься (при том, что программал я до этого лишь на Вб и ВБа, ну и школьный Паскаль) и если стоит, то с чего начать?
Автор: tomegadeth
Дата сообщения: 15.11.2006 11:45
andreww стоит для начала глянуть сюда FOR_C by Cobalt Blue
Автор: xdude
Дата сообщения: 15.11.2006 11:49
andreww
А я когда-то так делал: то, что на фортране было написано - скомпилировал в библиотеку (DLL), и эту библиотеку подгружал в программу, написанную на C++.
Автор: abrakadabra13
Дата сообщения: 15.11.2006 12:42
Mickey_from_nsk, kopachev
спасибо вам большое.


Цитата:
int *array[] = new int*[width];
for (int i=0; i<width; i++)
{
array[i] = new int[height];
// Если надо - инициализация
for (int j=0; j<height; j++)
array[i][j] = 0;
}

Я правильно понимаю что вначале объявляем массив динамических ссылок, а потом их самих объявляем динамическими массивами?
И насколько больше он ест памяти и почему? Объясните незнающему
Автор: Mickey_from_nsk
Дата сообщения: 15.11.2006 13:21
abrakadabra13

Цитата:
Я правильно понимаю что вначале объявляем массив динамических ссылок, а потом их самих объявляем динамическими массивами?
И насколько больше он ест памяти и почему? Объясните незнающему

Все правильно понял .
Линеаризованные массивы я видел еще в фортране. Там они реализуются на уровне компилятора и, видимо, тогда это было очень оправданно. При этом расходуется памяти ровно width*height*sizeof(int).
Во втором случае в силу необходимости выделения дополнительного вектора под указатели на линейные массивы, расход памяти увеличивается на width*sizeof(int*).

Как говорилось выше, достоинством первого подхода (линеаризации массива) является меньший расход памяти. Недостатком - то что необходимо каждый раз перевычислять положение требуемого элемента массива. То есть необходимо хранить и беречь переменную width. Во втором случае эта переменная особо не нужна (кроме случаев, если необходимо ввести доп. проверку на "невыход" за границы массива), соответственно, упрощается ситуация, когда массив надо вернуть из функции.
Кстати, тут уже где-то обсуждался такой ньюанс.
Если объявлять статический двумерный массив типа

Код:
int array[3][4];
Автор: andreww
Дата сообщения: 15.11.2006 16:53
tomegadeth
Пасибы, буду пробовать.
xdude
Тоже спсб, а с Билдером этот фокус прокатит?

Страницы: 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193

Предыдущая тема: не знаю как назвать тему :-)


Форум Ru-Board.club — поднят 15-09-2016 числа. Цель - сохранить наследие старого Ru-Board, истории становления российского интернета. Сделано для людей.