4311

Строки в языке Си

Контрольная

Информатика, кибернетика и программирование

Строки В языке С отсутствует строковый тип, работа со строками организована путем использования одномерных массив типа char. Строка в С – это массив символов, заканчивающийся нулевым байтом. Каждый символ строки размещается в отдельном ба...

Русский

2012-11-16

63 KB

11 чел.

Строки

В языке С отсутствует строковый тип, работа со строками организована путем использования одномерных массив типа char.

Строка в С – это массив символов, заканчивающийся нулевым байтом. Каждый символ  строки размещается в отдельном байте.

Нулевой байт – это байт, каждый бит которого равен нулю. Для нулевого байта определена специальная символьная константа ‘\0’. Это следует учитывать при описании соответствующего массива символов. Если строка должна содержать n символов, то в описании массива следует указать n+1 элемент.

Например при описании массива

char name  [20];

следует учитывать, что строка сможет содержать не более 19 символов, а последний байт зарезервирован под нулевой байт. Если при вводе в массив name  было введено меньше 19 символов, элементы массива, следующие за нулевым байтом, будут содержать случайные значения. Пусть например, в массив name было введено имя Александр, тогда в девяти байтах будут размещены символы, составляющие имя, десятый байт – это нулевой байт, и 10 байт окажутся заполнены случайными значениями. На рис 1. показано размещение массива name  в памяти.

А

л

е

к

с

а

н

д

р

‘\0’

                Рис. 1. Размещение массива name в памяти.

Инициализация строк

Инициализация строк может выполняться так, же как и инициализация одномерного массива – с помощью списка констант например:

char  str[ ]  =  {‘П’ , 'р', 'и','в','е','т',’\0’};

Однако для строк существует более удобный способ инициализации – с помощью строковой константы, например:

char  str[ ]  = “Привет”;

При использовании любого из этих способов инициализации компилятор подсчитывает количество символов и в соответствии с этим определяет размер массива.

Ввод – вывод строк

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

Для ввода строк существует специальная функция  gets(), которая читает строку, пока не будет нажата клавиша Enter.  Функция gets() позволяет ввести строки, содержащие пробелы.

Строку можно ввести и с помощью функции scanf(), используя спецификацию формата %s. Функции scanf() вводит символы до первого пробела. Обе функции автоматически ставят в конце строки нулевой байт.

Для вывода строк можно использовать функции     printf() и   puts()

В примере 1 показана программа, выполняющая ввод-вывод строк. Обе функции выводят содержание массива до первого нулевого байта.

Пример  1.  Ввод  - вывод строк.

#include <stdio.h>
            #include <conio.h>
              void main(void)

 {

//объявление строки как массива
 
char str[80];                                                    //зарезервировали место в памяти под строку

   clrscr();

  printf("Введите строку длиной менее 80 символов: ");

  gets(str);                                                //читает строку с клавиатуры, пока не нажата Enter

//вывод строки с помощью функции printf по спецификации %s

   printf("Вы ввели строку %s\n",str);

   printf("Введите еще одну строку длиной менее 80 символов: ");

   scanf("%s",str); //читает строку с клавиатуры, пока не  встретится пробел

   printf("Вы ввели строку %s\n",str);

//вывод строки с помощью функции puts

   puts(str);

   getch();

   }

Объединение двух строк

 Процесс объединения двух строк состоит в том, что символы, содержащиеся в одной строке, добавляются в конец другой. Этот процесс называется конкатенацией (concatenation). Для выполнения объединения двух строк следует организовать цикл, в котором анализируются символы  первой строки, пока не будет найден нулевой байт и сдвигается текущий индекс элемента массива на конец строки. Затем, во втором цикле, который исполняется, пока не найден нулевой байт второй строки, символы из второй строки копируются в конец первой.  В примере 2 показана программа, выполняющая конкатенацию строк.

Пример 2.  Объединение двух строк: к концу одной строки дописывается вторая и результат выводится

                
#include <conio.h>
                #include <stdio.h>

      void main(void)
                  {
                        char s[80], t[80];
                                 //резервирование места в памяти под строки

            int i=0,j=0;

            clrscr();

             puts("Введите первую строку ");

             gets(s);

             puts("первая строка");

             puts(s);

             puts("Bведите вторую строку ");

             gets(t);

             puts("вторая строка");

             puts(t);

//цикл выполняется, пока не будет найден  нулевой байт - конец первой строки

       while(s[i] != '\0')

       {

//сдвигаем текущий индекс элемента первой строки на ее конец   

        i++;

        }

//в этом цикле к концу первой строки дописывается вторая  цикл выполняется, пока не найден //конец второй строки

  while(t[j] != '\0')

   {

       s[i]=t[j];  //дописываем к первой строке символы второй

        i++;

        j++;

     }

 s[i]= '\0';                                           //дописываем нулевой байт к результирующей строке

  puts("результат:");

   puts(s);

  }

Сравнение двух строк

В С нельзя непосредственно сравнивать значения двух строк с помощью, например, такого условия:

      if (str1 = = str2)

Для сравнения двух строк можно воспользоваться библиотечной функцией strcmp(). Эта функция возвращает нулевое значение, если строки совпадают и ненулевое значение при несовпадении строк.

В примере 3 показана программа, в которой используется функции strcmp() для сравнения двух строк. Эта программа не всегда может давать правильный результат, особенно при сравнении строк, содержащих русские буквы. В примере 4 показано, как можно написать собственную программу для выполнения посимвольного  сравнения двух строк.

Пример 3. Сравнение двух строк с помощью библиотечной функции strcmp().

#include <stdio.h>     
           #include <string.h>
         //для функции strcmp()

void main(void)

{

       int flag=0;

       char name[10],  name1[10];

       clrscr();

       puts( "Введите первую строку" );

       gets( name );

       puts( "Введите вторую строку" );

       gets( name1 );

      if( strcmp( name, name1 ) == 0 )

       flag=0;

       else flag=1;

     if(flag==1)

     puts("Строки не совпадают");

      else

      puts("Строки  совпадают");

      }

Пример 4. Сравнение двух строк с помощью собственной программы.

     #include <stdio.h>

      void main(void)

      {

int  index,  flag=0;

char name[10], name1[10];

puts("Введите первую строку");

gets(name);

puts("Введите вторую строку");

gets(name1);

 for(index=0;  name[index]!= '\0';  index++)

  if(name[index] != name1[index])

   {

       flag=1;

       break;

     }

   if(flag==1)

   puts("Строки не совпадают");

   else

    puts("Строки  совпадают");

    getch();

   }


Примеры программ

Пример 1. Программа, распечатывающая  введенную строку символов, удалив из нее символы  * и удвоив  символы A. Программа выполняет анализ вводимых символов и записывает их в строку str.  Если введенный символ * - то он не заносится в строку str, а если введенный символ – A или а, то в строку str он записывается дважды. Затем полученная строка выводится.

// Можно обойтись без массива, если в цикле WHILE

// сразу осуществлять вывод нужных символов

//    while((getchar())!='\n')

// { if(ch=='*')

//    continue;    // если * -начать цикл заново,т.е. прочесть нов сим

//   if(ch=='A' || ch=='a')putchar(ch);

//    putchar(ch);

//  }

#include <stdio.h>

 void main(void)

 {

   int i,k=0;

   char str[80],ch;

   puts("\nВведите строку символов");

   while((ch=getchar())!='\n')

 {

if(ch=='*')

   continue;    // если * -начать цикл заново, т.е. прочесть нов символ

  if(ch=='A' || ch=='a')

   str[k++]=ch;

   str[k++]=ch;

   }

   for(i=0; i<k; i++)

   putchar(str[i]);

   }

Пример 2. Переворот символьной строки S (символы  строки располагаются в обратном порядке). Перевернутая строка располагается в той же области памяти, т.е. дополнительный массив не заводится.
                  
#include <stdio.h>
                  #include <conio.h>

     #define MAXLINE 1000 //макс. размер входной строки

  void main(void)

  {

       char s[MAXLINE]; //текущая строка ввода

       int i,j;

       char temp;  //для хранения одного символа строки

       i=0;

       clrscr();

     puts("Введите строку");

     gets(s);

     while(s[i] !='\0')             //ищем конец строки

       ++i;                     //увеличиваем на единицу количество найденных в строке символов

     --i;                //смещаемся назад от '\0' - признака конца строки

      j=0;             //начало перевернутой строки

      if(s[i]=='\n')  //если в строке присутствует символ новой строки

          --i;                        //смещаемся назад от признака новой строки

      while(j<i)       //j - индекс первого символа строки, i-последнего

      {  

// в процессе обмена символов j увеличивается (продвигается

   // к концу строки, а i уменьшается (движется к началу)

   temp=s[j]; // запоминаем символ в начале строки в дополнителной переменной

             s[j]=s[i];     //обмениваем символы

              s[i]=temp;

     --i;           //движемся к началу строки

               ++j;          //движемся к концу строки

 }

 // выводим перевернутую строку

 puts("  Перевернутая строка");

 puts(s);

 getch();

 }

Пример 3.  Программа, выполняющая копирование строки s1 в строку s2

# include <stdio.h>

 void main(void)
 {
      char s1[80],s2[80];
      int i;

      puts("введите исходную строку");

// цикл, в котором строка вводится посимвольно в массив

// выполнение цикла заканчивается, если была нажата клавиша Enter

      for(i=0;i<80;i++)

      {

            scanf("%c",s1+i);

            if(s1[i] =='\n')

            break;

       }

     s1[i]='\0';

     puts("Исходная строка");

     puts(s1);

     i=0;

//копируем строку s2  в строку s1

      while((s1[i])!='\0')

     {

          s2[i]=s1[i];

          i++;

      }

   s2[i]='\0';
   puts("
Скопированная строка" );
    puts(s2);
    }

Пример 3. Обьединение двух строк к концу строки s дописывается строка t, вычисляется длина полученной строки.  Память под строки распределяется динамически.

#include <alloc.h>

#include <stdio.h>

void main(void)

{

   char *t, *s;                         //объявление указателей на данные типа char

   int i=0;

//динамическое распределение памяти под строки

   s=(char *)malloc(160);

   t=(char *)malloc(80);

   puts("Введите первую строку ");

   gets(s);

   puts("первая строка");

   puts(s);

   puts("Bведите вторую строку ");

   gets(t);

   puts("вторая строка");

   puts(t);

while(*s != '\0')         //выполнять, пока не найден конец первой строки

   {

       i++;

       s++;                         //сдвигаем указатель в конец первой строки

    }

while(*t != '\0')          //выполнять, пока не найден конец второй строки

    {

        *s++ = *t++;         //дописываем символы второй строки к первой
        
             i++;

     }

  *s='\0';                              //дописываем нулевой байт к концу результирующей строки

    printf("длина результирующей строки i=%d\n", i);

while(--i >= 0)                           //сдвигаем указатель в начало результирующей строки

    {

         s--;

     }

    puts("результат:");

    puts(s);

}

Пример 3.  Программа, в которой используются указатели на строки.

#include <stdio.h>

void main(void)

{

char s[]="строка как массив";

char *ps=s                                  //указатель ps инициализирован значением адреса строки s

char *ps1,*ps2,*ps3;                //объявление указателей на строки

ps1="В языке  си в одну\n"  //присвоение указателю ps1 адреса строковой константы

        "строку можно записать\n"

       "целое стихотворение\n";

ps2="предложение не будет\   //присвоение указателю ps2 адреса строковой константы

         перенесено на следующую строку";

ps3="одна"         //присвоение указателю ps3 адреса строковой константы

       " строка";

//цикл вычисления длины строки s, адрес которой хранит указатель ps. Выполнять, пока не найден конец строки

while(*ps != '\0')

     ps++;

 printf("длина строки= %d\n",ps-s);

 puts(ps1);

 puts(ps2);

 puts(ps3);

}

ЗАДАЧИ ДЛЯ РЕШЕНИЯ

1

Напишите программу, выполняющую копирование одной строки в другую. Для работы со строками используйте указатели.

2

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

3.

Создайте функцию is_within(), которая принимает в качестве аргументов символ и указатель строки. Функция должна возвращать ненулевое значение ("истинно"), если символ присутствует в строке, и нуль ("ложно"), в противном случае.


 

А также другие работы, которые могут Вас заинтересовать

17568. Алгоритм RSA. Обмен ключами симметричных алгоритмов с использованием ассиметричных криптосистем 189 KB
  Лабораторная работа № 3.2 Тема: Алгоритм RSA. Обмен ключами симметричных алгоритмов с использованием ассиметричных криптосистем. Цель: Ознакомиться с математическими принципами функционирования алгоритма RSA. Научиться проводить шифрование/дешифрование с помощью...
17569. Поведение важнейших окислителей и восстановителей. Прогнозирование продуктов окислительно-восстановительных реакций 821 KB
  Перманганат-ион выступает окислителем в любой среде, от рН среды зависит продукт восстановления перманганата-иона. Кислую среду создают серная, азотная, соляная и другие сильные кислоты, раствор сернистого газа. Азотная кислота помимо создания кислой среды будет проявлять окислительные свойства
17570. Криптографические алгоритмы, которые используются для формирования подписи 2.57 MB
  Лабораторная работа № 3.4 Тема: Криптографические алгоритмы которые| используются для формирования подписи. Цель: Ознакомиться с основными методами формирования цифровой подписи. Ознакомиься с принципом функционирования метода DSA. ознакомиться с программой CrypTool.
17571. Атаки на алгоритм RSA. Взлом RSA при неудачном выборе параметров криптосистемы 600 KB
  Лабораторная работа № 4.1 Тема: Атаки на алгоритм RSA. Взлом RSA при неудачном выборе параметров криптосистемы. Цель: изучить атаки на алгоритм шифрования RSA посредством метода Ферма атаки повторным шифрованием атаки на основе китайской теоремы об остатках и метода к
17572. Использование криптографического интерфейса Windows при разработке приложений. Создание приложений для создания ключей и ключевого материала 2.41 MB
  Лабораторная работа № 4.2 Тема: Использование криптографического интерфейса Windows при разработке приложений. Создание приложений для создания ключей и ключевого материала. Обмен ключами. Функции CryptoAPI для работы с ключевым материалом. Цель: изучить принципы построе...
17573. Использование криптографического интерфейса Windows при разработке приложений. Шифрование и дешифрование данных 1.22 MB
  Лабораторная работа № 4.3 Тема: Использование криптографического интерфейса Windows при разработке приложений. Шифрование и дешифрование данных. Формирование и проверка ЭЦП. Управление доступом к контейнеру ключей. Цель: изучить принципы построения и использования Cr...
17574. Защита на уровне IP 13.27 MB
  Лабораторная работа № 4.4 Тема: Структура отчета Титульный лист. Тема и цель работы. Задание и номер варианта. Краткие теоретические сведения. Ход работы. Выводы. Теоретические сведения Защита на уровне IP Cообщество Internet разработало...
17575. Исследование регистрового файла микроконтроллера PIC 16C71 26.5 KB
  Лабораторна работа № 1 Тема: Исследование регистрового файла микроконтроллера PIC 16C71 Знакомство со средой MPLAB Цель работы: Ознакомиться с программной средой MPLAB. Краткие теоретические сведения: При помощи MPLAB можно редактировать эм
17576. Дослідження арифметико-логічних команд РІС – контролера 136 KB
  Лабораторна робота № 2 Дослідження арифметикологічних команд РІС контролера Множення без знакових чисел Мета роботи: Вивчення алгоритму множення без знакових чисел та його реалізація за допомогою системи команд периферійного РІС контролера у програмному ...