#1
26 июля 2008 в 08:11
Значит, решаю примитивную задачу по компьютеризации библиотеки. <br />Имею такие структуры: <br />
struct book {<br /> long id; <br /> char title[15]; <br /> char author[20]; <br /> int qTOTAL; <br /> int qLEFT; <br />} typedef book; <br /><br />struct student {<br /> char id[9]; <br /> char fname[10];<br /> char lname[20]; <br /> char address[30];<br /> char phone[9]; <br />} typedef student; <br /><br />struct zapros {<br /> long bookID; <br /> char studentID[9]; <br /> int retDAY; <br /> int retMONTH; <br /> struct zapros *next; <br />} typedef zapros;
<br /><br />В одном из пунктов задания требуется написать функцию, которая находит студента/студентов взявших в библиотеке максимальное кол-во книг. Исходя из того, что ID студентов определены как массив типа char[9], для выполнения функции задания испольую strcmp(). <br /><br />Проблема в том, что функция пишет не тех студентов/студента, которые взяли максимальное кол-во книг из библиотеки, функция пишет ВСЕХ студентов! <br />Я попытался "вскрыть" проблему дэбаггером и обнаружил интересную вещь, которую я не знаю как понимать: <br /><br /><br />Содержимое studentID из списка взятых книг имеет кроме цифр, какие-то бессвязные буквы в конце строки, которая сама по себе, почему-то, гораздо больше девяти ячеек. <br /><br />Непонятные символы скорее всего "мусор" или "наезд" на соседнее поле записи в структуре, но почему это происходит я не понимаю. <br /><br />Нужна помощь. <br /><br />П.С.: данные в главной: <br />main() <br />{<br /> book myARR[N]=<br /> {<br /> {111, "AAA","Pushkin", 40,23},<br /> {222, "BBB","Tolstoi", 20,2},<br /> {333, "CCC","Dostoevskij", 10,9},<br /> {12331111, "DDD","Lermontov", 4,3},<br /> {332222111, "EEE","Pasternak", 6,2}<br /> } ; <br /> student myARR2[NN]=<br /> {<br /> {"012345678", "Ivan", "Ivanofff", "Moscow", "086338456"},<br /> {"112345678", "Petr", "Sidorofff", "Kiev", "086111456"},<br /> {"023456789", "Zmey", "Gorynich", "St.Petersburg", "086333336"},<br /> {"032456789", "Ilja", "Muromec", "Murom", "086355556"},<br /> {"001034222", "John", "Smith", "New York", "067838456"}<br /> };<br /> zapros myARR3[5]=<br /> {<br /> {111,"012345678", 23,2, &myARR3[1]},<br /> {333,"112345678", 4,10, &myARR3[2]},<br /> {111,"023456789", 17,3, &myARR3[3]},<br /> {12331111,"012345678", 8,11, &myARR3[4]},<br /> {332222111,"012345678", 5,12, NULL}<br /> }; <br /> zapros *head=&myARR3[0]; <br /><br /> GIMEL(myARR2,head); <br />}
<br /><br />П.П.С.: я выяснил некую мелоч имеющую отношение к этому заданию: <br />печатают всех, потому что массив счетчиков весь ПО НУЛЯМ. Это значит, что не было ни одного совпадения студенчесиких номеров. <br /><br />Но основная проблема всё ещё не решена... <br /><br />П.П.П.С.: чтобы проверить дополнительные варианты "дырок" сделал такое: в структурах Студент и Запрос - изменил размер studentID на [10], а в функции вставил перед каждой строкой сравнения с помощью strcmp такой код: <br /><br />[code]myARR[i].id[9] = help->studentID[9] = '\0'; [/code] <br />То-есть, я добавл дополнительный нулевой терминирующий байт в полях studentID во всех структурах. <br /><br />Этим я добился только того , что в дэбаггере теперь ID студентов отображаются правильно... но это ничего не изменило и массив счетчиков всё ещё по нулям >:(<br />
#2
26 июля 2008 в 22:28
Так. Раз и навсегда, строки в C заканчиваются символом с кодом 0 (ноль). Как вариант, ты пишешь свои собственные функции, которые разбирают строчки посимвольно. Особенно эффективно будут работать твои собственные ф-ции если ты знаешь длину строк, как в твоём случае, все строки 9 символов.<br /><br />Второе золотое правило, ключевые поля - строки делают только извращенцы. Либо это принципиально обязательное условие задачи.<br /><br />[code]<br />for (i=0; (strcmp(help->studentID,myARR[i].id) ) && i < NN; i++);<br />if (i<NN) count[i]++;<br />[/code]<br />Не нравится мне это. Жопец какой-то. Непонимаю чего ты хотел этим сказать, вернее понимаю, но это какая-то очень специфическая логика и явно накопление не той суммы. Если считаешь кол-во книг, которые взяли каждый студент, тот как минимум [i]count[i]++[/i] должен сидеть в теле цикла<br />[code]<br />for (<перебор всех возможных вариантов>) count[i]++;<br />[/code]<br /><br />Ну, навскидку так должно работать:<br /><br />[code]<br />for (i=0; i < NN; i++) if (!strcmp(help->studentID,myARR[i].id) ) count[i]++;<br />[/code]<br /><br />Обрати внимание, что<br />
<br /> strcmp Посимвольно сравнивает две строки, strcmp возвращает:<br /> <0, если string1 меньше string2<br /> =0, если string1 равно string2<br /> >0, если string1 больше string2<br />
#3
27 июля 2008 в 07:52
willow<br />Во первых спасибо, что ответил :) <br /><br />Насчет
Второе золотое правило, ключевые поля - строки делают только извращенцы.<br />вполне согласен, но когда в задаче особо не оговорен формат studentID, и если представить, что он <br />может начинаться на ноль и имеет фиксированное кол-во символов, то согласись - упростить себе жизнь <br />не получится. <br /><br />
Не нравится мне это. Жопец какой-то. Непонимаю чего ты хотел этим сказать, вернее понимаю, но это какая-то очень специфическая логика и явно накопление не той суммы. Если считаешь кол-во книг, которые взяли каждый студент, тот как минимум count[ i ]++ должен сидеть в теле цикла<br />Логика такая (и поэтому инкремент не в цикле) - когда совпадение ID, значит студент такой-то под индексом i брал что-то в библиотеке. <br />Поэтому - выход из for и инкремент по индексу. <br /><br />В задаче требуется вывести имя студента, который взял наибольшее кол-во книг из библиотеки. <br />Если есть несколько таких студентов - вывести имена всех. <br /><br />
strcmp Посимвольно сравнивает две строки, strcmp возвращает:<br /> <0, если string1 меньше string2<br /> =0, если string1 равно string2<br /> >0, если string1 больше string2<br />так точно, но в рамках задачи нужен только вариант == 0 , отсюда вольности в построении условия цикла <br />[code]for (i=0; (strcmp(help->studentID, myARR[i].id) ) && i < NN; i++);[/code]<br />---<br />Проблема в том, что массив-счетчик не меняет значения, то-есть ВООБЩЕ не меняет! <br />При том, что, как видно из массивов с данными -есть студент котоый взял три книги, а остальные взяли по одной.
#4
27 июля 2008 в 09:29
Переделал под LONG - работает исправно, но вопросы не отпали
#5
27 июля 2008 в 09:41
Логика такая (и поэтому инкремент не в цикле) - когда совпадение ID, значит студент такой-то под индексом i брал что-то в библиотеке. <br />Поэтому - выход из for и инкремент по индексу.<br />Фига-се у нас логика! Это значит, до ближайшего совпадения, а если их несколько, совпадений? Если этот самый studentID взял несколько книг? А если студенты взяли одинаковые книги? Ага, крутим цикл пока не встретим совпадение, а потом, кстати, count[ i ]++ , что такое i ? :P Это лишь индекс элемента вхождения, а ты пытаешься i превратить в числовой аналог studentID ;D<br /><br />P.S. С почётным 666-м сообщением тебя!
#6
27 июля 2008 в 09:46
willow<br />Это вполне рабочая программа. И исходил из того, что массивы студентов и книг не будут модифицироваться. <br />Эффективность конечно хромает. <br /><br />А вообще, изначально я писал о том, что strcmp() не работает как положенно. <br /><br />П.С.: спасибо)