1.2. Строки
Стандартный Паскаль не определяет строки как отдельный тип данных. Турбо Паскаль определяет и поддерживает несколько процедур и функций для работы с ними. Си (и Турбо Си) не определяют отдельный строковый тип данных; однако, строки могут быть определены как массив char или указатель на char. Приведем для сравнения несколько описаний:
Турбо Паскаль
<имя> : string[<размер>];
type
BigStr = string[255];
StrPtr = ^BigStr;
var
Line : string[80];
Buffer: BigStr;
Word : string[35];
Ptr : StrPtr
Турбо Си
char <имя>[<размер>];
typedef char bigstr[256];
typedef char *strptr;
char line[81];
bigstr buffer;
char word[36];
strptr ptr;
Различия между строками в Турбо Паскаль и в Турбо Си связаны с различиями между массивами в двух языках.
В Турбо Паскале описание s : string [N] эквивалентно s : array of [0..N] of char. Строка имеет максимальную длину N символов; текущая длина хранится в S[0], в то время как сама строка располагается начиная с S[1]. Вы можете использовать операцию присваивания между строкой литералов или константой и строковой переменной. Паскаль побайтно передаст переменные и скорректирует длину.
В Турбо Си вы можете описать строку как char strarr [N] или как char *strptr. Первое описание выделит N байт для строки и запишет адрес в strarr. Второе описание только выделит несколько байт для strptr, которая указывает на char.
В Си длина строки не хранится; вместо этого используется строчный разделитель для маркировки конца строки. Этим разделителем является нулевой символ (ASCII 0), который определяет конец строки; строка начинается с strarr[0].
Поэтому, строка strarr может содержать только N-1 "реальных" символов, причем один байт должен быть отведен для разделителя. Вот почему Си-определения в сравнительной таблице имеют длину на один больше, чем соответствующие Паскаль - определения.
Далее, strarr не является фактической последовательностью байт, вы не можете прямо присвоить строку литералов. Вместо этого, вы должны использовать подпрограмму strcpy (или подобные) для побайтной передачи из одной строки в другую:
strcpy(strarr, "Hello, world!");.
Однако вы можете напрямую читать в strarr, используя функции scanf или gets.
Другой метод определения строк, char *strptr, потребует от вас больше забот. В этом случае, strptr только указывает на char: пространство для содержимого строки не распределяется, только несколько байт для указателя непосредственно.
Вы можете прямо присвоить strptr значение строки литералов; так как эти литералы создаются, как область с их объектным кодом, то вы просто присвоите их адрес переменной strptr. Если вы присвоите strptr значение strarr, то обе переменные будут указывать на одну и ту же строку. То же произойдет, если вы дадите strptr значение другого указателя на строку.
Каким же образом вы разместите strptr так, чтобы он указывал именно на свою собственную строку вместо еще чего-нибудь? Посредством выделения пространства:
strptr = (char*) malloc(N);
Это выделит отдельно N байт имеющейся памяти, с помощью процедуры malloc, и присвоит strptr адрес этой области. Вы можете затем использовать strcpy для переписывания строк (литералов или переменных) в эти выделенные байты.
В Паскале существует аналог этому (StrPtr, Ptr), но это очень грубый эквивалент.Вместо того, чтобы написать ^Char, StrPtr определяют как ^BigStr. При этом Турбо Паскаль узнает, что ptr является строкой . Это также помогает избежать любых проблем по проверке принадлежности к диапазону (контроль границ). Запись в следующем примере показывает, что только запрос пространства является действительным размещением ptr.
Вот список приблизительно подобных по действию операторов; обратитесь к Справочному руководству по Турбо Си для пополнения этих списков строковых функций Турбо Си. Эти операторы исходного описания типов, заданы в соответствии с предыдущим сравнением.
Турбо Паскаль Турбо Си
var main ()
Line,Name : BigStr; {
First,Temp: String #C; bigstr line,name;
Ptr : StrPtr; char first[81],temp[81];
I,Len,Err : Integer; char *ptr;
int i,len;
extern char*str char(char*s,char ch);
begin
Write('Enter name: '); printf("Enter name: *);
Readln(Name); gets(name);
I := Pos('',Name); ptr = strchr(name,'.');
if (ptr == NULL)
if I = 0 then strcpy(first,name);
First := Name else
else strncpy(first,name,ptr-name-1);
First := Copy(Name,1,I-1); Len=strlen (first);
Len:=Length(First); printf("len = \d\n",len);
Writeln('Len=',Len); strcpy(temh,"Hi,");
Temp:=Concat('Hi,'Name); strcat(temp,name);
puts(temp);
Writeln(Temp); if (strcmp(name,first))
if Name < > First strcpy(name,first);
then Name:=First; i=823;sprintf(temp,"\d", i);
I:=823;Str(I,Temp); i=atoi(temp);
Val(Temp,Err); ptr=(char*)malloc(81);
GetMem(Ptr,81); strcpy(ptr,"This is a test.");
printf("ptr=\s\n",ptr);
Ptr^:='This is a test.'; free(ptr);
Writeln('Ptr= ',Ptr^);
FreeMem(Ptr,81);
end. }
Использование Ptr в исходной программе, написанной на Паскале - это одна из вариантных записей и служит для того, чтобы получить эквивалент Си кода.
Последний пункт: прототипы функции для подпрограмм Си, вызываемых в этом примере, перечислены в заголовке файлов; так для обнаружения ошибки вам нужно расположить следующие #include операторы в начале программы Турбо Си.
# include<stdio.h>
# include<string.h>
# include<stdlib.h>
# include<alloc.h>