#1
                
                26 июля 2008 в 08:11
                
                
            
            
                Значит, решаю примитивную задачу по компьютеризации библиотеки. <br />Имею такие структуры: <br />
<br /><br />Содержимое studentID из списка взятых книг имеет кроме цифр, какие-то бессвязные буквы в конце строки, которая сама по себе, почему-то, гораздо больше девяти ячеек. <br /><br />Непонятные символы скорее всего "мусор" или "наезд" на соседнее поле записи в структуре, но почему это происходит я не понимаю. <br /><br />Нужна помощь. <br /><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 />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 />П.С.: спасибо)