Загрузка [MathJax]/jax/output/HTML-CSS/fonts/TeX/fontdata.js
 

printМассивы, строки и структуры

printСтроки

В языке С строки являются обычными массивами фиксированного размера из символов 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 – конец файла
  • в C++ результат ввода можно указать в качестве условия:
    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]);
}
Р’РІРѕРґ:

Выполнить
Вывод:
loading