Итак, что мы имеем изначально? Программа, приведённая в книге, очень проста. Создаётся массив строк numbers[10][80], этот массив сразу заполняется данными: имя, телефон, имя, телефон ... и т. д. Вы вводите имя, программа последовательно сравнивает введённую вами строку с элементами строкового массива. Если есть совпадение, программа отображает телефонный номер. Конец программы.
cin >> str; // Считываем строку в символьную (char) переменную str[80]
for(i = 0; i < 10; i += 2)
if(!strcmp(str, numbers[i])) { // Проверяем на совпадение с элементом массива
cout << "Телефонный номер: " // и выводим на экран
<< numbers[i+1] << "\n";// телефонный номер
break;
}
Теперь пора превратить этот телефонный справочник в музыкальную БД. Во-первых, я поменял название массива и сделал его "безразмерным", вот так: bands[][200]. Как видите, компилятор сам подсчитывает количество строк массива. Кроме того, я увеличил количество столбцов массива (т. е. максимальную длину записи) до 200, чтобы можно было перечислить несколько альбомов для каждого музыканта:
char bands[][200] = {
"группа1", "альбом1, альбом2 ...",
"группа2", "альбом1, альбом2, альбом3 ...",
// ...
"группаN", "
альбом1, альбом2 ...
",
"", ""
};
Здесь я добавил в конце массива две пустые строки, содержащие нулевой символ "\0" (компилятор самостоятельно добавляет этот символ в конце каждой строковой переменной). Это пригодится для огранизации цикла последовательного просмотра элементов строкового массива.
Поместил считывание строки, поиск совпадений, и вывод результата в бесконечный цикл, из которого два выхода (а как же иначе?..) - или клавиша <q>, или... <Ctrl>+<c>.
Теперь проблема с cin >> str; - нам не удастся ввести название группы, состоящее из нескольких слов, разделённых пробелами - знак пробела будет воспринят как конец ввода и в переменную str попадёт только первое слово из названия группы. Чтобы исправить это, потребуется использовать... ну, скажем, fgets(str, 100, stdin) для считывания строки. Однако именно эта функция и явилась причиной очень занятного бага, из-за которого программа не могла корректно работать. Дело в том, что функция fgets() прежде, чем завершить свою работу после нажатия <Enter>, считывает в строковую переменную str символ новой строки "\n"! Из-за этой "особенности" функция strcmp(str, bands[i]) работала некорректно - как я не бился, она "в упор" не видела очевидные совпадения введённой строки с элементом строкового массива... И вот теперь я знаю, в чём дело. Но как это исправить? В Интернете нашлось несколько различных howto на тему "как выкинуть ненужный символ новой строки из переменной". Однако все эти способы показались мне чресчур сложными для подобной задачи. После размышлений, я написал следующее:
// с функцией fgets проблема...
fgets(str, 100, stdin);
// ...она передаёт в символьную переменную str, кроме "обычных" символов,
// символ новой строки (\n). Из-за этого операции со str выполняются некорректно.
// Поэтому, с помощью простого цикла, мы находим символ конца строки
// и заменяем его на нулевой символ.
for(i = 0; i < strlen(str); i++)
if(str[i] == '\n') str[i] = 0;
После этого программа стала работать корректно.
В процессе изучения языка C++ я часто сталкиваюсь с различными проблемами, которые пытаюсь решить. Иногда это бывает очень просто, а иногда приходится потратить немало времени. В большинстве случаев, больше всего времени уходит на то, чтобы понять, где же я ошибся.
А вообще, на поиск и исправление ошибок может уйти время даже большее, чем на написание самой программы.
Почему именно C++ изучаешь? Сложноватая тема, плюс память надо в ручную чистить..
ОтветитьУдалить@.NET Trading
ОтветитьУдалитьВо-первых, интерес. К тому же, в Linux много чего на C++ написано, так что знание этого языка не помешает.
Во-вторых, программисты на C++ более востребованы, насколько я знаю.
В-третьих, на мой взгляд, этот язык более красивый и удобный, чем Pascal (который я со школы изучал).