Министерство образования и науки Российской Федерации
Федеральное агентство по образованию
Государственное образовательное учреждение высшего профессионального образования
«Санкт-Петербургский государственный университет информационных технологий,
механики и оптики»
ИКВО
МиПИУ
ВТИП
Лабораторная работа № 3
Использование стандартной библиотеки с
Вариант № 5
Студент: Гусихин А.Д.
Группа: 1750
Преподаватель: Гирик А.В.
Санкт-Петербург
2011
Задание:
Написать программу (язык С), которая выполняет ввод текстовой информации из файла или стандартного потока ввода, осуществляет преобразование информации в соответствии с вариантом задания (см. ниже) и выводит преобразованную информацию в файл или в стандартный поток вывода.
Программа представляет собой консольную утилиту [1, 2]. Настройка работы программы осуществляется путем передачи аргументов в строке запуска. Типичными примерами консольных утилит являются cat, ls, cal (в Unix) или dir, type, copy (в Windows) [3].
Строка запуска программы имеет следующий формат:
имя_программы [опции] [исходный_файл [результирующий_файл]]
где
опции - последовательность ключей, настраивающих поведение программы. Общие для всех вариантов опции перечислены в таблице 1. Некоторые варианты могут предусматривать дополнительные опции. Более подробно о правилах разбора опций можно прочитать в [4]. В большинстве случаев опции являются необязательными (т.е. могут не указываться в командной строке);
исходный_файл - путь к файлу, из которого нужно считывать информацию;
результирующий_файл - путь к файлу, в который нужно вывести результаты преобразования. Этот аргумент является необязательным и может задаваться в командной строке только в том случае, если был задан исходный_файл. Если результирующий файл не задан, результаты преобразования записываются в стандартный поток вывода. Результирующий файл может совпадать с исходным.
Если исходный_файл не задан, то это значит, что строки исходного текста программа должна читать из стандартного потока ввода.
Опция Значение
-b=N Выполнять действия, предусмотренные вариантом программы, начиная со строки номер N исходного текста. Если эта опция не задана, то действия выполняются, начиная с первой строки текста.
-e=M Выполнять действия, предусмотренные вариантом программы, до строки номер M исходного текста включительно. Если эта опция не задана, то действия выполняются до конца текста.
Задание:
Найти все уникальные (то есть встречающиеся в исходном тексте только один раз) строки.
Опции:
-i - не различать строчные и заглавные буквы при сравнении
Программа:
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <string.h>
int optionB=0; // опция b=
int optionE=0; // опция e=
int optionI=0; // опция -i=0 - нет, -i - да
char *fileNameIn; // наименование входного файла
char *fileNameOut; // наименование результирующего файла
FILE *fileIn, *fileOut; // переменная для файла
const int MaxRow=2048; // Максимальная длина массива arr
const int RowLen=128; // Длина буфера ввода/строк
// Функция предназначена для копирования подстроки
// из src в dest начиная с индекса B по индекс C
// src -исходная строка
// dest - результирующая строка
// b - Начало подстроки
// e - Конец подстроки
void strcpyBE(char *dest, char *src, int b, int e)
{
int j=0; // индекс элемента в строке dest
for(int i=b; (i<=e)&&(i<strlen(src)); i++) // цикл от b до e, но с контролем выхода i за предлы строки str
{
dest[j] = src[i]; // копируем элемент из строки src в строкцу dest
j++;
}
dest[j]=0; // в конце dest завершающий строку нулевой элемент
}
// функция декодирует один ключ
void DecodeOneKey(char *key)
{
char buf[128]; // буфер
// если строка имеет хотя бы два символа и начинается с b=
if ( (strlen(key)>1)&&(key[0]=='b')&&(key[1]=='=') )
{
strcpyBE(buf, key, 2, strlen(key)-1);
optionB = atoi(buf); // включена опция b
}
// если строка имеет хотя бы два символа и начинается с e=
else if( (strlen(key)>1)&&(key[0]=='e')&&(key[1]=='=') )
{
strcpyBE(buf, key, 2, strlen(key)-1);
optionE = atoi(buf); // включена опция e
}
// если строка имеет один символ и этот символ i
else if ( (strlen(key)==1)&&(key[0]=='i') )
{
optionI =1; // включена опция i
}
// иначе что-то не так
else printf("Неверный ключ: %s\n",key);
}
// функция обрабатывает список ключей -b11-e88-i
void DecodeKeys(char *key)
{
char buf[60];
int b=0, e=0; // начало и конец параметра
for (int i=0; i<strlen(key); i++) // проход по строке key
{
if (key[i]=='-' ) // Начало нового ключа
{
if ( (b<=e)&&(b>0) ) // если есть ключ
{
strcpyBE(buf,key,b,e); // копируем найденный ключ в buf
DecodeOneKey(buf); // декодируем ключ
}
b=i+1; // b - начало нового ключа
e=0; // конец пока неизвестен
}
else e=i; // возможный конец ключа
}
if ( (b<=e)&&(b>0) )
{
strcpyBE(buf,key,b,e);
DecodeOneKey(buf);
}
}
// функция печатает строку на экран или в файл если тот открыт
void PrintRow(char* buf)
{
if (buf==NULL)
return;
if ( fileOut==0 ) // если файл открыт
printf("%s\n", buf);
else
fprintf(fileOut,"%s\n", buf);
}
int main(int argc, char* argv[]) // argc - К-во параметров командной строки, argv[] - сами параметры
{
int i;
system("cls");
printf("utilsstr.exe [опции] [исходный_файл [результирующий_файл]]\n");
printf("опции =-i, -b=xxx, -e=xxx\n");
// проходим по списку апарметров командной строки
fileNameIn = NULL; // пока файлы не определены
fileNameOut = NULL; //
int j=0;
for (i=1; i<argc; i++) //при i=0 это имя самой программы, нас не интересует
{
if (argv[i][0]=='-') // это ключ
{
DecodeKeys(argv[i]); // раскодируем
}
else // это имя файла
{
j++; // номер файла в списке
switch(j)
{
// исходный файл
case 1: fileNameIn = new char[80]; // Выделяем память под имя файла
strcpy(fileNameIn, argv[i]); // Копируем из argv имя файла в fileNameIn
break;
// результирующий файл
case 2: fileNameOut = new char[80]; // Выделяем память под имя файла
strcpy(fileNameOut, argv[i]); // Копируем из argv имя файла в fileNameIn
break;
default: printf("Слишком много параметров!\n");
}
}
}
char* arr[MaxRow]; //массив для ввода информации с клавиатуры
for (i=0; i<MaxRow; i++)
arr[i] = 0; //обнуляем массив
if (fileNameOut!=NULL) // если определено имя результирующего файла
fileOut = fopen(fileNameOut, "w+");
int rowCount=0; // к-во строк
if (fileNameIn==NULL) // если нет файла то читаем с клавиатуры
{
printf("Введите строки (пусто - конец ввода): \n");
int t = 1; // для организации цикла
while ( t ) // пока t==1
{
char buf[128]; // буфер для ввода данных с клавиатуры
printf("%d=>",rowCount+1); // для больщей информативности
gets(buf); // ввести информацию с клавиатуры в buf
if (buf[0]!=0) // если буфер не пустой
{
arr[rowCount] = new char[strlen(buf)]; // распределить память для строки arr[rowCount]
strcpy(arr[rowCount],buf); // скопировать содержимое буфер в arr[rowCount]
} else t = 0; // конец ввода
rowCount++;
}
rowCount--; // кол-во строк - 1
}
else // если есть файл то читаем из файла
{
fileIn = fopen(fileNameIn, "r"); // Открыть файл
if ( fileIn!=0 ) // Если файл открыт
{
while (!feof(fileIn)) // Пока не конец файла
{
char buf[RowLen]; // Буфер для операций
fgets(buf, sizeof(buf), fileIn); // Читаем из файла в буфер
// Заменяем символ \n сиволом конец строки
for(int j=0; j<RowLen; j++) //
if (buf[j]==10) // \n=10
{
buf[j]=0;
break;
}
arr[rowCount] = new char[RowLen]; // распределить память для строки arr[rowCount]
strcpy(arr[rowCount], buf); // копируем из буфера в arr[rowCount]
rowCount++;
}
}
else printf("Ошибка откртия файла: %s\n", fileNameIn);
fclose(fileIn); // закрываем файл
}
// обработка введенных строк
for (i=0; i<rowCount; i++)
{
if ( ( optionB<=i+1) && ( (i+1<=optionE) || (optionE==0) ) )
{
int rowEq = 0; // кол-во повторений
char buf1[128], buf2[128]; // определение 2-х строк
for (int j=0; j<rowCount; j++) // пройдемся по всем введеным строкам
{
// копирование обрабатываемых строк а буфер 1, 2
strcpy(buf1, arr[i]);
strcpy(buf2, arr[j]);
if (optionI) // если не различать заглавные
{
// преобразуем в заглавные
strupr(buf1);
strupr(buf2);
}
if ( strcmp(buf1, buf2)==0) // сравневаем
rowEq++; // если строки равны то +1
}
if ( rowEq==1 ) // если строка в единственном экземпляре
PrintRow(arr[i]); // печатаем строку
}
}
// осбождаем распреленную память arr[i]
for(i=0; i<MaxRow; i++)
if (arr[i]!=NULL) // если память была распределена ранее
delete[] arr[i]; // освобождаем память arr[i]
if (fileOut!=0) // если результирующий файл был открыт
{
printf("Сформирован файл: %s\n", fileNameOut); // ссобщение
fclose(fileOut); // закрытие файла
}
// осбождаем распреленную память
if (fileNameIn!=NULL) delete[] fileNameIn;
// осбождаем распреленную память
if (fileNameOut!=NULL) delete[] fileNameOut;
printf("Press any key to continue...\n");
char c = getch(); // читаем символ с клавиатуры
return 0;
}
Результаты:
Начальный файл: