Введение |
Операторы |
Операции |
Переменные и типы |
Пояснения к курсовой работе |
Препроцессор |
Работа с файлами |
Стандарты безопасного кодирования |
Указатели и динамическая память |
Функции и модули |
Ввод-вывод |
В языке С строки являются обычными массивами фиксированного размера из символов char
(однобайтные символы) или wchar_t
(символы Unicode). Признаком конца строки является нулевой символ '\0'
, хранение которого нужно учитывать при определении размера массива. Определение
char s[]="ABC";
эквивалентно
char s[]={'A','B','C','\0'}; // массив из 4 символов
Аналогично последовательность символов в кавычках "ABC"
в операторах программы интерпретируется компилятором как массив-значение: (static const char []){'A','B','C','\0'}
Действия над строками в языке С определены как функции в заголовочных файлах <string.h>
, <wchar.h>
, <stdio.h>
. Основными недостатками этих функций является низкая эффективность, сложный код, необходимость проверки не только переполнения выделенной памяти, но и выхода за пределы текущей длины строки.
Гораздо удобнее использовать строки в языке С++, определенные в заголовочном файле <string>
Функция | Строки char |
Строки wchar_t |
Строки С++ |
---|---|---|---|
Определение строк | char s1[101], // строка длиной 100 символов + место для '\0' s2[101]="ABC"; // с заданием начального значения char* sr; // для результатов поиска |
wchar_t s1[101], s2[101]=L"ABC"; wchar_t* sr; |
string s1, s2="ABC"; // wstring s1, s2=L"ABC"; |
Вспомогательные объявления | size_t len, // длина строки pos=2, // позиция в строке n=5; //количество символов int a; double b; // для преобразований строка<->число |
||
Длина строки | len=strlen(s2); |
len=wcslen(s2); |
len=s2.length(); // len=s2.size(); |
Проход по всем символам строки | for(int i=0; s1[i]; ++i) // s1[i] |
for(int i=0; s1[i]; ++i) // s1[i] |
for(int i=0; i<s1.size(); ++i) // s1[i] |
Копирование строки | strcpy(s1,s2); |
wcscpy(s1,s2); |
s1=s2; |
Заполнение строки символом | memset(s1,'A',n); s1[n]=0; |
wmemset(s1,L'A',n); s1[n]=0; |
s1=string(n,'A'); |
Подстрока с pos длиной n (или до конца строки) |
strncpy(s1,s2+pos,n); s1[n]=0; |
wcsncpy(s1,s2+pos,n); s1[n]=0; |
s1=s2.substr(pos,n); |
Добавление строки | strcat(s1,s2); |
wcscat(s1,s2); |
s1+=s2; |
Добавление символа | len=strlen(s1); s1[len++]='A'; s1[len]=0; |
len=wcslen(s1); s1[len++]='A'; s1[len]=0; |
s1+='A'; |
Удаление подстроки с pos длиной n (или до конца строки) |
if(pos+n<len) memmove(s1+pos,s1+pos+n,len+1-pos-n); else s1[pos]=0; |
if(pos+n<len) wmemmove(s1+pos,s2+pos+n,len+1-pos-n); else s1[pos]=0; |
s1.erase(pos,n); |
Вставка строки | n=strlen(s2); memmove(s1+pos+n,s1+pos,len+1-pos); strncpy(s1+pos,s2,n); |
n=wcslen(s2); wmemmove(s1+pos+n,s1+pos,len+1-pos); wcsncpy(s1+pos,s2,n); |
s1.insert(pos,s2); |
Сравнение строк | if(strcmp(s1,s2)>=0) // s1>=s2 |
if(wcscmp(s1,s2)>=0) |
if(s1>=s2) |
Поиск подстроки/символа | sr=strstr(s1,s2); // sr=strchr(s1,'A'); if(sr) { pos=sr-s1; ... // s2 найдена в позиции pos else { ... // s2 не найдена |
sr=wcsstr(s1,s2); // sr=wcschr(s1,L'A'); if(sr) { pos=sr-s1; ... } else {...} |
pos=s1.find(s2); // pos=s1.find('A'); if(pos!=string::npos) {/* найдена */} else { /* нет */} |
Поиск подстроки/символа, начиная с pos | sr=strstr(s1+pos,s2); // sr=strchr(s1+pos,'A'); далее аналогично |
sr=wcsstr(s1+pos,s2); // sr=wcschr(s1+pos,L'A'); |
pos=s1.find(s2,pos); // pos=s1.find('A',pos); |
Ввод слова | scanf("%100s",s1); |
wscanf(L"%100ls",s1); |
cin>>s1; |
Ввод строки до '\n' | if(scanf("%100[^\n]", s1) != 1) s1[0] = 0; getchar(); |
if(wscanf(L"%100l[^\n]", s1) != 1) s1[0] = 0; getwchar(); |
getline(cin,s1); |
Вывод строки | printf("%s",s1); |
wprintf(L"%ls",s1); |
cout<<s1; |
Преобразование строки в число | sscanf(s1,"%d",&a); sscanf(s1,"%lf",&b); |
swscanf(s1,L"%d",&a); swscanf(s1,L"%lf",&b); |
a=stoi(s1); b=stod(s1); |
Преобразование числа в строку | sprintf(s1,"%d",a); sprintf(s1,"%lg",b); |
swprintf(s1,L"%d",a); swprintf(s1,L"%lg",b); |
s1=to_string(a); s1=to_string(b); |
Замечания:
strcpy/strncpy
используется только для копирования из одной строки в другую (strcpy
до конца строки, strncpy
– не более n символов, в том числе '\0'), memmove
– для копирования части строки, возможно в ту же строку (также как у массивов). scanf
вернет EOF
getchar()
или cin.get()
, функция возвращает ' '
, если есть еще слово в этой строке, или '\n'
– конец строки или EOF – конец файла if(cin>>s1) //успешный ввод
else // конец файла
#include <stdio.h>
#include <string.h>
// Вывод всех строк в обратном порядке
int main() {
char s1[101];
for(;;) {
if(scanf("%100[^\n]", s1) != 1) s1[0] = 0;
if(getchar()==EOF) break;
size_t len=strlen(s1);
for(int i=len-1;i>=0;--i)
printf("%c",s1[i]);
printf("\n");
}
}
Для распознавания символов в С и С++ используются функции, объявленные в заголовочных файлах <ctype.h>
,<wctype.h>
. Аргумент типа char
должен быть преобразован в unsigned char
(char8_t
).
Для однобайтных символов на результат будет влиять выбор кодировки:setlocale(LC_CTYPE|LC_COLLATE, "ru_RU.cp1251");
Функция | unsigned char |
wchar_t |
---|---|---|
Пробельный символ (' ', '\n', '\t' , …) |
isspace(c) |
iswspace(c) |
Цифра | isdigit(c) |
iswdigit(c) |
Буква | isalpha(c) |
iswalpha(c) |
Буква или цифра | isalnum(c) |
iswalnum(c) |
Строчная буква | islower(c) |
iswlower(c) |
Прописная буква | isupper(c) |
iswupper(c) |
В строчную букву | c=tolower(c); |
c=towlower(c); |
В прописную букву | c=toupper(c); |
c=towupper(c); |
#include <stdio.h>
#include <string.h>
// Первая строка содержит запрещенные буквы в верхнем регистре
// Вторая строка число N
// Далее N строк, для каждой строки вывести yes, если строка не содержит запрещенных букв, иначе no
int main() {
char dis[101],s[101];
int n;
scanf("%100s%d%*c",dis,&n); // ввести слово, число и символ '\n' после числа
for(int i=0;i<n;++i) {
if(scanf("%100[^\n]", s) != 1) s[0] = 0;
getchar();
int fl=1;
for(int j=0;dis[j];++j)
if(strchr(s,dis[j]) || strchr(s,tolower((unsigned char)dis[j]))) {
fl=0;
break;
}
if(fl) printf("yes\n");
else printf("no\n");
}
}
В <stdlib.h>
определены 2 функции для преобразования из wchar_t в символы текущей кодировки и обратно. Если установлена кодировка UTF8, то 1 символ может занимать в массиве от 1 до 4 байт (1 байт – символы ASCII, 2 байта – русские буквы, 3 байта – иероглифы, 4 байта – пиктограммы).
Для операций над строками с многобайтными символами можно использовать функции из <string.h>
, но нужно учитывать, что в качестве аргументов многим функциям нужно указывать номер байта, а не номер символа, и номер байта будет результатом поиска.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wchar.h>
#include <locale.h>
int main() {
setlocale(LC_ALL, "ru_RU.utf8");
wchar_t a[]=L"z\u00df\u6c34"; // строка из 3 символов: z, греческая бета и иероглиф
char b[100];
wchar_t c[10];
size_t alen=wcslen(a);
size_t blen=wcstombs(b, a, sizeof(b)); // преобразование из Unicode в UTF8
if(blen==-1) return 1; // ошибка
for(int i=0; i<alen; ++i)
printf("a[%d]=%x\n",i,a[i]);
for(int i=0; i<blen; ++i)
printf("b[%d]=%x\n",i,(unsigned char)b[i]);
strcat(b,u8"+\u0462"); // добавляем строку из 2 символов в кодировке UTF8
printf("len=%d\n",(int)strlen(b)); // длина строки увеличивается на 3 байта
size_t clen=mbstowcs(c, b, sizeof(c)); // преобразование из UTF8 в Unicode
if(clen==-1) return 1; // ошибка
for(int i=0; i<clen; ++i)
printf("c[%d]=%x\n",i,(int)c[i]);
}