Сайт о телевидении

Сайт о телевидении

» » Сравнение строк в си. Ввод и вывод символьных строк в си

Сравнение строк в си. Ввод и вывод символьных строк в си

Программист говорит:

Здравствуйте! Я прочел вашу статью. Мне было очень грустно и одновременно смешно. Особенно убивает эта ваша фраза: «Так как переменную типа char часто используют как массив, то определяют количество возможных значений». 😆 😆 😆
Я не смеюсь над вами. Создание сайта это действительно подвиг. Я лишь хочу поддержать вас советом и указать несколько ошибок.

1. Значение переменной типа char присваивается так:

Вот здесь:

Char a = *"A";

Происходит разадресация указателя на массив и в результате возвращается значение первого элемента массива т.е. ‘A’

2. Обнуление происходит так:

Char a = NULL;
char b = {};

//А так очищается строка в теле программы

"" -- этот символ называется ноль-терминатор. Он ставится в конце строки. Вы сами того не зная заполнили этим символом массив s1 из вашей статьи. А ведь можно было присвоить этот символ только нулевому элементу массива.

3. Смело пользуитесь терминологией.
Знак = это операция присваивания.
Знак * операция разадресации.
Я имею в виду вот этот фрагмент статьи: "Настолько всё оказалось просто, перед знаком = нужно было поставить знак * и нужно было объявить номер элемента (ноль соответствует первому)"

Поймите меня правильно, статья в нынешнем виде не может существовать. Не поленитесь, перепишите ее.
На вас лежит большая ответственность! Я серьезно. Страницы вашего сайта попали в первую страницу выдачи Яндекса. Много людей уже начали повторять за вами ошибки.

Удачи! Вы справитесь!

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

Я буду рад исправить и другие ошибки. поправить неточности, если они выскочат. Я ценю вашу помощь. спасибо.Я это давно знаю, просто трудно перечитывать 200 статей постоянно, чтобы что-то исправить. А некоторые грубые типы так пишут, что даже зная, что лучше исправить, исправлять совсем не охота.
С вашим char b = {}; Это не обнуление совсем. проверили бы хотя б.
если говорить о нулевом символе "" ; Я хорошо знал, когда заполнял им строку и цель была в том, чтобы показать настоящее очищение, а не видимое на глаз, ибо в строку входит мусор, который иногда мешает. Вы бы с терминами сами поаккуратнее, "символ нуль-терминации" или просто "нулевой символ", не терминатор))) А символ-терминатор звучит просто круто.

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

Я буду рад исправить и другие ошибки. поправить неточности, если они выскочат. Я ценю вашу помощь. спасибо.

Здравствуйте еще раз!
Хочу пояснить. Термином "ноль-терминатор" (terminator с англ. ограничитель) пользовался мой преподаватель в ВУЗе. Видимо это old school!
Что касается обнуления строк.
char b = {}; Это действительно обнуление. Весь массив заполнен нулями. Не верите -- проверьте!
Если рассматривать строку в её естественном, бытовом смысле, то "пустой" будет та строка в которой нет ни одного символа. Поэтому в 99.9% случаев достаточно поставить в начало нулевой символ. Обычно обработка строки идет до первого нулевого символа а какие символы идут за ним уже не важно. Я понимаю что вы хотели обнулить строку. Просто решил предложить проверенный временем классический вариант.

:
Когда "Обычно обработка строки идет до первого нулевого символа а какие символы идут за ним уже не важно" - да, строка обнуляется
Если рассматривать "реальное обнуление всех ячеек строки (о котором писал я)" - нет, не обнуление и, даже, первый символ не нулевой. Я этим вариантом проверял. MinGW(CodeBlock) - весь массив отдает символ "a"
не думаю, что это повод для споров.

Объявление строк

Строка в языке Си представляет собой одномерный массив символов, последним элементом которой является символ конца строки – нуль (строка, завершающаяся нулем, то есть NULL terminated string).

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

Первый способ:

Объявления массива символов (не забудьте добавить место для завершающего нуля):

Char s;

Второй способ:

Присвоить строковой переменной начальное значение (при этом длину строки компилятор может вычислить сам):

Char s = "Пример инициализации строки";

Справа от знака присваивания записана строковая константа. В конце строки автоматически добавляется ноль (‘\0’). Константы символьных строк помещаются в класс статической памяти.

Третий способ:

Неявное указание, что используется массив. В левой части от знака присваивания указывается указатель на символ:

Char *s="Второй вариант инициализации";

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

Char *s;

Ввод строки со стандартного устройства ввода (клавиатуры)

Для работы со строками есть набор функций. Для ввода со стандартного устройства ввода (клавиатуры) чаще всего используются библиотечные функциями из модуля стандартного ввода-вывода: scanf и gets .

Для ввода строки с помощью функции scanf , использует формат «%s » , причем обратите внимание на то, что перед идентификатором строки не используется знак адреса «& » , так как одномерный массив уже представлен указателем на его начало:

Scanf("%s", s);

Функция gets() считывает символы до тех пор, пока не достигнет символа перехода на новую строку. Функция принимает все символы вплоть до символа перевода строки, но не включает его. К концу строки добавляется завершающий ноль (‘\0’). Функция gets() помещает считанную с клавиатуры последовательность символов в параметр типа строка и возвращает указатель на эту строку (если операция завершилась успешно), или NULL (в случае ошибки). В приведенном ниже примере при успешном завершении операции, на экран будет выведено две одинаковые строки:

#include int main() { char s; char *p; p=gets(s); printf(" \n Введена строка %s. ",s); if (p) printf(" \n Введена строка %s. ",p); return 0; }

Попутно заметим, что функция gets часто используется для ввода лю-бых данных с клавиатуры в виде строки с целью дальнейшего преобразования функцией sscanf к нужному формату или для предварительного анализа вводимых данных, например:

#include #include #include int main() { char s; int x, err; do { printf(" \n Введите целое число -> "); gets(s); err=sscanf(s, "%d",&x); if (err!=1) printf(" \n Ошибка ввода. "); } while (err!=1); printf("\n Введено целое число -> %d", x); return 0; }

Вывод строк на стандартное устройство вывода (экран монитора)

Для вывода строк на стандартное устройство вывода (экран монитора) можно использовать две функции printf и puts . В функции printf в качестве формата передается «%s». Удобство использования этой функции заключается в том, что помимо строки можно сразу выводит данные других типов. Особенность функции puts заключается в том, что после вывода строки автоматически происходит переход на следующую строку.

Функции для работы со строками

Для преобразования строк в языке Си предусмотрена библиотека string. Каждая из функций имеет свой формат записи (прототип).

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

Пример программ(листинг) работающей со строками

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

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

В языках С и C++ печатаемыми являются символы, отображаемые на терминале. В ASCII-средах они расположены между пробелом(0x20) и тильдой(OxFE). Управляющие символы имеют значения, лежащие в диапазоне между нулем и Ox1F; к ним также относится символ DEL(Ox7F).

Исторически сложилось так, что аргументами символьных функций являются целые значения, из которых используется только младший байт. Символьные функции автоматически преобразуют свои аргументы в тип unsigned char. Безусловно, вы вольны вызывать эти функции с символьными аргументами, поскольку символы автоматически возводятся в ранг целых в момент вызова функции.

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

В версии С99 к некоторым параметрам нескольких функций, первоначально определенных в версии С89, добавлен квалификатор restrict. При рассмотрении каждой такой функции будет приведен ее прототип, используемый в среде С89(а также в среде C++), а параметры с атрибутом restrict будут отмечены в описании этой функции.

Список функций

Проверка на принадлежность

isalnum - Проверка на принадлежность символа к алфавитно-цифровым
isalpha - Проверка на принадлежность символа к буквам
isblank - Проверка пустого символа
iscntrl - Проверка на принадлежность символа к управляющим
isdigit - Проверка на принадлежность символа к цифровым
isgraph - Проверка на принадлежность символа к печатным но не к пробелу
islower - Проверка на принадлежность символа к строчным
isprint - Проверка на принадлежность символа к печатным
ispunct - Проверка на принадлежность символа к знакам пунктуации
isspace - Проверка на принадлежность символа к пробельным
isupper - Проверка на принадлежность символа к прописным
isxdigit - Проверка на принадлежность символа к шестнадцатеричным

Работа с символьными массивами

memchr - Просматривает массив чтобы отыскать первое вхождение символа
memcmp - Сравнивает определённое количество символов в двух массивах
memcpy - Копирует символы из одного массива в другой
memmove - Копирует символы из одного массива в другой с учётом перекрытия массивов
memset - Заполняет определённое количество символов массива заданным

Манипуляции над строками

strcat - Присоединяет копию одной строки к заданной
strchr - Возвращает указатель на первое вхождение младшего байта заданного параметра
strcmp - Сравнивает в лексикографическом порядке две строки
strcoll - Сравнивает одну строку с другой в соответствии с параметром setlocale
strcpy - Копирует содержимое одной строки в другую
strcspn - Возвращает строку в которой отсутствуют заданные символы
strerror - Возвращает указатель на строку содержащую системное сообщение об ошибке
strlen - Возвращает длину строки с завершающим нулевым символом

Теги: Си строки. Char array.

Строки в си. Введение.

Э то вводная статья по строкам в си. Более подробное описание и примеры будут, когда мы научимся работать с памятью и указателями. В компьютере все значения хранятся в виде чисел. И строки тоже, там нет никаких символов и букв. Срока представляет собой массив чисел. Каждое число соответствует определённому символу, который берётся из таблицы кодировки. При выводе на экран символ отображается определённым образом.
Для хранения строк используются массивы типа char. Ещё раз повторюсь – тип char – числовой, он хранит один байт данных. Но в соответствии с таблицей кодировки каждое из этих чисел связано с символом. И в обратную сторону – каждый символ определяется своим порядковым номером в таблице кодировки.
Например

#include #include void main() { char c = "A"; int i = 65; printf("display as char %c\n", c); printf("display as int %d\n", c); printf("display as char %c\n", i); printf("display as char %d\n", i); getch(); }

Мы создали две переменные, одна типа char , другая int . Литера "A" имеет числовое значение 65. Это именно литера, а не строка, поэтому окружена одинарными кавычками. Мы можем вывести её на печать как букву

Printf("display as char %c\n", c);

Тогда будет выведено
A
Если вывести её как число, то будет
65
Точно также можно поступить и с числом 65, которое хранится в переменной типа int .
Спецсимволы также имеют свой номер

#include #include void main() { printf("%c", "\a"); printf("%d", "\a"); printf("%c", 7); getch(); }

Здесь будет сначала "выведен" звуковой сигнал, затем его числовое значение, затем опять звуковой сигнал.
Строка в си – это массив типа char , последний элемент которого хранит терминальный символ "\0". Числовое значение этого символа 0, поэтому можно говорить, что массив оканчивается нулём.
Например

#include #include void main() { char word; word = "A"; word = "B"; word = "C"; word = "\0"; //word = 0; эквивалентно printf("%s", word); getch(); }

Для вывода использовался ключ %s. При этом строка выводится до первого терминального символа, потому что функция printf не знает размер массива word.
Если в этом примере не поставить

Word = "\0";

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

#include #include void main() { char word = "ABC"; char text = {"H", "E", "L", "L", "O"}; printf("%s\n", word); printf("%s", text); getch(); }

В данном случае всё корректно. Строка "ABC" заканчивается нулём, и ею мы инициализируем массив word. Строка text инициализируется побуквенно, все оставшиеся символы, как следует из главы про массивы, заполняются нулями.

Чтение строк

Д ля того, чтобы запросить у пользователя строку, необходимо создать буфер. Размер буфера должен быть выбран заранее, так, чтобы введённое слово в нём поместилось. При считывании строк есть опасность того, что пользователь введёт данных больше, чем позволяет буфер. Эти данные будут считаны и помещены в память, и затрут собой чужие значения. Таким образом можно провести атаку, записав нужные байты, в которых, к примеру, стоит переход на участок кода с вредоносной программой, или логгирование данных.

#include #include void main() { char buffer; scanf("%19s", buffer); printf("%s", buffer); getch(); }

В данном случае количество введённых символов ограничено 19, а размер буфера на 1 больше, так как необходимо хранить терминальный символ. Напишем простую программу, которая запрашивает у пользователя строку и возвращает её длину.

#include #include void main() { char buffer; unsigned len = 0; scanf("%127s", buffer); while (buffer != "\0") { len++; } printf("length(%s) == %d", buffer, len); getch(); }

Так как числовое значение символа "\0" равно нулю, то можно записать

While (buffer != 0) { len++; }

Или, ещё короче

While (buffer) { len++; }

Теперь напишем программу, которая запрашивает у пользователя два слова и сравнивает их

#include #include /* Результатом сравнения будет число 0 если слова равны 1 если первое слово больше второго в лексикографическом порядке -1 если второе слово больше */ void main() { char firstWord; //Первое слово char secondWord; //Второе слово unsigned i; //Счётчик int cmpResult = 0; //Результат сравнения scanf("%127s", firstWord); scanf("%127s", secondWord); for (i = 0; i < 128; i++) { if (firstWord[i] > secondWord[i]) { //Больше даже если второе слово уже закончилось, потому что //тогда оно заканчивается нулём cmpResult = 1; break; } else if (firstWord[i] < secondWord[i]) { cmpResult = -1; break; } } printf("%d", cmpResult); getch(); }

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

Строки в C++

Строка - последовательность (массив) символов. Если в выражении встречается одиночный символ, он должен быть заключен в одинарные кавычки . При использовании в выражениях строка заключается в двойные кавычки. Признаком конца строки является нулевой символ \0 . В C++ строки можно описать с помощью символов (массив элементов типа char ), в котором следует предусмотреть место для хранения признака конца строки.

Например, описание строки из 25 символов должно выглядеть так:

Можно описать и массив строк:

Определен массив из 3 строк по 25 байт в каждой.

Для работы с указателями можно использовать (char * ). Адрес первого символа будет начальным значением указателя.

Рассмотрим пример объявления и вывода строк.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

#include «stdafx.h»
#include
using namespace std;
int main()
{
setlocale(LC_ALL,«Rus» ) ;
//описываем 3 строки, s3- указатель
char s2[ 20 ] , * s3, s4[ 30 ] ;
cout << «s2=» ; cin >> s2; //ввод строки s2
cout << «s2=» << s2<< endl;
//запись в s3 адреса строки, где хранится s4. Теперь в переменных
//(указателях) s3 и s4 хранится значение одного и того же адреса
s3= s4;
cout << «s3=» ; cin >> s3; //ввод строки s3
//вывод на экран строк s3 и s4, хотя в результате присваивния s3=s4;
//теперь s3 и s4 — это одно и тоже
cout << «s3=» << s3<< endl;
cout << «s4=» << s4<< endl;
system («pause» ) ;
return 0 ;
}

Результат работы программы:

Но следует отметить, что если пользователь введет в одну переменную слова разделенные пробелом, то программа будет работать иначе:

Все дело в том, что функция cin вводит строки до встретившегося пробела. Более универсальной функцией является getline .

cin.getline(char *s, int n);

Предназначена для ввода с клавиатуры строки s с пробелами, в строке не должно быть более n символов. Следовательно, для корректного ввода строк, содержащих пробел, необходимо в нашей программе заменить cin>>s на cin.getline(s, 80) .

Операции над строками

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

Для преобразования числа в строку можно воспользоваться функцией sprintf из библиотеки stdio.h .

Некоторые функции работы со строками:

Прототип функции Описание функции
size_t strlen(const char *s) вычисляет длину строки s в байтах.
char *strcat(char *dest, const char *scr) присоединяет строку src в конец строки dest, полученная срока возвращается в качестве результата
char *strcpy(char *dest, const char *scr) копирует строку scr в место памяти, на которое указывает dest
char strncat(char *dest, const char *dest, size_t maxlen) присоединяет строку maxlen символов строки src в конец строки dest
char *strncpy(char *dest, const char *scr, size_t maxlen) копирует maxlen символов строки src в место памяти, на которое указывает dest
int ctrcmp(const char *s1, const char *s2) сравнивает две строки в лексикографическом порядке с учетом различия прописных и строчных букв, функция возвращает 0, если строки совпадают, возвращает - 1, если s1 располагается в упорядоченном по алфавиту порядке раньше, чем s2, и 1 - в противоположном случае.
int strncmp(const char *s1, const char *s2, size_t maxlen) сравнивает maxlen символов двух строк в лексикографическом порядке, функция возвращает 0, если строки совпадают, возвращает - 1, если s1 располагается в упорядоченном по алфавиту порядке раньше, чем s2, и 1 - в противоположном случае.
double atof(const char *s) преобразует строку в вещественное число, в случае неудачного преобразования возвращается число 0
long atol(const char *s) преобразует строку в длинное целое число, в случае неудачного преобразования возвращается 0
char *strchr(const char *s, int c); возвращает указатель на первое вхождение символа c в строку, на которую указывает s . Если символ c не найден, возвращается NULL
char *strupr(char *s) преобразует символы строки, на которую указывает s, в символы верхнего регистра, после чего возвращает ее

Тип данных string

Кроме работы со строками, как с массивом символов, в C++ существует специальный тип данных string . Для ввода переменных этого типа можно использовать cin , или специальную функцию getline .

getline(cin, s);

Здесь s - имя вводимой переменной типа string .

При описании переменной этого типа можно сразу присвоить значение этой переменной.

string var(s);

Здесь var - имя переменной, s - строковая константа. В результате этого оператора создается переменная var типа string , и в нее записывается значение строковой константы s . Например,

string v(«Hello»);

Создается строка v , в которую записывается значение Hello .

Доступ к i-му элементу строки s типа string осуществляется стандартным образом s[i] . Над строками типа string определенны следующие операции:

  • присваивания, например s1=s2;
  • объединения строк (s1+=s2 или s1=s1+s2) - добавляет к строке s1 строку s2, результат храниться в строке s1, пример объединения строк:
  • сравнения строк на основе лексикографического порядка: s1=s2, s1!=s2, s1s2, s1<=s2, s1>=s2 - результатом будет логическое значение;

При обработке строк типа string можно использовать следующие функции:

  • s.substr(pos, length) - возвращает подстроку из строки s , начиная с номера pos длинной length символов;
  • s.empty() - возвращает значение true, если строка s пуста, false - в противном случае;
  • s.insert(pos, s1) - вставляет строку s1 в строку s , начиная с позиции pos ;
  • s.remove(pos, length) - удаляет из строки s подстроку length длинной pos символов;
  • s.find(s1, pos) - возвращает номер первого вхождения строки s1 в строку s , поиск начинается с номера pos , параметр pos может отсутствовать, в этом случае поиск идет с начала строки;
  • s.findfirst(s1, pos) - возвращает номер первого вхождения любого символа из строки s1 в строку s , поиск начинается с номера pos , который может отсутствовать.

Русский язык для строк

Думаю вы уже заметили, что при выводе русских букв, в консоли появляются «левые» символы. Для того чтобы избежать этого недоразумения, необходимо воспользоваться сторонней функцией CharToOemA . Подключаем библиотеку windows.h , она нужна для того, чтобы наша функция могла преобразовать строки в другую кодировку. Также, нам понадобиться дополнительный символьный массив. Исходный код программы будет выглядеть вот так:

1
2
3
4
5
6
7
8
9
10
11
12
13
14

#include «stdafx.h»
#include
#include
using namespace std;
int main()
{ setlocale(LC_ALL,«Rus» ) ;
char s[ 255 ] = { » Меня надо преобразовать « } ;
char * pre= new char [ 255 ] ;
CharToOemA(s, pre) ; //преобразовываем
cout << s;
delete pre;
system («pause>>void» ) ;
return 0 ;
}

Способ только что описанный достаточно не удобен. Но существует более простой вариант решения «русской» проблемы. Как видите, в программе используется функция setlocale(), вместо этого удобнее вписать в главную функцию следующую конструкцию.