Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.06.2008, 23:10   #21
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,619
По умолчанию

Вот откоментированная прога
Код:
#include <stdio.h>
#include <iostream>
#include <string>
using namespace std;

class NameDataSet
    {
public:
char szFirstName[128];   			//поле класса ИМЯ   
char szLastName [128];      			//поле класса ФАМИЛИЯ
int nSocialSecurity;        			//поле класса НОМЕР СОЦ. СТРАХОВАНИя
NameDataSet* pNext;				//указатель на следующий элемент
     };

NameDataSet* pHead = 0;				//в начале работы программы список пуст

void addTail(NameDataSet* pNDS)			//функция добавления в конец ("В хвост") списка
{
pNDS->pNext = 0;				//переходим на следующий элемент
if (pHead == 0)					//если список пуст (т.е. первый элемент = NULL)
{
pHead = pNDS;					//просто присваиваем указателю на первый элемент списка значение указателя на текущий элемент
return;
}

NameDataSet* pCurrent = pHead;			//Иначе объявляем временный указатель на начало
while(pCurrent->pNext)				//пока не дойдем до последнего элемента (тоесть пока не найдем элемент у которо указетель на следующий не будет равен 0)
{
pCurrent = pCurrent->pNext;			//в цикле переходим с текущего элемента к следующему 
}
pCurrent->pNext = pNDS;				//для последнего элемента следующим делаем тот, что передали в функцию
}
NameDataSet* getData()				//функция возвращает указатель на элемент для добавления
{
NameDataSet* pNDS = new NameDataSet;		//создаем новый элемент		
cout << "Введите имя ";				//вводим значение для его поля ИМЯ
cin >> pNDS->szFirstName;

if ((stricmp(pNDS->szFirstName, "exit") == 0))	//если было введено слово "exit"
{	
delete pNDS;					//удаляем элемент
return 0;
}
cout << "Введите фамилию ";			//Вводим поле ФАМИЛИЯ для данного элемента
cin >> pNDS->szLastName;
cout << "Введите номер социального страхования ";
cin >> pNDS->nSocialSecurity;
pNDS->pNext = 0;				//следующего элемента после введенного элемента нет
return pNDS;					//возвращаем значение указателя
}
void displayData(NameDataSet* pNDS)		//функция вывода на экран
{
cout << pNDS->szFirstName			//выводим по полям класса ИМЯ ФАМИЛИЯ Н.СОЦ.СТРАХ. 
<< " "
<< pNDS->szLastName
<< "/"
<< pNDS->nSocialSecurity
<< "\n";
}

int main(int argc, char* pArgs[])
{
cout << "Считываем имя \ Фамилию социального страхования" << endl
<< "Введите 'exit' в поле имени для выхода" <<endl;
NameDataSet* pNDS;				//объявляем указатель на элемент списка
while (pNDS = getData())			//пока не введем в поле ИМЯ "exit"
{
addTail(pNDS);					//добавляем в конец элементы
}
cout << "Элементы: " <<endl;
pNDS = pHead;					//находим начало
while(pNDS)
{
displayData(pNDS);				//выводим содержимое списка по полям каждого элемента
pNDS = pNDS->pNext;				//переходим на следующий элемент
}
system("PAUSE");
return 0;
}
Хотя некоторые вещи там не так написаны как нужно. Тоесть прога эта нестабильно пахать будет.
MaTBeu вне форума Ответить с цитированием
Старый 08.06.2008, 01:56   #22
filosof_x86
...
Форумчанин
 
Аватар для filosof_x86
 
Регистрация: 01.06.2008
Сообщений: 134
По умолчанию

Цитата:
Сообщение от Rembo Посмотреть сообщение
нашел пример работы со списками
Только вот в этом куске с++ немногим больше

Вот еще одна реализация сортированного списка, но только теперь на С++. Причем в этом коде уже вовсю инкапсуляция и шаблоны. Кстати по поводу одного высказывания:

Цитата:
Сообщение от ACE Valery Посмотреть сообщение
Насколько я знаю, к элементу нельзя НИКАК обратиться, кроме как по адресу.
Обращение по индексу можно сделать абстрактным понятием, перегрузив оператор []. Это продемонстрировано в коде.

Код:
#include <iostream>
#include <fstream>

typedef size_t bad_index;

template<typename T>
class SortedList {
public:
  SortedList() 
  {
    begin = end = 0;
    count = 0;
  }

  virtual ~SortedList() 
  {
    clear();
  }

  void clear()  // уничтожение всего списка
  {
    if(begin) { // если в списке есть хотя бы один элемент  
      while(begin->next) {   // у end->next будет равен 0, поэтому мы обойдем весь список
        begin = begin->next; // двигаемся к следующему элементу 
        delete begin->prev;  // поэтому уничтожаем предыдущий 
      }   
      delete begin;   
    }
    begin = end = 0;
    count = 0;
  }

  void insert(T value) // добавление еще одного элемента в список
  {
    count++;
    Item<T> *item = new Item<T>(value);    

    if(begin == 0) {                // список сейчас вообще пуст
      item->next = item->prev = 0;
      begin = end = item;
      return;
    }

    if(value < begin->value) {      // ставим в самое начало списка
      item->prev = 0;
      item->next = begin;
      begin = begin->prev = item;
    } else if(end->value < value) { // ставим в самый конец списка
      item->next = 0;
      item->prev = end;
      end = end->next = item;
    } else {                        // нужно найти место в середине списка
      Item<T> *p = begin->next;
      while((p != end) && (p->value < value)) p = p->next; // поиск места в списке
      item->next = p;
      item->prev = p->prev;
      p->prev = p->prev->next = item;
    }
  }

  void erase(size_t idx) // удаление элемента с индексом idx
  {
    Item<T> *p = get_item(idx);
    if(p->next) p->next->prev = p->prev;
    if(p->prev) p->prev->next = p->next;
    delete p;
  }

  inline size_t size()
  {
    return count;
  }

  T operator[](size_t idx) // для возможности рыботы как с массивом
  {
    return get_item(idx)->value;
  }

  friend std::ostream& operator<<(std::ostream &out, const SortedList<T> &list) // выводим весь список
  {
    out << "[sorted_list count=" << list.count << "]" << std::endl;
    size_t i = 0;
    Item<T> *p = list.begin;
    for(; p; ++i, p=p->next) out << "  sorted_list[" << i <<  "]: " << p->value << std::endl;
    out << "[/sorted_list]" << std::endl;
    return out;
  }

protected:
  template<typename T> 
  struct Item {
    Item(const T &v) {value=v;}
    T value;              // значение этого элемента
    Item<T> *next, *prev; // следующий и предыдущий элемент
  };
  
  Item<T>* get_item(size_t idx)
  {
    if(idx + 1 > count) throw (bad_index) idx; // если превышен индекс генерируем исключение
    Item<T> *p = begin;
    for(; idx; --idx) p = p->next; // находим нужный элемент
    return p;                      // и возвращаем его адрес
  }

  Item<T>* get_begin() {return begin;}
  Item<T>* get_end()   {return end;}

private:
  Item<T> *begin, *end; // указатели на начало и конец списка
  size_t count;         // счетчик кол-ва элементов
}; 

int main()
{
  const size_t n      = 10,
               mod    = 50,
               const_ = -15; // чтобы были и отрицательные числа
  SortedList<int> list;

  int tmp;
  for(size_t i = 0; i<n; ++i) {
    tmp = const_ + rand()%mod;
    std::cout << "new rand[" << i << "]: " << tmp << std::endl;
    list.insert(tmp);
  }
  
  std::cout << "\n\n>print list:\n"
            << list
            << "\n\nuse operator[]: " << std::endl;
  while(true) {
    try { // демонстрация обработки неверного индекса
      std::cin >> tmp;
      std::cout << "list[" << tmp << "]: " << list[tmp] << std::endl;
    }
    catch(bad_index) {
      std::cout << "bad index, list.size = " << list.size() << std::endl;
    }
  }
  return 0;
}
P.S. Это мне только одному так кажется, или подсветка синтаксиса на форуме для Паскаля и для С/С++ мало подходит
filosof_x86 вне форума Ответить с цитированием
Старый 08.06.2008, 09:48   #23
Rembo
Форумчанин
 
Аватар для Rembo
 
Регистрация: 29.10.2007
Сообщений: 628
По умолчанию

MaTBeu, спасибо большое. А почему вы считаете, что прога не стабильно будет работать? что там примерно не так? Я брал этот пример из книги
Rembo вне форума Ответить с цитированием
Старый 08.06.2008, 13:25   #24
MaTBeu
Eclipse Foundation
Старожил
 
Аватар для MaTBeu
 
Регистрация: 19.09.2007
Сообщений: 2,619
По умолчанию

Извините что ввел вас в заблуждение. Просто в этом куске кода
Код:
if ((stricmp(pNDS->szFirstName, "exit") == 0))	
{	
delete pNDS;					
return 0;
}
cout << "Введите фамилию ";			
cin >> pNDS->szLastName;
cout << "Введите номер социального страхования ";
cin >> pNDS->nSocialSecurity;
pNDS->pNext = 0;				
return pNDS;
не заметил что после delete pNDS стоит return 0. Мне показалось, что после удаления указателя всеравно вводятся фамилия и номер социального страхования. Еще раз извиняюсь.

ПыСы: То filosof_x86
Я вот не пойму в вашем (и не только) коде только одного. Разве не проще написать в начале программы одну строку
Код:
using namespace std;
чем возле каждого cin, cout, endl и прочих писать std? Или я чего-то не доганяю?

Последний раз редактировалось MaTBeu; 08.06.2008 в 13:30.
MaTBeu вне форума Ответить с цитированием
Старый 08.06.2008, 14:05   #25
Rembo
Форумчанин
 
Аватар для Rembo
 
Регистрация: 29.10.2007
Сообщений: 628
По умолчанию

Народ, вот решил сам хоть что-нибудь попробовать написать на тему связанные списки. Вообщем суть в том, чтобы создать 5 элементов, и все их заполнить. Но, уже после первого введенного числа выскакивает ошибка. Вопрос: у меня просто где-то ошибка, или вообще эта программа по такому принципу не заработает, тоесть это просто чушь? Посмотрите пожалуйста:
Код:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;

class NameDataSet
{
   public:
   int chislo;
   NameDataSet* pNext;   
};
                             
NameDataSet* pHead = 0;        
NameDataSet* pNew;             
NameDataSet* pLast;              

void zapolnenie(NameDataSet *pNew)
{
   cout << "Введите целочисленное число ";
   cin >> pNew->chislo;  
   pNew->pNext = 0;  
   return;
}

int main(int nNumberofArgs, char* pszArgs[])
{
for (int i = 0; i<5; i++)
{
pNew = new NameDataSet;
if (!pHead)               
   {
      pHead = pNew;        
   }   
   else
    {
     pLast->pNext = pNew;
    pLast = pNew;        
    } 
 zapolnenie(pNew); 
}  
system("PAUSE");
return 0; 
}
Rembo вне форума Ответить с цитированием
Старый 08.06.2008, 18:25   #26
filosof_x86
...
Форумчанин
 
Аватар для filosof_x86
 
Регистрация: 01.06.2008
Сообщений: 134
По умолчанию

Цитата:
Сообщение от MaTBeu Посмотреть сообщение
ПыСы: То filosof_x86
Я вот не пойму в вашем (и не только) коде только одного. Разве не проще написать в начале программы одну строку
Код:
using namespace std;
чем возле каждого cin, cout, endl и прочих писать std? Или я чего-то не доганяю?
На этом вопросе можно приличную статью накатать, но постараюсь как можно кратче:

Пространство имен введено для того, чтобы избежать совпадения имен в одной области видимости. Однако когда мы подключаем все пространство, то мы сводим попытку разграничить имена на «нет» и рискуем столкнуться с ситуацией неопределенности.

Вот пример такой ситуации:
Код:
namespace A { int i; }
namespace B { int i; }

int main()
{
  A::i = 0; // все хорошо
  B::i = 0; // все хорошо
  using namespace A;
  using namespace B;
  i = 1;    // неопределенность - i из какого пространства имен нужно вызвать?
  return 0;
}
Если в мелких проектах на такую ситуацию практически никогда не натыкаешься, то в средних и больших она уже не слишком редка. К тому же, ошибка при компиляции не будет очевидна – начинающий или программист средней масти не сможет исправить эту ситуацию за малое время, т.к. не знает все имена в каждом из пространстве имен.

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

Использование using namespace можно сравнить с жизнью: вы же покупаете только то, что вам нужно, а то, что не нужно не купите, просто потому, что оно вам не нужно.
filosof_x86 вне форума Ответить с цитированием
Старый 08.06.2008, 19:00   #27
Rembo
Форумчанин
 
Аватар для Rembo
 
Регистрация: 29.10.2007
Сообщений: 628
Вопрос

Многоуважаемый MaTBeu мне сказал что, чтобы освоить связанные списки нужно понять, ну и написать самому, такие примеры: 1) Добавление в начало. 2) Добавление в конец. 3) Удаление из начала. 4) Удаление из конца. 5) Вывод.
1) да, у меня получилось. 2) тоже. 3,4) позже буду разбираться. 5) Как выводить, когда мы добавляем элементы в конец списка у меня получилось, а вот как выводить элементы, добавленные в начало списка - нет Помогите пожалуйста, скажите в чем ошибка: почему-то выводится только последний элемент:
Код:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;

class NameDataSet
{
   public:
   int chislo;
   NameDataSet* pNext;   
};
                             
NameDataSet* pHead = 0;        
NameDataSet* pNew;             
NameDataSet* pLast = 0;              

void zapolnenie(NameDataSet *pNew)
{
   cout << "Введите число ";
   cin >> pNew->chislo;  
   pNew->pNext = 0;  
   return;
}
void displayData(NameDataSet* pNew)
{ 
 cout << pNew->chislo <<endl;
}  

int main(int nNumberofArgs, char* pszArgs[])
{
for (int i = 0; i<5; i++)
{
pNew = new NameDataSet;
pNew->pNext = pHead;
pHead = pNew;
 zapolnenie(pNew); 
}  
pNew = pHead;
while(pNew)
{
   displayData(pNew); 
      pNew = pNew->pNext;    
           }
system("PAUSE");
return 0; 
}

Последний раз редактировалось Rembo; 08.06.2008 в 19:03.
Rembo вне форума Ответить с цитированием
Старый 08.06.2008, 19:17   #28
filosof_x86
...
Форумчанин
 
Аватар для filosof_x86
 
Регистрация: 01.06.2008
Сообщений: 134
По умолчанию

В zapolnenie() не нужно занулять:
Код:
pNew->pNext = 0;
filosof_x86 вне форума Ответить с цитированием
Старый 08.06.2008, 21:35   #29
Rembo
Форумчанин
 
Аватар для Rembo
 
Регистрация: 29.10.2007
Сообщений: 628
По умолчанию

filosof_x86, да, Вы правы, теперь заработало! Только я вот не понял: зачем вообще эту строчку я написал А вот если эту строчку удалить из программы "когда мы вносим элементы в конец списка, а затем элементы выводятся в консоль", то эта программа не работает, белиберду всякую выводит...
ЗЫ: программа конечно заработала, но числа почему-то выводятся наоборот, тоесть последнее число выводится первым и т.д. Где нужно изменить, чтобы числа в нормальном порядке выводились? Помогите пожалуйста.
Rembo вне форума Ответить с цитированием
Старый 08.06.2008, 23:54   #30
filosof_x86
...
Форумчанин
 
Аватар для filosof_x86
 
Регистрация: 01.06.2008
Сообщений: 134
По умолчанию

Цитата:
Сообщение от Rembo Посмотреть сообщение
А вот если эту строчку удалить из программы "когда мы вносим элементы в конец списка, а затем элементы выводятся в консоль", то эта программа не работает
Когда элемент вставляется в конец списка, то за ним следующего элемента нет, поэтому pNext надо занулить.

Цитата:
Сообщение от Rembo Посмотреть сообщение
ЗЫ: программа конечно заработала, но числа почему-то выводятся наоборот, тоесть последнее число выводится первым и т.д. Где нужно изменить, чтобы числа в нормальном порядке выводились? Помогите пожалуйста.
Разумеется, ведь вы каждый новый элемент вставляете в начало списка. Т.е. по мере заполнения у вас список изменяется так (если заполнять числами [1;5] в прямом порядке):

Код:
_____  _  _  _  _  _  1
_____  _  _  _  _  1  2
_____  _  _  _  1  2  3
_____  _  _  1  2  3  4
pHead->  1  2  3  4  5
И вывод начинается с pHead.
filosof_x86 вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Связанные таблицы в Аксессе mirawoo Microsoft Office Access 8 12.03.2008 00:13
Не отображаются данные связанные с гл. таблицей? zimmion БД в Delphi 11 27.02.2008 18:50
Связанные таблицы - проблема при обращении к полю БД nataly_ukr БД в Delphi 7 13.11.2007 10:47
Добавление записей в связанные таблицы с помощью Навигатора ~MaGic~ БД в Delphi 2 09.07.2007 08:01