Показаны сообщения с ярлыком язык программирования Паскаль. Показать все сообщения
Показаны сообщения с ярлыком язык программирования Паскаль. Показать все сообщения

суббота, 6 января 2018 г.

Задание начального значения элементам массива

Очень часто при решении задач с массива требуется задать им начальное значение или обнулить. Самый простой способ использование цикла. Но есть и специальные функции, которые по указанному количеству байт задает им начальное значение.

В Паскале:

var A:array[1..100]of integer;
FillChar(A, 100*SizeOf(integer), 0);

Для строк:
Var S:string;
S:='';

или
Var S:string[100];
FillChar(S, SizeOf(S), ' ');

В С++:

int A[10]={0};
int B[10]={1};

Но для массива с переменной длиной не будет работать, надо так:

int n;
cin>>n;
fill(A, A+n, 0); 
Здесь A - хранит адрес начала массива, А+n - переносим указатель на n элементов, т.е. в конец массива, третий аргумент - чем заполнить массив, можно поставить 1.

fill(&A[0], &A[0]+n,0);
Здесь &A[0] - получаем адрес на начальный элемент массива с индексом 0.

Таким образом можно обнулять часть массива, например, начиная с середины:
fill(&A[n/2], &A[0]+n,0); 

Если это двумерный массив:
int n, m;
cin>>n>>m;
double A[n][m];
fill(&A[0][0], &A[0][0]+n*m, 0);

Если массив объявлен как vector:
vector <bool> A;
int n;
cin>>n;
A.resize(n,false);

или
fill(A.begin(), A.end(),true);



четверг, 30 апреля 2015 г.

Задание 27(С4) с пробного ЕГЭ 2015 Вариант 2.

Задача:
По каналу связи передается последовательность слов в алфавите {А, Е, Р}. Длина каждого слова не превосходит 10 букв, слова могут не быть осмысленными словами русского языка. Каждое слово передается в виде целого числа, полученного следующим образом:
1. Сначала слово кодируется с помощью неравномерного двоичного кода с кодовыми словами: Е - 0; Р - 10; А - 11.
2. К полученной двоичной последовательности b0b1...bm (длина последовательности - m+1) справа приписывается еще одна цифра bm+1 = 1;
3. Искомое число N вычисляется по формуле:
N = b0 + 21 · b1 + 22 · b2 + ... + 2m · bm + 2m+1 · bm+1.
Например, символьная последовательность ААЕЕР будет преобразована в 11110010, затем в 111100101, а затем - в число: 1 + 2 + 4 + 8 + 64 + 256 = 335. Отметим, что 335 = 1010011112.
Напишите программу, которая, получив на вход натуральное число, определяет, сколько раз в исходном слове встречаются гласные буквы, и выводит полученное значение на экран. Само слово выводить не нужно. 
Пример входных данных:
5483
Пример выходных данных:
4
Примечание:
В этом примере исходное слово: АЕРАЕРР
кодовая двоичная последовательность: 110101101010
после добавления 1 справа получим: 1101011010101

Решение с рассуждениями:
1) Что нам по задаче дано: одно натуральное число N.
2) Что нужно получить: количество гласных букв в закодированном слове K (счетчик).
3) Сформулируем алгоритм решения: чтобы найти закодированные символы, нужно перевести число N в двоичную систему, перевернуть двоичное представление и удалить последний символ единицу. Затем сначала выделяем группы цифр и соотносим их с кодами символов. Символы сохраняем в строку и проверяем каждый символ в строке. Если это гласная буква, то увеличиваем счетчик.
Если реализовать этот алгоритм, то можете получить только 2 балла. Попробуем упростить наши действия.
4) Определим диапазон натурального числа: максимальное количество символов в слове 10, максимальное количество бит на кодирование символа - 2, получим 2*10+1=21 бит, т.е. 3 байта. Целое число без знака не менее 3 байт - это длинное целое, занимающее 4 байта.
5) Как будем хранить двоичное представление числа? В виде строки S или в массиве целых чисел A, длиной не менее 21.
6) Как перевести число в двоичное представление? Посмотрим на примере перевода числа 83:
83 : 2 = 41 целых 1 в остатке
41 : 2 = 20 целых 1 в остатке
20 : 2 = 10 целых 0 в остатке
10 : 2 = 5 целых 0 в остатке
5 : 2 = 2 целых 1 в остатке
2 : 2 = 1 целых 0 в остатке
1 : 2 = 0 целых 1 в остатке
Собираем с конца -1010011 и переворачиваем - 1100101. Запишем алгоритм так:
пока N не равно 0 делать
   сохраняем остаток от деления N на 2  
   заменяем N на результат целочисленного деления N на 2
конец цикла пока
7) Видно, что переворачивать строку или массив не нужно. Так, если мы последовательно будем находить остатки, то их сразу будем заносить в массив или добавлять в строку справа. Переводить число в символ также не обязательно - можно просто проверить остаток на 0 и добавить к строке символ '0' или '1' если это 1.
8) Кроме этого, можно заметить, что удаление единицы можно заменить условием на N>1 вместо N<>0.
9) Как будем выделять коды символов?
Заметим, что с нуля начинается только один символ Е. Если встретилась '1', то проверяем следующий символ. Если это '0', то - символ Р (10), иначе - А (11). Таким образом можно сразу увеличивать счетчик K при проверке этих условий.
Попробуем реализовать этот алгоритм на Паскале с использованием строки:

var N: longint; i, b, m, K:integer; S:string[20];
begin
 readln(N);
 K:=0; S:='';
 while N>1 do begin
  b:=N mod 2; 
  N:=N div 2;
  if b=0 then S:=S+'0' else S:=S+'1';
 end;
 m:=length(S);
 i:=1;
 while i<=m do 
   if s[i]='0' then begin K:=K+1; i:=i+1; end
   else
      if s[i+1]='1' then begin K:=K+1; i:=i+2; end
      else i:=i+2;  
 writeln(K); 
end.

Программа на Паскале с использованием массива:

var N: longint; i, b, m, K:integer; A:array[1..20] of byte ;
begin
 readln(N);
 K:=0; i:=0;
 while N>1 do begin
  b:=N mod 2; 
  N:=N div 2;
  i:=i+1; 
  A[i]:=b;
 end;
 m:=i;
 i:=1;
 while i<=m do 
   if A[i]=0 then begin K:=K+1; i:=i+1; end
   else
      if A[i+1]=1 then begin K:=K+1; i:=i+2; end
      else i:=i+2;  
 writeln(K); 
end.

Оба варианта тянут на 3 балла. Попробуем написать на 4 балла.

10) Заметим, что цифры 0 или 1 мы получаем последовательно и их же потом и проверяем последовательно. Тогда зачем их хранить в массиве/строке? Будем сразу находить остатки и проверять условие. Приведем программу на С++:

#include <iostream>
using namespace std;
int main()
{
 int N, K=0, b;
 cin>>N; 
 while (N>1)
 { 
   b=N%2;
   N=N/2;  
   if (b==0) K++;
   else
    if (N%2==1)
   {
      K++; 
      N=N/2;
    }
  }
 cout<<K;
 return 0;
}

среда, 29 апреля 2015 г.

Задание 27(С4) с пробного ЕГЭ 2015 Вариант 3.

Задача: 
В физической лаборатории проводится долговременный эксперимент по изучению гравитационного поля Земли. По каналу связи каждую минуту передаются положительные вещественные числа - текущие показания прибора "Бета 14". Количество передаваемых чисел в серии известно и не превышает 10 000. Все числа не превосходят 1000.
Необходимо вычислить "бета-значение" серии показаний прибора - максимальную сумму двух показаний, между моментами передачи которых прошло не менее 5 минут. Временем, в течение которого происходит передача передача числа, можно пренебречь. В первой строке задается число N - общее количество показаний прибора. Гарантируется, что N>5. В каждой из следующих N строк задается одно положительное вещественное число - очередное показание прибора.
Пример входных данных:
10
12
5
45
46
8
11
20
30
28
26
Программа должна вывести одно число - описанную в условии сумму.
Пример выходных данных для приведенного выше примера входных данных:
75

Решение:
Сначала определимся, как получился результат: 30+45=75.
Теперь разберем задачу, что нам известно и какие нам нужны переменные:
N - количество вещественных положительных чисел;
А - массив таких чисел;
Max_Summa - максимальная сумма, которую нужно найти.
Для ее нахождения нужно перебрать все пары чисел на расстоянии не менее 5.
Так для первого числа это будут 6-е, 7-е, 8-е, 9-е. 10-е. 
Для второго - 7-е, 8-е, 9-е. 10-е.
и т.д.
Из этих сумм находим наибольшее. Приведем пример такой программы на Паскале:
var N:integer;
A:array [1..10000]of real;
Max_Summa:real;
i,j:integer;
begin
    readln(N);
    for i:=1 to N do
      readln(A[i]);
    Max_Summa:=0;
    For i:=1 to N-1 do
    For j:=i+5 to N do
        if  A[i]+A[j]>Max_Summa then Max_Summa:=A[i]+A[j];
   writeln(Max_Summa);
end.
Эта программа весит 2 балла, так как использует двойной цикл и массив, зависящий от количества переменных.

Попробуем разобрать алгоритм. Нужно ли перебирать все пары? Применим метод рассуждения как при динамическом программировании (получение решения на основе уже полученного ранее на предыдущем шаге).
С первыми пяти элементами мы ничего не можем делать.
Возьмем 6-й элемент - какой элемент мы будем складывать с ним? Только первый. Считаем его максимальной суммой.
Возьмем 7-й элемент - можно сложить к нему только 1-й и 2-й. А какой наверняка даст нам максимальную сумму (не считая первый полученный максимум)? Наверное тот, который максимальный. Значит нужно определить среди 1-го и 2-го элемента максимальный (обозначим как maximum) и найти максимальную сумму из условия:
если  6-й элемент + maximum > max_summa, то max_summa:=6-й элемент + maximum.
Для следующих элементов рассуждаем аналогично. Получим следующую программу на Delphi (Lazarus, PascalABC):
var N:integer;
A:array of real;
Max_Summa, Maximum:real;
i, j:integer;
begin
    readln(N); setlength(A,N); //нумерация массива от 0 до N-1
    for i:=0 to N-1 do
      readln(A[i]);
    Max_Summa:=0;
   
    For i:=5 to N-1 do begin
     Maximum:=0;
     For j:=0 to i-5 do 
       if A[j]>Maximum then Maximum:=A[j];
     if  A[i]+Maximum>Max_Summa then Max_Summa:=A[i]+Maximum;
   end;
   writeln(Max_Summa);
end.

Вроде бы не сильно изменилась программа, но все равно не обошлись без вложенного цикла.внимательно, то максимальный элемент можно искать последовательно добавляя новый, а не начинать поиск с начала. Перепишем так:

var N:integer;
A:array of real;
Max_Summa, Maximum:real;
i:integer;
begin
    readln(N); setlength(A,N); //нумерация массива от 0 до N-1
    for i:=0 to N-1 do
      readln(A[i]);
    Max_Summa:=0;
    Maximum:=0;
    For i:=5 to N-1 do begin
     if A[i-5]>Maximum then Maximum:=A[i-5];
     if  A[i]+Maximum>Max_Summa then Max_Summa:=A[i]+Maximum;
   end;
   writeln(Max_Summa);
end.

Эта программа на 3 балла. Так как в программе нет вложенных циклов, то она будет эффективна по времени.
Теперь избавимся от большого массива. Посмотрим, что используем мы только первые пять элементов и всегда только последний максимальный. Если массив будет из первых пяти, то для 11-го нужно сравнивать уже с шестым. Поэтому 6-й элемент нужно тоже сохранить для последующей обработки. А куда его деть? Посмотрите, что после обработки 6-го элемента первый элемент уже не нужен, так как он будет максимальный и в дальнейшем нахождении максимального он не нужен. Но остальные 4 элемента нам понадобятся. Можно сделать сдвиг массива влево и записать 6-й элемент как пятый. Этот массив можно представить как очередь (первый пришел - последний вышел). Приведем пример программы на С++:

#include <iostream>
#include <queue>
using namespace std;
int main()
{
queue <float> A;
int N, i;
float Max_Summa=0, Maximum=0, a;
cin>>N;
for(i=0;i<5;i++){cin>>a; A.push(a);}
for(i=5; i<N; i++)
{
a=A.front(); A.pop();
if (a>Maximum) Maximum=a;
cin>>a; A.push(a);
if (a+Maximum>Max_Summa) Max_Summa=a+Maximum;
}
cout<<Max_Summa;
return 0;
}
И эта программа уже будет на 4 балла. Но можно использовать и другой вариант без очереди с массивом из пяти элементов и без сдвига элементов массива влево. 

Заметим, что 5-й элемент нам понадобится только когда будем проверять 10-й, 6-й - для 11-го, 7-й - для 12-го, 8-й - для 13-го, 9-й - для 14-го. А далее 10-й только для 15-го и т.д. Т.е. каждый новый i-ый элемент можно занести в массив под номером, полученному по модулю 5: 
A[i%5]=a;
а ранее сравнивать с тем же элементом A[i%5]:
5-й с нулевым,
6-й с первым,
7-й со вторым,
8-й с третьим,
9-й с четвертым,
10-й с нулевым, который теперь 5-й,
11-й с первым, который теперь 6-й,
12-й со вторым, который теперь 7-й,
13-й с третьим, который теперь 8-й,
14-й с четвертым, который теперь 9-й,
и т.д.

Обратим внимание, что хранить в массиве можно только максимальные элементы. Тогда программа на C++ запишется в виде:

#include <iostream>
using namespace std;
int main()
{
float A[5];
int N, i;
float a, Max_Summa=0, Maximum=0;
cin>>N;
for(i=0;i<5;i++){
   cin>>a; 
   if (a>Maximum) Maximum=a; 
   A[i]=Maximum;
}
for(i=5; i<N; i++)
{
    cin>>a;
    if (A[i%5]+a>Max_Summa) Max_Summa=A[i%5]+a;
    if (a>Maximum) Maximum=a;
    A[i%5]=Maximum; 
}
cout<<Max_Summa;
return 0;
}

воскресенье, 11 января 2015 г.

Сложность алгоритма

Что значит сложность алгоритма и зачем нам ее знать? 
Для составления эффективного и оптимизированного по времени и по памяти алгоритма.
Сложность алгоритма обычно вычисляют для больших объемов данных, например, массивы из N элементов. 
Она бывает временная (по используемому времени выполнения) и емкостная (по размеру используемой памяти) и выражается как функция от N. Ее можно вычислить, зная сколько арифметических операций используется в алгоритме и сколько байт занимают данные. 

Кроме этого на эффективность алгоритма (точнее программы) влияет:

  •  работа процессора (количество операций выполняемых в секунду), 
  •  его разрядность (сколько бит считывается сразу, как одно слово), 
  •  устройство памяти,
  •  компилятор языка программирования (быстрее будет программа на Ассемблере).

Вот некоторые рекомендации:

  • Разрядность процессора должна совпадать с размером данных. Например, 32-х разрядный процессор будет быстрее выполнять операции с типами данных, которые кратны 32 (в Паскале - longint). Это относится и к размеру массива.
  • Цикл for работает быстрее while, так как не проверяет условие продолжения/окончания цикла каждый раз.
  • В логическом выражении ставьте первым то условие, которое выполняется чаще других. То же относится ко вложенным циклам и циклам с условиями.
  • Лучше использовать цикл вместо рекурсивной функции.
  • Ввод и вывод на экран тратится больше времени, чем при работе с файлом. Лучше работать напрямую с памятью (лучше динамической).
  • По возможности сохраняйте громоздкие вычисления в переменные или константы.
  • Вызов функций и подпрограмм тоже требует времени.
  • Если есть возможность - сразу считываем, обрабатываем и выводим результат. В некоторых задачах использование массива необязательно, например: в массиве, состоящий из целых чисел, подсчитать количество положительных чисел.
program project1;
var i,n,k,a:int64;//64 разрядный тип целых чисел
begin
 read(n);
 k:=0;
 for i:=1 to n do begin
  read(a);
  if a>0 then k:=k+1;
end;
write(k);

end.

Рассмотрим еще одну задачу, где можно обойтись без массива:
Напишите программу, которая циклически сдвигает элементы массива влево (например, массив {3, 5, 7, 9} превращается в массив {5, 7, 9, 3}).

Решение:
var
n:integer;
a,i,p:longint;
begin
 read(n);read(p);
 for i:=1 to n do begin
  read(a); 
  write(a,' ');
 end;
 write(p);
end.

Здесь сложность алгоритма, не учитывая время на ввод и вывод данных,  равна 0.

Рассмотрим аналогичную задачу, где без массива не обойтись:
Напишите программу, которая циклически сдвигает элементы массива вправо (например, если элементы нумеруются, начиная с нуля, то 0-й элемент становится 1-м, 1-й становится 2-м, ..., последний становится 0-м, то есть массив {3, 5, 7, 9} превращается в массив {9, 3, 5, 7}). (см. здесь)

Решение:
1. Считываем сразу все элементы в нужном порядке и выводим:
program A1;
var
n:integer;
a:array[1..3200] of longint;
i:longint;
begin
 read(n);
 for i:=2 to n do read(a[i]);
 read(a[1]);
 for i:=1 to n do write(a[i],' ');
end.
Здесь сложность алгоритма, не учитывая время на ввод и вывод данных,  равна 0.

2. После считывания всех элементов - делаем сдвиг с конца.
program A2;
var
n:integer;
a:array[1..3200] of longint;
i,p:longint;
begin
 read(n);
 for i:=1 to n do read(a[i]);
 p:=a[n];
for i:=n downto 2 do a[i]:=a[i-1];
a[1]:=p;
 for i:=1 to n do write(a[i],' ');
end.
По количеству присваиваний - сложность алгоритма линейно зависит от N+1.

3. После считывания всех элементов - делаем перестановки пары элементов с конца (как в сортировке пузырьком).
program A3;
var
n:integer;
a:array[1..3200] of longint;
i,p:longint;
begin
 read(n);
 for i:=1 to n do read(a[i]);
 for i:=n downto 2 do begin
  p:=a[i];a[i]:=a[i-1];a[1-1]:=p;
 end;
 for i:=1 to n do write(a[i],' ');
end.
По количеству присваиваний - сложность алгоритма линейно зависит от 3*(N-1).

Еще пример: Дан массив чисел. Переставить элементы массива в обратном порядке.

Решение: Если больше ничего с этим массивом делать не надо, то можно просто считать и вывести за один проход.

program A1;
var
n:integer;
a:array[1..3200] of longint;
i:longint;
begin
 read(n);
 for i:=1 to n do read(a[i]);
 for i:=n downto 1 do write(a[i],' ');
end.

или так

program A2;
var
n:integer;
a:array[1..3200] of longint;
i:longint;
begin
 read(n);
 for i:=n downto 1 do read(a[i]);
 for i:=1 to n do write(a[i],' ');
end.

Если действительно нужно перевернуть массив, то придется написать алгоритм:


program A3;
var
n:integer;
a:array[1..3200] of longint;
p,i:longint;
begin
 read(n);
 for i:=1 to n do read(a[i]);
 for i:=1 to n div 2 do begin
   p:=a[i]; a[i]:=a[n-i+1]; a[n-i+1]:=p; 
 end;
 for i:=1 to n do write(a[i],' ');
end.
 
 

четверг, 19 сентября 2013 г.

Работа со строками - что лучше Паскаль или C/С++?

Если задача на олимпиаде требует работу со строками, то всегда возникают некоторые проблемы с оптимизацией и быстрой ее реализацией. Если вы знаете Паскаль и Си (С++), то что выбрать?

В Паскале тип string работает как массив и хранит до 255 символов. Нумерация символов в строке начинается с 1. А в нулевом номере хранится символ, код которого отвечает за длину строки. В Си (точнее в С++) тоже есть тип string, но это класс и работать нужно со свойствами и методами этого класса.
Ели строка длиннее 255 символов, то строку можно сохранить как массив символов типа char (как в Си). Но в Си строка символов - это указатель, т.е. адрес памяти, с которого начинается строка, а заканчивается строка символом с нулевым кодом или символом конца строки '\0' (и об этом нужно всегда помнить!). Если его нет, то при выводе может выйти весь мусор, который находится в памяти компьютера, до тех пор пока не найдется этот символ (соответствующий ему нулевой байт).
Иногда по задаче даже не надо всю строку хранить, достаточно работать с одним символом типа char. В Си один символ заключается в апострофы, а строка - в кавычки. В Паскале - в любом случае - апострофом. Кроме этого в Си тип char - это целое со знаком в один байт, поэтому для русских букв (которые начинаются после 127 кода) при считывании получим отрицательный код. Чтобы этого избежать - объявляем как unsigned char.
Существует проблема ввода/вывода русских символов в современных средах. Так в среде Lazarus используется кодировка UTF8, которая отводит 2 байта под один символ, а все функции со строками языка Паскаль в основном работают в кодировке ANSI, поэтому нужно в начале перевести строку с помощью функции utf8toansi в привычную для Паскаля кодировку. Та же проблема возникнет и в среде CodeBlocks при написании программ с русскими строками (даже при выводе). В этом случае можно поменять кодировку самого проекта или вставить функцию setlocale(LC_ALL,"Russian"). Не забудьте подключить библиотеку locale.h. Конечно можно написать свою функцию декодирования, но это займет время, которое очень дорого стоит во время олимпиады.

Приведем стандартные алгоритмы при работе со строками, которые очень часто встречаются в олимпиадных задачах:
  1. Найти количество символов в строке
  2. Заменить символ в строке
  3. Удалить символ в строке
  4. Переставить символы в строке наоборот
  5. Найти количество подстрок в строке
  6. Удалить заданную строку d в строке s
  7. Вставить заданную строку d в строку s
  8. Заменить подстроку на заданную строку
  9. Вывести все слова в тексте, разделенные пробелом или иным символом
  10. Выделить цифры/число из строки
  11. Вывести число по заданному формату
  12. Определить дату/время по введенной строке
Каждая из этих задач по разному выполняется в Паскале и в Си. Если представить строку как массив символов, то разницы будет мало. Нужно сделать перебор каждого символа последовательно, как в массиве, если мы точно знаем сколько символов в строке. При этом ввод строки можно осуществить посимвольно. Если считывать всю строку, то в Паскале - это просто readln(s), а в Си - при потоковом вводе (с помощью cin) учитывается пробел, поэтому, если в строке есть пробелы, а нужно считать всю строку целиком, то используют специальную процедуру (например, getline). Но при этом конец строки не считывается, как в Паскале, его при выводе нужно добавлять самим (и об этом все время помнить!). Для определении количества символов обычно используют стандартные библиотеки: length(s) в Паскале, strlen(s) в С, s.length или s.size в С++.

Кроме этого при работе с файлами есть свои заморочки: проверка конца строки (коду 10, а не 13 как для Enter, или EOLN), проверка конца файла (EOF).

Описание строк

Паскаль:
var s:string; //строка с переменной длиной
    a:string[100];//строка с максимальной длиной строки 100
    b:array [1..500] of char;//массив из 500 символов
    c:char; //один символ
С:
unsigned char c; //один символ в кодировке ANSI
char d[]="programs for school";//строка сразу задана
char s[100]; // для строки выделяем 100 символов
c=&d; //  передаем указатель строки d переменной с.
char* t;//строка - указатель на первый символ.
t=(char*) malloc(10);//выделяем память под 10 символов 
free(t); //освобождение памяти

C++:
string a;//описание строки а как экземпляр класса string
char *c; /* указатель на начало строки, пока равен NULL (нулевой адрес, который ни на что не указывает)*/
с=new char [100]; /* теперь выделили для хранения строки 100 байт и с указывает на адрес начала строки.*/
delete c[]; //освобождение памяти

Ввод и вывод строк. Определение длины строки.

Паскаль:
readln(s); //ввод строки s
writeln(s);//вывод строки s
ls:=ord(s[0]);//длина строки s

readln(a); //ввод строки a и только до 100 символов
writeln(a);//вывод строки a
la:=length(a);//длина строки a

l:=0;
while not eoln do begin //
 read(c);//посимвольный ввод строки
 inc(l);//длина строки (учтите, что символов в строке/массиве не более 500)
 b[l]:=c;
end;
readln;//обязательно перейдите на следующую строку
for i:=1 to l do write(b[i]);//посимвольный вывод
writeln; //переход на новую строку

var x,code:integer;y:real;
// считываем только первое найденное число
{1 вариант}
s:='';//пустая строка
while not eoln do begin 
 read(c);
 if c in ['0'..'9'] then s:=s+c //проверка на цифры
     else break;
end;
val(s,x,code);//перевод из строки в число
if code=0 then write('целое число - ' , x);

{2 вариант}
//выделяем из строки число, удаляя все не числовые символы
readln(s);
repeat
val(s,y,code);
if code>0 then delete(s,code,1);//удаляем не числовой символ
until code=0;
write('не всегда целое число - ' , y);

//перевод числа x в строку s
str(x,s); str(y:0:2,a);
s:=s+' шт. за '+a+' руб.';
writeln(s);

//одна цифра в символ
x:=6;
c:=chr(ord('0')+6);
//цифра как символ в число
read(c);
x:=ord(c)-ord('0');

var hh,mm,ss,i,x:integer;
//ввод и вывод времени hh:mm:ss или даты dd.mm.yyyy
hh:=0;
for i:=1 to 2 do begin
read(c);
x:=ord(c)-ord('0');
hh:=hh*10*(i-1)+x;//собираем цифры в число
end;
read(c);//пропускаем разделитель времени

s:='';
for i:=1 to 2 do begin
read(c);
s:=s+c;
end;
//подключите модуль system (работает в среде FreePascal, Lazarus)
//strtoint - функция перевода из строки в целое
//strtofloat - функция перевода из строки в вещественное
//inttostr - функция перевода из целого в строку
//floattostr - функция перевода из вещественного в строку
mm:=strtoint(s);
read(c);//пропускаем разделитель времени

readln(ss);//оставшееся число считываем как целое

writeln(hh,':',mm,':',ss);

C:
Для ввода и вывода строки нужно учитывать следующее: есть ли в строке пробелы и оканчивается ли строка после ввода символом конца строки.
1) Можно считать как элементы массива и в конце добавить символ конца строки
2) Используя формат для ввода и вывода строки "%s"
3) Используя потоковый ввод и вывод для строки, содержащей пробелы
#include <stdio.h>
char с='5', t[]="school";

printf ("символы: %c %c %c\n", 'a', 65, c); 
printf ("строка: %s \n", t);

scanf("%s",t); //считывает до первого пробела
scanf("%10s",t);//считает не более 10 символов
scanf("%c",&c);
//посимвольный ввод строки
int i; 
char s[20];
for (i=0; (s[i] = getchar()) != '\n'; i++); 
 s[i] = '\0'; 
printf("\n%s\n", s);
//ввод/вывод всей строки 
gets(s); //ввод строки с пробелами не включая нулевой символ '\0', длина считываемой строки не ограничена, поэтому, если выделено 20 строк, а введено более, то считает всю строку "куда-нибудь в память", что может привести к непредвиденным ситуациям.
puts(s);//вывод строки с переходом на новую строку

//ввод строки s с указанным максимально возможным размером size-1
fgets(s, size, stdin);
int k = strlen(s); // Длина строки
if((k > 0) && (s[k-1] == 10))
{
 k--;
 s[k] = '\0';}

/*Функция fgets() имеет побочный эффект. Кроме полезной информации, что была набрана с клавиатуры, в конец строки будет помещён символ с кодом 10, а только затем символ с кодом 0. Для каких-то задач это не существенно, но лучше всегда удалять этот "мусор": в позицию символа с кодом 10 записывать нуль-символ.*/

k=isalpha(c);//проверка того, что символ — латинская буква. Здесь k будет не равно 0, если в переменой c хранится символ — латинская буква, и равно 0 — в противном случае.
k=isdigit(c);//проверка того, что символ — это цифра. Результат — не 0, если в c находится символ цифры, и 0 — если это не так.

//преобразование из числа в строку
char str[50];
int i=15; 
int j; 
sprintf(str, "%d", i); // Записать в str строковое представление i
sscanf(str, "%d", &j); // Записать в j число, содержащееся в строке str 
sprintf(str, "i=%d and j=%d", i, j); // содержимое str: "i=15 and j=15"
//преобразование из строки в число
double d=atof("23.4"); 
int i=atoi("123"); 
long l=atol("100000000"); 

//Заполняем s символьной строкой "ABCD". После выхода из цикла переменная i равна 4. 
// В эту позицию и записываем нуль-символ.
char s[6];
int i;
for(i = 0; i < 4; i++)
s[i] = i + 'A';
s[i]='\0';

С++:cin >>a; //ввод слова до пробела
int i, l=a.size();//размер строки
cout<<"длина строки: "<<a<<"\n равна "<<l<<" или "<<a.length()<<endl;

for (i=0;i<l;i++) cout<<a[i]<<endl;//посимвольный вывод

//ввод и вывод всей строки вместе с пробелами до нажатия Enter
string line;
getline (cin, line);
cout << line << endl;
//внимание! перевод строки не считывается.

//посимвольный ввод и вывод до нажатия клавиши Enter (код 10)
while ( (c=cin.get()) != 10)
cout.put(c);
cout<<endl;


// считываем только числа (нужна библиотека sstream)
string mystr; float price=0; int quantity=0;
cout << "Enter price: "; getline (cin,mystr);
stringstream(mystr) >> price;
cout << "Enter quantity: "; getline (cin,mystr);
stringstream(mystr) >> quantity;
cout << "Total price: " << price*quantity << endl;


double aa=5.5123;
int bb=10;
string ss="74326.46238",dd="123";

//перевод из строки dd в число bb
stringstream(dd)>>bb;
cout<<'\n'<<bb;

//перевод из строки ss в число aa
istringstream ins;
ins.str(ss);
ins>>aa;
cout<<'\n'<<aa;

//перевод из числа bb в строку ss
bb=456;
ostringstream oss;
oss<<bb;
ss=oss.str();
cout<<endl<<ss;

//ввод и вывод времени и даты по формату
int mm, hh, ss, d, m, y;
cout<<"введите время по формату час:мин:сек -> ";
cin >>hh>>c>>mm>>c>>ss;
cout<<hh<<'-'<<mm<<'-'<<ss<<endl;

cout<<"введите дату по формату день/месяц/год:";
cin >>d>>c>>m>>c>>y;
cout<<d<<'-'<<m<<'-'<<y<<endl;


Работа с текстовыми файлами

Паскаль:
Var f:text; 

assign(f,'input.txt');reset(f);
readln(f,s);
close(f);

assign(f,'output.txt');rewrite(f);
writeln(f,s);
close(f);

//стандартный ввод/вывод
assign(input,'input.txt');reset(input); //если закоментировать, то ввод с клавиатуры,
assign(output,'output.txt');rewrite(output);// а вывод на экран

readln(s);//input и output не объявляем и не упоминаем в командах!
writeln(s);

В среде Lazarus:
вместо text используют textfile
вместо assign используют assigntfile
вместо close используют closefile

С:
FILE *f; 
if((f=fopen("output.txt", "w"))==NULL) //открыть файл для записи
{ 
 printf("He удается открыть файл.\n"); 
 exit(1); 
} 

fprintf(f, "%s", s); 

fclose(f);
f=fopen("input.txt","r");//открыть файл для чтения
fscanf(f, "%s", s);


freopen("input.txt","r",stdin); //стандартный поток ввода/вывода
freopen("output.txt","w",stdout); 
scanf("%s",s); 
printf("%c",c);
//чтение одного символа из файла 
c=fgetc(f);
c=fgetc(stdin);//из стандартного потока ввода данных
//вывод одного символа в файл
fputc(c,f);
fputc(c,stdout);//в стандартный поток вывода данных
fgets(s, n, f);//Чтение строки из файла f размером не более n-1

C++:
//вывод строк в файл
string lines;
ofstream myfile ("example.txt");
if (myfile.is_open()) {
myfile << "This is a line.\n";
myfile << "This is another line.\n";
myfile.close(); }
else
cout << "Unable to open file";


//ввод строк из файла
ifstream myfile ("example.txt");
if (myfile.is_open()) {
while ( myfile.good() ) {
getline (myfile,lines);
cout << lines << endl; }
myfile.close(); }
else
cout << "Unable to open file";

//посимвольный ввод и вывод из файла пока не обнаружится конец файла EOF
ifstream in("input.txt");
ofstream out("output.txt");
while ( (c=in.get()) != EOF)
cout.put(c);
cout<<endl;


Стандартные библиотеки при работе со строками:

Паскаль:
l:=length(s)- длина строки s
p:=pos(s1,s) - позиция подстроки s1 в строке s - всегда первое вложение!
s1:=copy(s,index,count) - выделение из строки s подстроки длины count, начиная с позиции index
delete(s,index,count); - удаление из строки s подстроки длины count, начиная с позиции index
insert(p,s,index); - вставка подстроки p в строку s начиная с позиции index
С:
char *u;
strlen(s) - длина строки без нулевого символа
strcpy(d,s) - копирует строку s в d (при этом не добавляется знак конца строки )
strcpy(d,s,n) - копирует строку s в d  c максимально возможным количеством символов n при копировании

strcat(d,s) - соединяет строки d и s и результат записывает в d (конец строки сохраняется)
strncat(d,s,n) - Добавить в конец строки d первые n символов из строки s
strcmp(d,s) - сравнивает две строки, если они равны, то возвращает 0, если d<s, то возвращает число <0, иначе число >0

char c = 'B';
u = strchr(s, c);// Результатам выполнения функции strchr() будет адрес первого символа в строке s, который равен искомому символу c. Если символ не найден, то в указатель u будет записано число 0.
u = strrchr(s, c);//Вычисляется адрес последнего вхождения символа c в строку s (т.е. справа или с конца строки).
u=strstr(d,s) - поиск строки d в строке s; возвращает адрес на начало подстроки, если строка  найдена, иначе NULL

С++:
При работе со строками обычно используют функции библиотеки string.h:
l=a.size(); - длина строки
l=a.length();
a.insert(index,"const"); - вставка подстроки "const" в строку a с позиции index
string b("moroz"); - инициализация строки
a="oй, "+b+", "+b+"!"; - конкатенация (слияние) двух строк
a.replace(index,count,b); - замена count символов на подстроку, начиная с позиции index
b=a.substr(index, count); - выделение подстроки длиной count из строки а, начиная с позиции index
//удаление подстроки "ok"
int n;
while((n=a.find("ok"))!=-1)
 //пока символ есть
{
  a.erase(n,2);//удаляем с позиции n два символа
}
a.swap(b); - обмен строк

Более подробно смотрите о Си и С++.