Последние новости

YoungCoder теперь и на Stepikе. Записывайтесь: https://vk.cc/75rISy

Чтобы записаться на курс, необходимо зарегистрироваться на Степике: https://vk.cc/75rIC4

Это моя личная ссылка-приглашение на Stepik для вас. Регистрируясь по этой ссылке, записываясь на курсы и решая задачи, Вы помогаете автору данного сайта принять участие в конкурсе платформы Stepik! Подробности конкурса здесь: https://vk.cc/75rKuS

воскресенье, 11 августа 2013 г.

Урок 15. Некоторые стандартные функции работы со строками.


Всем доброго дня.
Продолжаем изучать строки. Сегодня у нас праздник. Почему? Да просто мы познакомимся с новым заголовочным файлом – string.h. Нетрудно сообразить, что в нём описываются стандартные функции, предназначенные для работы со строками.  Естественно не следует забывать, что для использования этих функций необходимо подключить этот заголовочный файл. Я надеюсь вы не забыли как это делается.

Прочитайте улучшенную версию этого урока "Стандартные функции работы со строками".

В новой версии:

  • Ещё более доступное объяснение
  • Дополнительные материалы
  • 8 задач на программирование с автоматической проверкой решения


Функция strlen().

В практическом задании к прошлому занятию, я просил вас написать  программу, которая вычисляет длину строки без учета нулевого элемента.  Длина строки - это один из самых важных параметров, характеризующих любую строку, и необходимый при работе со строками.  Для определения длины строки в заголовочном файле string.h описана функция strlen().
Данная функция имеет простой синтаксис. Она принимает один параметр строку символов, и возвращает в результате своей работы целое число - длину этой строки.
Листинг 15.1
#include <stdio.h> 
#include <string.h> 
int main(void) { 
      char str[]="Hello world"
      int n=strlen(str); 
      printf("Dlina stroki %d simvolov\n",n); 
return(0);
}
Рис.1 Программа, иллюстрирующая работу функции strlen().

Как видите ничего неожиданного, функция вернула в результате своей работы число 11.
Теперь, на основании знаний, полученных на прошлом занятии, объясните результат работы следующей программы.
Листинг 15.2
#include <stdio.h> 
#include <string.h> 
int main(void) { 
      char str[100]; 
      fgets(str,100,stdin); 
      int n=strlen(str); 
      printf("Dlina stroki %d simvolov\n",n);
return(0); 
}

Рис.2. Иллюстрация работы программы Листинг 15.2
Почему, когда мы ввели Hello world и нажали Enter, наша функция вернула нам число 12, а не 11 как в прошлом случае?

Функции сравнения строк.

Еще одной задачей, предложенной для решения в прошлом занятии, было написание программы, которая посимвольно сравнивает между собой две строки.  Для выполнения этой операции, тоже существует готовая функция –strcmp().
Данная функция принимает в качестве аргументов две строки, которые необходимо сравнить. В результате своей работы, если строки одинаковые, он возвращает нуль, и если разные, то либо целое число положительное или отрицательное. Сравнение идет по коду символов в таблице ASCII.
Рассмотрим пример.
Листинг 15.3
#include <stdio.h> 
#include <string.h> 
int main(void) { 
       char  str1[] = "hello world",
             str2[] = "hello world"
             str3[] = "hello World"
       int n12 = strcmp(str1,str2); 
       int n13 = strcmp(str1,str3); 
       int n31 = strcmp(str3,str1); 
       printf(" %s i %s %d\n", str1, str2,n12); 
       printf(" %s i %s %d\n", str1, str3,n13); 
       printf(" %s i %s %d\n", str3, str1,n31); 
       printf("%c/%d\n",str1[6],str1[6]); 
       printf("%c/%d\n",str3[6],str3[6]);
return(0); 
}
Результат работы данной программы:
Рис.3. Сравнение строк функцией strcmp()

 
Строки str1 и str2 одинаковые и потому, при их сравнении получилось 0. А вот строки str1 и str3 различаются, регистром символа ‘w’ поэтому результат их сравнения не равен нулю. Обратите внимание, что в одном случае он равен единице, а в другом минус единице. Почему так получается, мы сейчас разберемся.
Строки сравниваются посимвольно, использую соответствие между символом и его кодом в таблице ASCII.  Ниже сравнения, в нашей программе указаны коды символов ‘w’ и ‘W’.  Как видите, код символа ‘w’ –  119, больше чем код символа ‘W’ – 87. Значит и строка str1 больше чем строка str3.

Основное правило:  Если, в функции strcmp() строка записанная в первом аргументе, больше чем строка во втором аргументе, то функция возвращает положительное число.  Если меньше – отрицательное.
Есть и еще одна функция, предназначенная для сравнения строк strncmp(). Её отличие лишь в том, что добавляется третий параметр – целое число, указывающее, сколько символов с начала строки необходимо сравнить.
Немного преобразуем предыдущую программу
Листинг 15.4
#include <stdio.h> 
#include <string.h> 
int main(void) { 
       char  str1[] = "hello world"
             str2[] = "hello World"
       int n1 = strncmp(str1,str2,6); 
       int n2 = strncmp(str1,str2,7); 
       printf("%s i %s %d\n", str1, str2,n1); 
       printf("%s i %s %d\n", str1, str2,n2);
return(0);
}

Рис.4. Сравнение частей строк, с помощью функции strncmp().
Как видите, когда мы сравнили первые шесть символов двух строк, то получили 0, так как они совпадают. Если же мы сравниваем первые семь символов, то первая строка больше второй, и в ответе получается положительное целое число. Причем в данном случае, это разность между кодами соответствующих символов (119-87 = 32). Пользоваться этим обстоятельством нужно очень осторожно. Не факт, что в других средах разработки, эти функции реализованы точно таким же образом. Т.е. может быть, что где-то strcmp будет тоже возвращать  32, а не 1, как в нашем примере. А где-то возможно strncmp не будет возвращать 32. Как это реализовано в вашей среде программирования проверьте самостоятельно.   

Функции изменения регистра строки.

Как вы помните, в задаче к прошлому уроку требовалось написать функцию, которая переводит все символы строки в нижний регистр. Для этой задачи тоже есть готовая функция – strlwr().  Ко всему прочему имеется и функция, которая переводит все символы в верхний регистр – strupr().
Данные функции принимают один параметр – строку, которую необходимо перевести в тот или иной регистр. Рассмотрим пример их использования.
Листинг 15.5
#include <stdio.h> 
#include <string.h> 
int main(void) { 
      char str[] = "HeLLo WoRlD"
      printf ("%s\n",str); 
      strlwr(str); //переводим строку в нижний регистр
      printf ("%s\n",str); 
      strupr(str); //переводим строку в верхний регистр
      printf ("%s\n",str);
return(0);
}
Результат работы программы
Рис.5. Изменение регистра строки функциями strupr() и strlwr().

Функции объединения строк.

В файле string.h описаны две функции для объединения строк.
Первая strcat() принимает две строки, и приписывает вторую в конец первой. Т.е. результат склеивания двух строк окажется в той, что записана в первом аргументе. Причем нулевой символ ‘\0’ добавляется автоматически в конец новой, получившейся строки.  Небольшой иллюстрирующий пример:
Листинг 15.6
#include <stdio.h> 
#include <string.h> 
int main(void) { 
      char  str1[50] = "hello"
            str2[]="world"
      strcat(str1," "); //приклеиваем к str1 пробел получаем
                        //в str1 строку "hello "
      strcat(str1,str2);//приклеиваем к str1 строку str2 
      printf("%s\n", str1); //выводим str1
return(0); 
}
Рис.6. Склеивание двух строк функцией strcat().

Вторая функция strncat() отличается от предыдущей, наличием еще одного аргумента, означающего, какое количество символов с начала второй строки следует приклеить к первой строке. Немного переделаем наш предыдущий пример.
Листинг 15.7
#include <stdio.h> 
#include <string.h> 
int main(void) { 
      char  str1[50] = "hello"
            str2[]="world"
      strcat(str1," "); //приклеиваем к str1 пробел получаем                              //в str1 строку "hello "
      strncat(str1,str2,3); //приклеиваем к str1 3 первых                                     //символа из str2

      printf("%s\n", str1); //выводим str1

return(0);
}

Ну и соответственно результат её работы.
Рис.7. Использование функции strncat().


Ничего удивительного. Все работает именно так, как и ожидалось.
При работе с этими двумя функциями стоит внимательно следить за тем, чтобы в строке, к которой мы приклеиваем, хватило места, иначе произойдет ошибка переполнения. С ней мы уже сталкивались с прошлом занятии. Вот попробуйте выполнить следующую программу.
 Листинг 15.8
#include <stdio.h> 
#include <string.h> 
int main(void) { 
      char  str1[10] = "hello"
            str2[]=" world"
      strcat(str1,str2); 
      printf("%s\n", str1); 
      return(0);
}

Хотя программа и скомпилируется, но при выполнении возникнет ошибка.
На этом сегодняшний урок мы закончим. Мы рассмотрели лишь некоторые функции, описанные в заголовочном файле string.h. Есть там еще несколько очень интересных и полезных функций, но о них мы поговорим чуть позже, когда познакомимся с указателями.  

Отдельного практического задания к этому уроку не будет.  Проверьте с помощью стандартных функций программы, написанные к прошлому занятию. А 3,4 и 5 задачи перепишите с использованием стандартных функций.


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

9 комментариев :

  1. решал задачку с перевёртышами из прошлого урока. возник вопрос

    #include "stdio.h"
    #include "string.h"
    int main(void) {
    char str1[100],str2[100];
    fgets(str1,100,stdin);
    strlwr(str1);

    str2[100]=str1[100];

    printf("%s\n", str2);
    return(0);


    }

    почему при выводе показателя str2, который я до этого приравнял к str1, появляется "мусор"?

    ОтветитьУдалить
    Ответы
    1. Потому что, вот так просто нельзя копировать строки, к сожалению. =))) Тут нужно либо посимвольно с использование цикла, либо специальными функциями пользоваться.

      Удалить
  2. В листинге 15.5 комментарии поменять местами надо)

    ОтветитьУдалить
    Ответы
    1. И действительно. Спасибо за бдительность! )

      Удалить
  3. А мне программа из листинга 15.2 при вводе Hellow World выдает -1098753604. Это норма?

    ОтветитьУдалить
  4. Переписывал задание 5 прошлого урока при помощи изученных функций. Возник вопрос, почему ответ выводится не на экран а в файл "in.txt" и почему выводит ответ, что строка состоит из 0 символов.

    #define _CRT_SECURE_NO_WARNINGS
    #include
    #include
    char fun1(char arr[]);
    int main(void)
    {
    char str1[200];
    fun1(str1);
    char mass[28] = { 0 }, c = 0;
    freopen("D:\\in.txt", "r", stdin);
    while (c = getchar())
    {
    if (c == EOF) break;
    mass[27]++;
    if (c == 32) mass[26]++;
    if (c > 96 && c < 123) mass[c - 97]++;
    }
    printf("dlina stroki - %d\n", mass[27]);
    printf("kolichestvo probelov - %d\n", mass[26]);
    for (int i=0; i < 26; i++)
    if (mass[i] > 0) printf("%c - %d\n", i + 97, mass[i]);
    return(0);
    }
    char fun1(char arr[])
    {
    freopen("D:\\input.txt", "r", stdin);
    gets(arr);
    freopen("D:\\in.txt", "w", stdout);
    _strlwr(arr);
    puts(arr);
    return (0);
    }

    ОтветитьУдалить
  5. в последнем я так понял ошибка вылезет потому что str1[10], это при том что символов выйдет 11. думаю я прав, компилировать правда не стану

    ОтветитьУдалить
  6. Очень понятно написано!
    Спасибо!

    ОтветитьУдалить
    Ответы
    1. Пожалуйста. В новой версии сайта youngcoder.ru всё ещё понятнее. Заходите.

      Удалить

Примечание. Отправлять комментарии могут только участники этого блога.