Составить программу перекодировки текстового файла,
Задание 7.05. Перекодировка текстов из MS-DOS в Windows
Составить программу перекодировки текстового файла, подготовленного редактором MS-DOS, в кодовую страницу 1251 для Windows. Следует попытаться, по возможности сохранить вид таблиц, сформированных с помощью символов псевдографики.
Совет 1 (общий)
Совет 2 (общий)
Совет 3 (общий)
Совет 4 (Си, Паскаль)
Программа 7_05.bas
DECLARE SUB TOWIN(T01251() AS INTEGER)
DIM T0125K256) AS INTEGER
INPUT "Задайте имя файла - ",SOURCE$
TOWIN T01251()
OPEN SOURCE$ FOR INPUT AS #1
OPEN "TMPWIN.TXT" FOR OUTPUT AS #2
DO WHILE NOT EOF(l)
LINE INPUT #1, A$
FOR J=l TO LEN(A$)
MID$ (A$, J, 1) =CHR$ (T01251 (ASC (MID$ (A$, J, 1) ) ) )
NEXT J
PRINT #2, A$
LOOP
CLOSE 1,2
END
SUB TOWIN(T012510 AS INTEGER)
' Сохраняем первую половину таблицы ASCII
FOR J=0 TO 127: T01251(J)=J: NEXT J
' Увеличиваем на 64 коды букв от "А" до "n"
FOR J=128 TO 175: Т01251{J)=J+64: NEXT J
' Заменяем все символы псевдографики знаком "+"
FOR J=176 TO 223: Т01251(J)=ASC("+"): NEXT J
' Заменяем одинарную вертикальную черту
t01251(179)=ASC("|")
' Заменяем двойную вертикальную черту
t01251(186)=ASC("|")
' Заменяем одинарную горизонтальную черту
t01251(196)=ASC("-")
' Заменяем двойную горизонтальную черту
t01251(205)=ASC("=")
' Увеличиваем на 16 коды букв от "р" до "я"
FOR J=224 TO 239: Т01251(J)=J+16: NEXT J
t01251(240)=168: ' Заменяем код буквы "ё"
t0125К241) =184: ' Заменяем код буквы "Ё"
END SUB
Программа 7_05.с
#include <stdio.h>
#include <conio.h>
#include <string.h>
void to_win(void);
unsigned char to!251[256];
main(int narg, char **argv) {
FILE *fin,*fout;
unsigned char str[80],source[80];
int j,len;
if(narg==2) strcpy(source,argv[l]);
else {
printf("\n Задайте имя исходного файла - ");
scanf("%s",source); }
to_win();
fin=fopen(source,"rt");
fout=fopen("tmpwin.txt","wt");
while (Ifeof(fin)) {
fgets(str,80,fin);
len=strlen(str);
for(j=0; j<len; j++)
str[j]=to!251[str[j]];
fputs(str,fout);
}
fcloseall() ;
}
/*------------------------------------*/
void to_win(void) {
/* Формирование словаря перекодировки из MS-DOS в Windows */
int i ; /* Сохраняем первую половину таблицы ASCII */
for (i=0; i<128; i++) to1251[i]=i;
/* Увеличиваем на 64 коды букв от "А" до "n" */
for(1=128; i<176; i++)
to1251[i]=i+64;
/* Заменяем все символы псевдографики знаком "+" */
for(1=176; i<224; i++) to1251 [!] = ' + ';
и
/* Заменяем одинарную вертикальную черту */
to1251[179]='|'; /* Заменяем двойную вертикальную черту */
to1251[186]='|'; /* Заменяем одинарную горизонтальную черту */
to1251[196]='-'; /* Заменяем двойную горизонтальную черту */
to1251[205]='='; /* Увеличиваем на 16 коды букв от "р" до "я" */
for(i=224; К256; i++)
to1251[i]=i+16;
to1251[2401=168; /* Заменяем код буквы "ё" */
to1251[241]=184; /* Заменяем код буквы "Ё" */
return; }
Программа 7_05.pas
program translate; var
to1251:array [0..255] of char;
fin,fout:text;
str:string[803;
source:string[80];
j,len:integer; procedure to_win;
var
i:integer; begin
for i:=0 to 127 do
to1251[i]:=chr(i);
for i:=128 to 175 do
to1251[i]:=chr(1+64);
for i:=176 to 223 do
to1251[i]:='+';
to1251[179]:='|';
to1251[186]:='|';
to1251[196]:= '-';
to1251[205]:= '=';
for i:=224 to 239 do
to1251[i]:=chr(i+16);
to1251[240]:=chr(168);
to1251[241]:=chr(184);
end;
begin
if(ParamCount=2) then source:=ParamStr(1)
else begin
write('Задайте имя исходного файла - ');
readln(source);
end; to_win;
assign(fin,source);
reset(fin);
assign(fout, 'tmpwin.txt');
rewrite(fout);
while (not eof(fin)) do begin
readln(fin,str);
len:=length(str);
for j:=0 to len do
str[j]:=to1251[ord(str[j])];
writeln(fout,str);
end;
close (fin);
close(fout);
end.
Задание 7.06. Телефонный справочник
Составить программу, которая открывает текстовый файл для дозаписи и формирует в нем список, содержащий фамилию абонента и его телефон. Сортировкой фамилий в алфавитном порядке и исключением дублирующихся строк мы пока заниматься не будем.
Совет 1 (QBasic)
Совет 3 (Паскаль)
Программа 7_06.bas
CLS
OPEN "notebook" FOR APPEND AS #1
'Ввод данных с клавиатуры
DO
INPUT "ФАМИЛИЯ: ",Name$
INPUT "ТЕЛЕФОН: ",Phone$
WRITE #1, Name$,Phone$
INPUT "Добавим ";R$
LOOP WHILE LEFT$(R$,l)="f1"
CLOSE #1
CLS
OPEN "notebook" FOR INPUT AS #1
PRINT "Список абонентов в файле:"
DO WHILE NOT EOF(l)
'LINE INPUT #1, NP$ ' Чтение строки целиком
'PRINT NP$ ' Вывод данных на экран
INPUT #1, А$, В$ ' Чтение строки по компонентам
PRINT А$, В$' ' Вывод данных на экран
LOOP
CLOSE #1
END
Программа 7_06.с
#include <conio.h>
#include <stdio.h>
main() {
FILE *f;
int k;
char r,Name[20],Phone[10]; clrscr();
'f=fopen("notebook","at");
m: /* Ввод данных с клавиатуры */
printf("\n ФАМИЛИЯ: ");
scanf("%s",Name); printf("ТЕЛЕФОН: ");
scanf("%s",Phone);
fprintf(f,"%-20s %10s\n",Name,Phone);
printf("Добавим (д/н) - ");
r=getche(); if(г=='д')
goto m;
fclose(f);
clrscr();
f=fopen("notebook","rt");
printf("\пСписок абонентов в файле:\n") ;
while(!feof (f)) {
fscanf(f,"%20s %10s\n",Name,Phone);
printf("%-20s %10s\n",Name,Phone); }
fclose(f);
getch(); }
Программа 7_06.pas
program notebook;
uses Crt;
var
f:text;
R,Name,Phone:string; begin
clrscr;
assign(f, 'notebook ');
{$!-} append(f); {$!+}
if IOResult <> 0 then rewrite(f);
{ Ввод данных с клавиатуры }
repeat
write('ФАМИЛИЯ: ');
readln(Name);
write('ТЕЛЕФОН: ');
readln(Phone);
writeln(f,Name, ' ':15-length(Name), Phone:10);
write{'Добавим ');
readln(R);
until r[l] <> 'д ';
close(f);
clrscr;
reset(f);
writeln('Список абонентов в файле: ');
repeat
readln(f,r);
{ Чтение строки целиком } writeln(r);
{ Вывод данных на экран } until eof(f);
close(f);
readln;
end.
Задание 7.07. Создание резервной копии файла
Написать программу, которая извлекает из командной строки имя файла и создает в том же каталоге резервную копию файла с расширением bak.
Совет 1 (общий)
Совет 2 (QBasic)
Совет 3 (Си)
Совет 4 (Паскаль)
каталога, содержащего исходный файл (Dir), собственно имя файла (Name) и его расширение (Ext). Программа будет работать быстрее, если размер буфера для копирования очередной порции увеличить до 32 768 (кратность 512 здесь желательна, т. к. это число совпадает с длиной физического сектора).
Программа 7_07.bas
CLS : DIM k AS STRING*!
INPUT "Задайте имя файла - ", NAME1$
OPEN NAME1$ FOR BINARY AS #1
К = INSTR(NAME1$, ".")
IF К = 0 THEN NAME2$ = NAME1$
ELSE NAME2$ = LEFT$(NAME1$, К - 1)
NAME2$ = NAME2$ + ".ВАК"
PRINT NAME2$, К
OPEN NAME2$ FOR BINARY AS §2
DO
GET fl, , k
PUT #2, , k
LOOP UNTIL (EOF(l))
END
Программа 7_07.с
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 512
main(int narg, char **argv) {
FILE *f1,*f2;
int rd,wr;
char buf[N];
char namel[80],name2[80];
char *point;
if(narg < 2)
{ printf("\n He задано имя файла"); exit(0); }
strcpy(namel,argv[l]);
fl=fopen(namel,"rb");
if(fl==NULL)
{ printf("\n Файл %s не найден",namel); exit(0); }
point=strchr(namel, '. ');
if(point) {strncpy(name2,namel,point-namel};
name2[point-namel]=0x0; }
else strcpy(name2,namel); strcat(name2,".bak");
f2=fopen(name2,"wb");
do {
rd=fread(buf,l,N,fl);
wr=fwrite(buf,1,rd,f2); }
while (rd!=0 && rd == wr) ;
fclose(fl);
fclose(f2); }
Программа 7_07.pas
program reserve; uses Dos; const
N=512; var
fl,f2 : file;
rd,wr : word;
buf : array [1..N] of byte;
namel, name2 : PathStr;
dir : DirStr;
name : NameStr;
ext : ExtStr; begin
if ParamCount=0 then
begin writeln('He задано имя файла');
exit;
end;
namel:=ParamStr(1);
assign(f1,name1);
{$!-} reset(f1,l); {$I+}
if IOResult <> 0 then
begin writeln('Файл ',namel, ' не найден');
exit;
end;
fsplit(namel,dir,name,ext);
name2:=dir+name+'.bak';
assign(f2,name2);
rewrite(f2,1); repeat
blockread(fl,buf,N,rd);
blockwrite(f2,buf,rd,wr);
until (rd=0) or (rd <> wr) ;
close(fl);
close(f2);
end.
Задание 7.08. Выдача каталога на экран
Составить программу, которая извлекает из текущего каталога имена файлов с заданным расширением (например, *.pas) и выводит их на экран подобно директиве MS-DOS (dir *.pas), суммируя количество и длину обнаруженных файлов.
Совет 1 (QBasic)
Совет 2 (Си)
struct ffblk {
char ff_reserved[21]; //резерв на будущее
char ff_attrib; //атрибут набора данных
unsigned ff_ftime; //упакованное время создания
unsigned ff_fdate; //упакованная дата создания
long ff fsize; //длина набора в байтах
char ff_name[13]; //имя набора
};
Третий аргумент определяет атрибуты, которыми должен быть снабжен отбираемый набор данных, и может принимать разумную логическую сумму из значений, определенных в файле dos. h и задаваемых в Си следующими константами:
Цикл поиска нужных наборов данных начинается с обращения к процедуре f indf irst (поиск первого объекта) и повторяется многократными обращениями к процедуре findnext (поиск следующего объекта). Аргумент sr в обоих обращениях должен быть один и тот же. Цикл поиска продолжается до тех пор, пока функция поиска возвращает нулевое значение. Как только очередная попытка окажется неудачной, функция поиска возвращает значение -1.
Совет 3 (Си)
Вообще говоря, упакованные данные можно было бы извлечь и другим способом — логически умножить упакованную величину на константу, содержащую сплошные единицы в соответствующем поле, и сдвинуть полученный результат на нужное число разрядов вправо.
Совет 4 (Паскаль)
ченными в состав модуля DOS. Аргумент path задает маску отбора файлов (например, "*.pas"), расширенную спецификацию маски (например, "с: \tp\source\* .раs") или просто путь (например, "c:\tp"). Второй аргумент определяет атрибут, которым должен быть снабжен отбираемый набор данных, и может принимать логическую сумму из следующих значений, задаваемых в Паскале мнемоническими константами:
Аргумент sr представляет собой запись типа searchRec, на поля которой заносятся атрибуты найденного набора. Этот тип описан в модуле DOS и имеет следующую структуру:
type
SearchRec=record
Fill:array [1..21] of byte;
Attr:byte; {атрибут набора данных}
Time:longint; {упакованные дата и время создания}
Size:longint; {длина набора в байтах}
Name:string[12]; (имя набора} end;
Цикл поиска нужных наборов данных начинается с обращения к процедуре FindFirst (поиск первого объекта) и повторяется многократными обращениями к процедуре FindNext (поиск следующего объекта). Аргумент sr в обоих обращениях должен быть один и тот же. Цикл поиска продолжается до тех пор, пока системная переменная DosError принимает нулевое значение. Как только очередная попытка окажется неудачной, в DosError заносится 18.
Совет 5 (Паскаль)
Программа 7_08.bas
SHELL "dir *.bas" END
Программа 7_08.с
#include <stdio.h>
#include <conio.h>
#include <dir.h>
#include <dos.h>
main() {
struct ffblk sr;
int k,nf=0;
long lf=0;
struct tim
{
unsigned sec:5;
unsigned min:6;
unsigned hour:5;
};
struct dat {
unsigned day:5;
unsigned month:4;
unsigned year:7;
};
union {struct tim a;
unsigned b;}u;
union {struct dat c;
unsigned d; }v;
clrscr();
printf("Имя файла Длина Дата Время");
k=findfirst("*.c",&sr,FA_ARCH);
while (k==0) {
u.b=sr.ff_ftime; v.d=sr.ff_fdate; nf++;
lf+= sr.ff_fsize;
printf("\n%12s %61d ",sr.ff_name,sr.ff_fsize) ;
printf(" %02d/%02d/%4d ",v.c.day,v.c.month,1980+v.c.year);
printf(" %02d:%02d",u.a.hour, u.a.min);
k=findnext(Ssr); }
printf("\n%d файлов занимают %ld байт",nf,If);
getch(); }
Программа 7_08.pas
program dir;
uses Crt,Dos; var
dt:DateTime;
sr:SearchRec;
const
nf:integer=0;
If:longint=0;
function Zero(k:byte):string;
var
s: string;
begin
Str(k,s);
if k>9 then Zero:=s else Zero:= '0 '+s; end;
begin clrscr;
writeln('Имя файла Длина Дата Врекя');
FindFirst('*.pas',AnyFile,sr);
while DosError=0 do
begin with sr,dt do
begin inc(nf);
If:=lf+Size;
UnpackTime(Time, dt);
write (Name:12, ' ',Size:6, ' ');
write(Zero(Day), '/',Zero(Month), '/',Year:4, ' ');
writeln(Zero(Hour), ': ',Zero(Min), ': ',Zero (Sec)); end;
FindNext(sr); end;
writeln(nf, ' файлов занимают ',1f, ' байт');
readln; end.
Задание 7.09. Сдвиг содержимого текстового файла
Составить программу сдвига содержимого каждой строки текстового файла на заданное число позиций вправо. Это может оказаться полезным для формирования левого поля нужной ширины перед выводом содержимого файла на принтер по командам операционной системы PRINT или COPY.
Совет 1 (QBasic)
Совет 2 (Си)
Совет 3 (Паскаль)
Программа 7_09.bas
INPUT "Задайте имя исходного файла - ", NAME1$
INPUT "Задайте имя выходного файла - ", NAME2$
INPUT "Задайте величину сдвига - ", N%
OPEN NAME1$ FOR INPUT AS #1
OPEN NAME2$ FOR OUTPUT AS #2
DO WHILE NOT EOF(l)
LINE INPUT #1,A$: A$=SPACE$(N%)+A$
PRINT #2,A$
LOOP
CLOSE II: CLOSE #2
END
Программа 7_09.c
#include <stdio.h>
#include <stdlib.h>
void ind_copy(FILE *fl,FILE *f2,int n);
main(int narg, char **argv) {
FILE *fl,*f2; int n;
if(narg < 4) {
printf("\n Ошибка. Должно быть :"};
printf("\n7_09.exe файл1 файл2 n");
exit(0); }
f1l=fopen(argv[l],"rt");
f2=fopen(argv[2],"wt");
n=atoi(argv[3]};
ind_copy(fl,f2,n);
fcloseall();
}
/*-------------------------------------*/
void ind_copy(FILE *fl,FILE *f2,int n) {
char str[80]; int j;
for(j=0; j<n; j++) str[j]=' ';
while (Ifeof(fl)) {
fgets(&str[n],80,fl);
fputs(str,f2); }
return; }
Программа 7_09.pas
program indent;
var
f1,f2:text;
namel,name2:string;
n,k:integer;
procedure ind_copy(var fl,f2:text;n:integer);
var
str:string; begin
while not eof(fl) do
begin
readln(fl,str);
writeln(f2, ' ':n,str);
end;
end;
begin
if ParamCount < 3 then begin
writeln(' Параметры заданы неверно. Должно быть: ');
writeln('7_09.exe файл1 файл2 сдвиг ');
exit;
end;
namel:=ParamStr(1);
name2:=ParamStr(2);
Val(ParamStr(3),n,k);
assign(fl,namel);
reset (fl);
assign(f2,name2);
rewrite(f2);
ind_copy(f1,f2,n);
close(f1);
close(f2); end.
Программа 7_09a.pas
program indent1; var
f1,f2:text; namel,name2:string;
n,k:integer;
procedure ind_copy(var f1,f2:text;n:integer) ;
var
ch:char;
begin
while not eof(fl) do begin
write(f2, ' ':n);
while not eoln(f1) do begin
read(fl,ch); write(f2,ch);
end;
readln(f1); writeln(f2);
end;
end;
begin
if ParamCount < 3 then begin
writeln("Параметры заданы неверно. Должно быть: ');
writeln('7_09a.exe файл! файл2 сдвиг ');
exit;
end;
narnel:=ParamStr(1);
name2:=ParamStr(2);
Val(ParamStr(3),n,k);
assign(fl,namel);
reset(f1);
assign(f2,name2);
rewrite(f2);
ind_copy(f1,f2,n);
close(fl);
close(f2);
end.