Опубликован: 02.02.2011 | Доступ: свободный | Студентов: 1 / 0 | Оценка: 4.43 / 3.57 | Длительность: 33:06:00
Специальности: Программист
Лекция 10:

Решение задач на обработку строк

< Лекция 9 || Лекция 10: 12 || Лекция 11 >
Аннотация: В лекции рассматриваются понятие, способы объявления, инициализация указателей на строки, применение функций обработки строк при решении типовых задач, особенности выполнения стандартных функций в контексте представления строк и указателей на строки.

Цель лекции: изучить принципы работы со строками и указателями на строки, алгоритмы решения задач на обработку строковых данных, научиться приемам решения задач на обработку строк, используя, функции для работы со строками и указателями на строки в языке С++.

Строки и указатели

Строки в языке С++ представляют собой массив символов. Поскольку имя массива без индексов является указателем на первый элемент этого массива, то при использовании функций обработки строк им будут передаваться не сами строки, а указатели на них.

Так как все строки в языке С++ заканчиваются нулевым символом, который имеет значение <ложь>, то условие в операторе while(*str) будет истинным до тех пор, пока программа не достигнет конца строки.

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

/*Пример пользовательской функции копирования строки s2 в s1*/
char * strcpy_my (char *s1, char *s2){
  char *ptrs1 = s1;
  //указатель инициализирован на начало строки
  while ((*s1++ = *s2++) != 0);
  return ptrs1; //возвращается указатель на строку s1
}

Следующий пример демонстрирует, что использование нулевого ограничителя упрощает различные операции над строками.

/*Пример пользовательской функции конкатенации*/
char * strcat_my (char *s1, char *s2) {
char *p1, *p2;
p1 = s1; p2 = s2;
while ( *p1 != '\0') p1++; //найти конец 1-ой строки.
                           //или while ( *p1) p1++;
  while ((*p1 = *p2) != 0) {
  /*копировать строку р2, пока не будет скопирован нулевой 
    Ограничитель*/
    p1++;  
    p2++; //Передвинуть указатели к следующему байту
  }       //или while (( *p1++ = *p2++) != 0);/*.
return s1;
}

Пример 1.

/*Демонстрация работы с указателями и с функциями для обработки строк*/
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
  char string[100], temp[100], *result, simvol;
  int numresult, res;
  /*создает строку "computer program" посредством 
    использования strcpy и strcat*/
  strcpy(string, "computer");
  result = strcat(string," program"); 
  printf("1) создали строку\n%s\n",result);
  /*находит строку, в которой первый раз обнаружено 'a'*/
  simvol='a';
  result = strchr(string,simvol);    
  printf("2) находим в строке первое вхождение символа \'%c\'\n
          %s\n",simvol,result);
  /* создает копию строки */
  result = strcpy(temp,string);
  printf("3) создали копию строку\n%s\n",result);
  /* находит "a","b","c" в строке */
  strcpy(string,"xyzabbc"); 
  res = strcspn(string,"abc");   
  printf("4) определяем длину заданного сегмента \n%d\n",res);
  /*создает новый указатель на строку для дублирования 
    строки*/
  result = strdup(string);   
  printf("5) создали новый указатель на строку \n%s\n",result);
  system("pause");
  return 0;
}

В предыдущих примерах рассматривалось присваивание указателю адреса только первого элемента символьного массива. Однако это можно делать и с адресом любого отдельного элемента массива путем добавления символа '&' к индексированному имени. Особенно удобно пользоваться этим правилом при выделении подстроки. Например, следующая программа выводит на экран часть введенной строки после первого пробела:

Пример 2.

/*Вывести на экран часть строки после первого пробела*/
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
  char s[80], *p;
  int i;
  printf("ввести строку: ");
  gets(s);
  /*найти первый пробел или конец строки*/
  for(i=0; s[i] && s[i]!=' '; i++);
  p = &s[i];
  printf(p);
  system("pause");
  return 0;
}

В этой программе p будет указывать либо на пробел, если он есть, либо на ноль, если в строке нет пробелов. Если p указывает на пробел, то программа выведет на экран его и затем остаток строки. Например, если ввести фразу <язык программирования С++>, функция printf() напечатает сначала пробел и затем <программирования С++>. Если p укажет на ноль, то на экран ничего не выводится.

Пример 3:

//Выводит каждое отдельное слово и подсчитывает его длину
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[]){
  char text[100],*p, *razd=" .,";
  int dlina;
  puts ("Введите текст ");
  gets(text);
  p=strtok(text,razd); // Выделение первого слова текста
  while (p) {  // Пока можно выделить слово
    dlina=strlen(p); // Определение длины слова
    cout << "\n слово "<< p << " длина = " << dlina <<"\n";
    p=strtok(NULL,razd); 
    //Выделение второго, третьего, и т.д. слов
  } 
  system("pause");
  return 0;
}

При использовании строк или указателей на строки в качестве параметров функций следует учитывать некоторые особенности.

При передаче строки как параметра функции не указывается длина, так как ограничителем является символ конца строки.

Строки передаются в функции в качестве параметров как массивы символов или как указатели типа char.

При побайтовом копировании строки или ее подстроки без использования стандартных функций формируемую строку следует завершить, дописав символ конца строки. В противном случае строка не воспринимается как единое целое, а при выходе за ее границы доступными становятся байты, содержащие "мусор", то есть непредсказуемую информацию.

Обращение к строкам через указатели позволяет вносить и сохранять изменения, записанные в адресуемой области памяти. Для недопущения изменений в строке указатель на константу можно объявить с лексемой const следующим образом: const char *p;.

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

При копировании строки или подстроки с использованием указателя не создается физической копии значений элементов. Объявленный новый указатель адресует то место в памяти, с которого начинается копируемая строка или подстрока. Например:

char text[50]="Язык программирования";
char *p=text, *pp;
//объявление и инициализация указателя р адресом строки text
pp=p;
//указатель рр адресует ту же строку text

Адресация на тот же участок памяти объясняется, во-первых, неэффективностью повторного хранения уже имеющихся данных, во-вторых, относительной программной трудоемкостью копирования байтов, в-третьих, для хранения адреса строки требуется гораздо меньше места, чем для самой строки. В данном контексте понятие эффективности носит относительный характер, так как иногда в программе полезным бывает хранение резервной копии введенных данных.

Ключевые термины

Адрес строки – это указатель на блок непрерывной области памяти, с которого начинает располагаться массив символов.

Строки как параметры функций – это описание передачи значений строк в функции как массив символов или указатель типа char.

Указатель на строкуадрес начала расположения строки в памяти.

Краткие итоги

  1. В силу специфики представления строк в виде символьного массива сами строки, строковые константы, заключенные в кавычки, и указатели на строки обрабатываются эквивалентно.
  2. Строки передаются в функции в качестве параметров как массивы символов или как указатели типа char.
  3. Обращение к конкретному элементу строки можно осуществить посредством адресации индексированного имени строки.
  4. При формировании строки без использования стандартных функций требуется дописывать символ конца строки.
  5. С помощью указателей на константы можно защитить строку от изменений.
  6. Копирование строк с помощью указателей осуществляется через объявление нового указателя, адресующего область памяти, занимаемую строкой или подстрокой.
< Лекция 9 || Лекция 10: 12 || Лекция 11 >
Денис Курбатов
Денис Курбатов
Владислав Нагорный
Владислав Нагорный

Подскажите, пожалуйста, планируете ли вы возобновление программ высшего образования? Если да, есть ли какие-то примерные сроки?

Спасибо!