Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
л_13_Строки.doc
Скачиваний:
0
Добавлен:
01.04.2025
Размер:
572.42 Кб
Скачать

Возможные ошибки при работе со строками

Основные ошибки при работе с С-строками происходят из-за отсутствия понимания специфики описания строк (строка-массив или строка-указатель)

//пример_4

int main ( )

{

char msg[10]; //определение строки-массива

//msg="hello"; // error!!! пытаемся изменить указатель-константу!!!

strcpy_s (msg, "hello"); //ok!!! заполнение строки копированием!!!

char *name; //определение указателя на char

//scanf ("%s", name); // error!!! место под строку-указатель не выделено!!!

name = (char*) malloc(10); // ok!!! присваивание указателю адреса динамической строки

// или name = new char[10];

printf ("name?");

scanf ("%s",name); //ввод строки, перед именем переменной не ставится символ &

// ввод выполняется до первого пробельного символа

printf ("%s%s", msg, name);

_getch();

return 0;

}

Так как имя строки-массива – это указатель-константа, то нельзя выполнить присваивание:

char array[20];

//array = "Literal of string"; // error!!!

Заполнить строку-массив можно с использованием функции копирования (что мы видели в примере: strcpy_s (msg, "hello");).

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

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

Для ввода-вывода С-строк используются функции printf (),scanf (),gets() и puts(), унаследованные из библиотеки С. Функция gets(s) читает символы с клавиатуры, в том числе и пробелы (до символа новой строки), и помещает их в строку, завершая ее 0-символом; функция puts(s) выводит строку, заменяя 0-символ символом новой строки.

// С-ввод строки до первого пробельного символа

int main()

{

const int MAX = 80;

char str[MAX]; // строка-массив

printf ("Enter a string: ");

scanf ("%s", str); //odin_dwa адрес переменной здесь не указываем

printf("%s", str); //odin_dwa

printf(" %3s\n", str); //3 – минимальный размер поля вывода : odin_dwa

printf(" %10.2s\n", str); // od выравнивание вправо и 2 символа

printf(" %-10.2s\n", str); //od выравнивание влево и 2 символа

printf (" string?\n");

scanf ("%s", str); //вводим: odin dwa, но вводится только odin (до пробела)

printf (" %s\n", str); // в буфере ввода остался «хвост» dwa

//fflush (stdin); // для корректной дальнейшей работы scanf() // требуется очистка буфера ввода: fflush (stdin);

printf (" string?\n");

scanf ("%s", str);

printf (" %s\n", str);

_getch();

return 0;

}

// С-ввод строки с пробелами

int main()

{

const int MAX = 10;

char str[MAX]; // строка-массив

printf ("Enter a string: ");

gets(str); //ввод строки: odin dwa

puts(str); //вывод строки: odin dwa

_getch();

return 0;

}

//посимвольный ввод строки в стиле С

int main()

{

const int MAX = 10;

char str[MAX]; // строка-массив

printf ("Enter a string: ");

for (int i=0; i<MAX; i++)

scanf ("%c", &str[i]); //ввод символов 1234567899

str[MAX-1]='\0';

printf ("%s", str); //вывод строки 123456789

int i=0;

printf ("\nEnter a string: ");

while ( (str[i] = _getch() ) !=13 ) // или != ‘\r’ посимвольный ввод

_putch (str[i++]); // посимвольный вывод

str[i] = '\0'; //завершение строки 

_putch ('\n'); _putch ('o'); _putch ('k');

printf ("\n%s", str); //вывод строки

_getch();

return 0;

}

Для ввода-вывода С-строк в стиле С++ используются известные нам объекты cin и cout.

//ввод строки до первого пробельного символа

int main()

{

const int MAX = 80;

char str[MAX]; // строка-массив

cout << "Enter a string: ";

cin >> str; //ввод строки

cout << "You entered: " << str << endl; //вывод строки

_getch();

return 0;

}

//посимвольный ввод строки

int main()

{

const int MAX = 10;

char str[MAX]; // строка-массив

cout << "Enter a string: ";

for (int i=0; i< MAX-1; i++)

cin >> str[i]; //ввод символов 1234567899

str[MAX-1]='\0';

cout << "You entered: " << str << endl; //вывод строки: 123456789

_getch();

return 0;

}

Для ввода любых символов, включая пробельные, используются методы get() и get(c) класса istream, объектом которого является cin:

char c, d, e;

c=cin.get(); //возвращается код извлеченного из потока символа или EOF

cin.get(d); //извлеченный из потока символ записывается в переменную-аргумент

cin.get(e);

//посимвольный ввод строки с использованием метода get()

int main()

{

const int MAX = 10;

char str[MAX]; // строка-массив

cout << "Enter a string: ";

for (int i=0; i< MAX-1; i++)

cin.get(str[i]); //ввод без пробелов символов 12345 9

str[MAX-1]='\0';

cout << "You entered: " << str << endl; //вывод строки 12345 9

_getch();

return 0;

}

Для ввода строки из нескольких слов используются методы getline() или get() объекта cin:

//ввод строки из нескольких слов с использованием метода getline()

int main()

{

const int MAX = 80;

char str[MAX];

cout << "\nEnter a string: ";

cin.getline (str, MAX); //ввод строки в str

//символ ‘\n’ считывается (удаляется) из потока ввода

//и вместо него в строковую переменную записывается ‘\0’

cout << "You entered: " << str << endl;

cin.get (str, MAX); // ввод строки в str

//символ ‘\n’ остается в потоке

//в строковую переменную добавляется ‘\0’

cout << "You entered: " << str << endl;

_getch();

return 0;

}

// ввод нескольких строк, завершающихся <enter>, в качестве одной строки

const int MAX = 2000;

char str[MAX];

int main()

{

cout << "\nEnter a string:\n";

cin.get(str, MAX, '$'); //ввод всех строк завершается символом $

cout << "You entered:\n" << str << endl;

_getch();

return 0;

}

В этом случае можно ввести несколько строк, завершающихся <enter>, и только затем набрать символ $ (все строки будут восприняты как одна строка):

Enter a string:

qwert

12345

qwert$

You entered:

qwert

12345

qwert

Обратите внимание на «плохую» работу метода get() при вызове его с двумя аргументами два раза подряд:

char s[10];

int n=5;

cin.get (s, n); //1 вводим 123<enter>,‘\n’остается в потоке ввода

cout << s << endl; //2 выводит 123

cin.get (s, n); //3 считывает пустую строку

cout << s << endl; //4 выводит пустую строку

cin.get (s, n); //5 считывает пустую строку

cout << s << endl; //6 выводит пустую строку

cout << "end" << endl; //7 выполняется!!!

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

123

123

end

За выводом в операторе //2 сразу последует сообщение “end”, выведенное оператором //7. Это происходит из-за символа ‘\n’, оставленного в потоке ввода первым вызовом метода get(), т.е. оператором //1. Поэтому операторами //3 и //5 будут считаны (и, соответственно) выведены на экран пустые строки.

Удалить символ ‘\n’ из входного потока можно путем вызова метода get() без параметров cin.get():

char s[10];

int n=5;

cin.get (s, n); //1 вводим 123<enter>,‘\n’остается в потоке ввода

cout << s << endl; //2 выводит 123

cin.get (); //удаляем ‘\n’ из входного потока

cin.get (s, n); //3 вводим 234<enter>,‘\n’остается в потоке ввода

cout << s << endl; //4 выводит 234

cin.get (); //удаляем ‘\n’ из входного потока

cin.get (s, n); //5

cout << s << endl; //6

cout << "end" << endl; //7

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

123

123

234

234

345

345

end

Еще лучше – использовать в таких случаях метод getline().

Следующий цикл обеспечивает ввод символов до нажатия ctrl+z признака конца файла

char c;

while ((c=cin.get())!=EOF) { //ввод символов, выход из цикла – ctrl+z признак конца файла

cout << c;

}

Для ввода нескольких С-строк можно использовать метод getline() в заголовке цикла:

int main()

{

const int n = 80;

char s[n];

while (cin.getline(s, n)) { //ввод строки в s, выход из цикла – ctrl+z – признак конца файла

cout << s << endl; //вывод строки

//………. обработка строки

}

_getch();

return 0;

}