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