Вывод и ввод данных в файл с помощью функций библиотеки периода выполнения (C Runtime Library), страница 5

puts("\nCreate and delete dirs example\n"

  "\nShall we create 10 nested dirs in C:\\? (Y/N)\n");

if (toupper(getch()) == 'Y')   // Ждем ответ и приводим его к верхнему регистру

{

  puts("\n\tEnter the dir name to create:\n");

  gets(dir);

  if (strlen(dir) != 0)

  {

   _chdir("C:\\");     // Начинаем с корня

   strcat (path, dir); // Наращиваем файловый путь

   while (nDirs--)

   {

    if (_mkdir(path) == -1)    // Создаем папку

    {

      puts("\nCould not create this dir\n");

      break;

    }

    strcat (path, "\\");

    strcat (path, dir);  // Наращиваем файловый путь

    _chdir(dir);

   }

   _chdir("C:\\");

   bCreated = true;

  }

}

   //===== Вторая (полезная) часть программы

if (!bCreated)

{

  puts("\n\tEnter the dirs name to remove:\n");

  gets(dir);

  if (!strlen(dir))

   return;

  //=== По умолчанию поиск начнется с текущей директории, которая определяется

      //=== местом запуска программы. Его выбирает пострадавший

  puts("\nShall we start from C:\\? (Y/N)\n");

  if (toupper(getch()) == 'Y')

   _chdir("C:\\");

}

//======= Входим внутрь (эта процедура зависит от числа созданных папок)

for (nDirs=0; !_chdir(dir);   nDirs++)

  ;

if (nDirs==0)

{

  printf("\n\n %s not found\n\n",dir);

  return;

}

//======= Выводим содержимое самой внутренней папки

fflush(stdin);

system ("dir\n"); // Это просто команда DOS

printf("\n\n %d dirs opened\n\n Should we remove them?\n",nDirs);

if (toupper(getch()) != 'Y')

  return;

for (int i=0;  i<nDirs;  i++)

{

  _chdir("..");  // Выходим наверх и пытаемся удалить папку

  if (_rmdir(dir) == -1)

  {

   printf("\n%s could not be removed\n\n",dir);

   break;

  }

  else

   printf("\nRemoving %s",dir);

}

printf ("\n%d dirs were removed\n\n", i);

}

Задание

Задание преследует цель выработать навык работы с динамическими массивами элементов стандартных типов. Дополнительно вы должны поупражняться в использовании файловых операций, рассмотренных в этом разделе. Смысл задания — моделирование отдельных функций синтаксического анализатора.

Условие задания таково:

¨  Пользователь вводит с клавиатуры произвольный текст, завершая его вводом символа «конец файла» (Ctrl+Z).

¨  Отдельный модуль программы размещает текст в буфере и затем записывает его в файл.

¨  Другой модуль подсчитывает количество слов (точнее лексем) nWords во введенном тексте. Разделителями будем считать множество символов: { '\n', '\t', ' '}.

¨  Далее следует отвести память (размером nWords) под динамический массив указателей на тип char, и вызвать модуль, который заполнит этот массив адресами начал слов (лексем) в буфере.

¨  Следует создать еще один динамический массив элементов типа int, в котором пользователь задаст порядок вывода на экран слов из буфера.

¨  После этого надо дать возможность пользователю ввести желаемый порядок и вывести отдельные слова (лексемы) в этом порядке.

Тем, кому это задание кажется слишком простым, предложим оттдельно подсчитать количество лексем, являющихся числовыми данными (например, 2 или 1.0е-3), и вывести их на экран. Кроме того, можно расширить множество символов, разделяющих лексемы.

Подсказки

¨  Для практики задайте новый тип данных typedef unsigned int uint;

¨  Функция подсчета количества слов может иметь примерно такую структуру:

uint CountWords()

{

bool was, is; // Флаги событий: "Был разделитель", "Текущий символ - разделитель"

uint nWords, i;

char c;

//========== Пока следуют обычные символы (не разделители), продолжаем сканировать буфер

for (uint i=num=0, was=true;  (c=buf[i])!=0 && c!=EOF;   i++)

{

  // Определяем флаги и увелиличиваем счетчик слов (если найден разделитель       

}

printf ("\nFound %d words\n", num);

return num;   // Возвращаем количество слов

}

¨  При работе с массивом указателей вспомните, что массив задается как адрес его начала, то есть массив — это уже указатель. Поэтому динамический массив указателей должен иметь тип адреса адресов символов (или char**).

¨  При реализации вывода отдельных слов, вычленяемых из текста, помните, что символьная строка в языке С (и С++) должна заканчиваться символом с кодом '\0', который надо как-то синтезировать.

¨  При посимвольном вводе текста надо учесть то, что не все функции ввода могут определить факт поступления символа  «конец файла» (Ctrl+Z). Советуем воспользоваться функцией getchar().

¨  При поиске целых чисел можно пользоваться функцией strtol (string to long), которая пытается преобразовать последовательность символов в число типа long. Параметры смотрите в Help. Алгоритм ее использования выглядит примерно так:

//====== pStop будет указывать на символ, который остановил сканирование строки (то есть не число)

char *stop, word[] = "24 some text";

char *p = word;              // p должно указывать на начало строки

long n = strtol (p, &stop, 0);   // Попытка преобразовать строку в число

if (*stop != *p)             // Если сканирование продвинулось, то число найдено

  printf ("\nInteger %d found\n", n);