Создание нового проекта консольного типа, страница 2

#include "stdafx.h"

// Глобальные переменные

const int maxSize = 2048;

char buf[maxSize];

char text[] = "  I    love    C++   very   much   Ok   ";

char** words;

int nWords, nChars;

// Глобальные функции (утилиты)

void CountWords()

{

#ifdef _DEBUG

cout << "\n\nCountWords:\tGot a text: '" << text << "'";

#endif

nWords = nChars = 0;

bool was = true;

   // Ваш код. Разработайте цикл прохода по строке text и подсчета количества слов

nChars = (int)strlen (text);

#ifdef _DEBUG

cout << "\n\tFound " << nWords << " words"

   << "\n\t" << nChars << " characters";

#endif

}

void CreateList()

{

   // Ваш код. Если words не равн нулю, то освободите память

// Ваш код. Захватите память под массив указателей в nWords + 1 элементов

char **d = words; // destination (Рабочая лошадка)

bool was = true;

for (int i = 0, n = 0; i <= nChars; i++)

{

//  bool is = // Ваш код. Является ли текущий символ пробелом?

//  if (Не пробел и не ноль)

//  {

//    // Ваш код. Перенесите текущий символ в буфер и увельчьте счетчик n

   // Этот фрагмент кода выполняет защитные функции. Его можно и выкинуть, так как вряд-ли у вас будут слова длиннее 2048

//    if (n == maxSize - 1)

//    {

//      cout << "\n\nCreateWords: found word longer than "<<maxSize

//        << " bytes. Leaving...";

//      // Ваш код. Если words не равн нулю, то освободите память

//      return;

//    }

//  }

//  if (сейчас не пробел, а был пробел, или сейчас ноль)

//  {

   if (n > 0)

   {

    buf[n++] = 0;  // Заканчиваем слово

    *d++ = strcpy (new char[n], buf); // Захванываем память, копируем слово и запоминаем в words[i]

    n = 0;  // Готовимся считать символы следующего слова

   }

//  }

//  was = is;

}

*d = 0;

#ifdef _DEBUG

cout << "\nCreateWords: Ok";

#endif

}

void PrintWords ()

{

cout << "\nWords:\n\n";

// Ваш код. Цикл вывода все слов

}

void TrimWord (char* word)

{

char *s, *d;

for (s = word, d = s;  *s == ' '; s++) // Пропускаем начальные пробелы

  ;

// Ваш код. Копируем не пустые символы по адресу *d. Это цикл

*d = 0; // Заканчиваем слово

}

void ReplaceWord (int id, char *word)

{

if (id < 0 || nWords <= id)

{

  cout << "\nReplaceWord: Wrong Index = " << id;

  return;

}

delete [] words[id]; // Освобождаем память

// Ваш код. Перекопируйте новое солво в words[id]. Здесь понадобится динамический захват памяти

TrimWord (words[id]);

}

void SwapWords (int i, int j)

{

char* t = words[i];

words[i] = words[j];

words[j] = t;

}

//void SwapWords (Два парамера. Оба адреса на адреса)

//{

// char* t = // Ваш код

// *s1 = // Ваш код

// *s2 = // Ваш код

//}

//void SwapWords (Два парамера. Оба ссылки на адреса)

//{

// char* t = // Ваш код

// // Ваш код

// // Ваш код

//}

void SwapAdjacentWords ()

{

int lim = int(nWords & 0xfffffffe);

for (int i = 0; i < lim; i+=2)

  SwapWords(i, i+1);

}

//void SwapAdjacentWordsPtr ()

//{

// for (Используйте указатели p1 и p2)

//  SwapWords (p1, p2);      // Передача адресом

//}

//void SwapAdjacentWordsRef ()

//{

// for (Используйте указатели p1 и p2)

//  SwapWords (*p1, *p2);    // Передача ссылкой

//}

void SortWords()

{

if (nWords < 2)

  return;

bool sorted = false;

      // Ваш код. Внешний цикл сортировки

{

  sorted = true;

      // Ваш код. Вннутренний цикл сортировки

  {

//    if (strcmp (*s1, *s2) > 0)

//    {

//      SwapWords (s1, s2);

//      sorted = false;

   }

  }

}

}

void main()

{

#ifndef _DEBUG

cout << "\n\nSource Text:   '"<<text<<"'";

#endif

CountWords();

CreateList();     PrintWords();

SwapAdjacentWordsRef(); PrintWords();

SwapAdjacentWordsRef(); PrintWords();

SwapAdjacentWordsPtr(); PrintWords();

SwapAdjacentWordsPtr(); PrintWords();

SwapAdjacentWords(); PrintWords();

SwapAdjacentWords(); PrintWords();

ReplaceWord (2, "  Mary   Lou  "); PrintWords();

SortWords();  PrintWords();

cout << "\n\n";

}

Все функции приложения должны работать.

Приложение

В языках С и С++ существуют еще две функции для захвата памяти в области heap. Действия по выделению памяти для массива array из size вещественных выглядят следующим образом:

float *array;         // Адрес начала будущего массива

array = (float*) malloc (sizeof(float)*size);   // или

array = (float*) calloc (size, sizeof(float));

Здесь malloc и calloc — функции, прототипы которых объявлены в файле alloc.h. Функция malloc(Nbyte) запрашивает память размером Nbyte байт из области heap и возвращает указатель на первый байт этого участка. Возвращаемый указатель имеет описатель void*. Это означает, что тип переменной, на которую он может указывать, не определен. Так как мы собираемся присвоить его переменной array (указателю на тип float), то необходимо осуществить преобразование с помощью cast-преобразования (float*).

Возвращаясь к операции захвата памяти new, отметим, что можно запросить память для произвольного, но известного на этапе выполнения количества (n) элементов какого-то типа. Это и составляет суть динамической работы с массивом переменных.

В языке С++ имеется возможность инициализировать указатель путем запроса памяти прямо в момент объявления переменной. Например,

float *p = new float[n];   // Инициализация указателя p

Здесь действует некая условность. Эту же операцию можно было бы выполнить в два этапа.