Всем доброго времени суток. Изучаю программирование и решая задачу столкнулся с проблемой, нуждаюсь в объяснении что я делаю не так. Приступим:
Задача 12.7: Даны две фамилии. Определить, какая из них длиннее. (из задачника "1400 задач по программированию" от Златопольский Д.М.)
Для себя решил что входные данные поданы в виде одной строки.
Код решения компилируется без замечаний (gcc -Wall -g file.c -o file).
При запуске программы получаю бесконечный ввод данных.
Тестируя отдельно самолепную функцию GetString таких проблем не получаю и ввод заканчивается как и задумано при нажатии клавиши Enter. Добавление 1 следующей строчки кода и отладочной печати ведет к вышеназванной проблеме бесконечного ввода. Объясните что я делаю не так. Спасибо за внимание.
Вот код решения задачи:#include <stdio.h>
int GetString(char *str, int strsize)
{
char c;
int i=0;while ((c=getchar())!='\n') {
if (i<=strsize-1){
str[i]=c;
i++;
}
}
str[i]='\0';
return 0;
}int GetWord (char *str, int number, char *word, int wordsize)
{
int i=0, k=0;
int countword=0;
char prev=' ';while (str[i]!='\0') {
if (prev==' ' && str[i]!=' ') {
countword++;
}
if (countword==number && str[i]!=' ' && k<=wordsize-1) {
word[k]=str[i];
k++;
}
prev=str[i];
}
word[k]='\0';
return k;
}int main () {
enum {strsize=100, wordsize=20};
char str[strsize];
char surname1[wordsize];
char surname2[wordsize];
int lensurname1=0;
int lensurname2=0;GetString(str, strsize);
lensurname1=GetWord (str, 1, surname1, wordsize);
lensurname2=GetWord (str, 2, surname2, wordsize);
if (lensurname1 > lensurname2 ) {
printf("%s is longer than %s!\n", surname1, surname2);
}
if (lensurname1 < lensurname2 ) {
printf("%s is longer than %s!\n", surname2, surname1);
}
if (lensurname1 == lensurname2 ) {
printf("Surnames are equal!\n");
}
return 0;
}
Проблема в незнании сей. На глаз сразу вижу что гетстринг не работает, дальше и смотреть не хочется.
>[оверквотинг удален]
> }
> if (countword==number && str[i]!='
> ' && k<=wordsize-1) {
>
> word[k]=str[i];
>
> k++;
> }
> prev=str[i];
> }в этом цикле нету инкремента i.
> в этом цикле нету инкремента i.Большое спасибо! Всё заработало! Даже обидно на невнимательности завалиться :(
Хороший пример, как НЕ НУЖНО писать программы. Сравни с этим:
#include <stdio.h>int main(int argc, char* argv[]) {
if (argc != 3) {
puts("need 2 surnames\n");
return 1;
}
int diff = strlen(argv[1]) - strlen(argv[2]);if (diff >0) {
printf("%s longer than %s\n", argv[1], argv[2]);
return 0;
}
if (diff <0) {
printf("%s shorter than %s\n", argv[1], argv[2]);
return 0;
}printf("%s and %s are equal length\n", argv[1], argv[2]);
return 0;
}
> Хороший пример, как НЕ НУЖНО писать программы. Сравни с этим:Приветствую! Спасибо за комментарий! Очень важен для меня ибо поднимает актуальные вопросы.
Первый: "Как выглядит промышленный код?" По задумке выношу реализацию в отдельные функции и в main оставляю только общую логику и организацию данных. На данном этапе на простых программах это избыточный код, но может быть такая привычка даст результаты в будущем?
Второй: "Как правильно учиться?" Где то прочел: пока не знаешь как устроенны и работают простые библиотечные функции не используй их, а пиши свои реализации". ПОДЧЕРКНУ: совет для стадии обучения. Мне он понравился вот и леплю как могу.
Из Примера подчеркнул:
Проверку входный данных - полезно, ЗАПОМНЮ!
Введение переменной хранящей разницу вместо постоянного сравнения и её имя "diff". ЗАПОМНЮ!
Это вообще мрак придумывать имена для переменных на англ да ещё как можно короче.Что думаете о выше поставленных вопросах?
>На данном этапе на простых программах это избыточный код, но может быть такая привычка даст результаты в будущем?Изменения в конкретной функции затрагивают её поведение. Если ты кладёшь весь код в одну функцию и в ней много кода, при изменении может много что сломаться. Ну и лично у меня есть правило не класть в одну функцию кода больше, чем помещается на экране, правда вот, на си я обычно не пишу, на си бы я лимит строк мог бы и увеличить, возможно.
Просто если это читает другой человек, то для того, чтобы понять смысл функции, ему придётся мотать функцию туда-сюда. Если же она примерно умещается на экране (25-50 строк где-то - мой верхний лимит обычно), то и мотать не придётся.>Где то прочел: пока не знаешь как устроенны и работают простые библиотечные функции не используй их, а пиши свои реализации
В принципе, совет хороший, вместе с алгоритмами учить, как делаются вот такие вот вещи. Жалко, что меня на такое не хватило, хотелось бы поизучать...
Но помимо этого стоит ещё читать чужой код. Я не читал и имею с этого последствия в понимании.>Проверку входный данных - полезно, ЗАПОМНЮ!
По идее, везде, где есть внешние данные, должны быть проверки или слои проверок для того, чтобы не ставить кордоны по периметру внутреннего кода. Сверху, снизу, сбоку и так далее. Защитному программированию вообще никто не учит, а жалко.
>затрагивают её поведениеМогут затрагивать.
> Первый: "Как выглядит промышленный код?" По задумке выношу реализацию в отдельные функцииПромышленный код выглядит, как дерьмо, размазаное по потолку криворукими обезьянами.
> и в main оставляю только общую логику и организацию данных. На
> данном этапе на простых программах это избыточный код, но может быть
> такая привычка даст результаты в будущем?Результатом будет промышленный код. Писать нужно просто. Чем проще, тем лучше. Чтобы можно было с первого взгляда понять, что ты делаешь. Без углубления в общую логику и организацию данных.
> Второй: "Как правильно учиться?" Где то прочел: пока не знаешь как устроенны
> и работают простые библиотечные функции не используй их, а пиши свои
> реализации". ПОДЧЕРКНУ: совет для стадии обучения. Мне он понравился вот и
> леплю как могу.Мы поняли.
Обрати внимание, что в моём примере использована только одна библиотечные функция (не считая печати) - strlen. И не написана ни одна новая.Всё остальное сделано [за кадром] средствами операционной системы.
> Что думаете о выше поставленных вопросах?Научишься. Попробуй найти книгу https://search.rsl.ru/ru/record/01001496775
И ещё - никогда не используй глобальные переменные.
> И ещё - никогда не используй глобальные переменные.А goto ему можно использовать?
>> И ещё - никогда не используй глобальные переменные.
> А goto ему можно использовать?Это не некропост, просто пришлось подумать.
Если не использовать heap, а всю память брать из stack, то exception реализуется очень просто - переставляешь stack и выполняешь goto.
Походу malloc - крайне вредная функция. Это же COMMON BLOCK из FORTRAN.
А вот я терпеть не могу стиль с { на той же строке.
Но это ладно, тут звезда сразу после типа - может подбить новичка думать, что звезда - часть типа.
Да и по паре действий в каждом if внизу не особо нужны.
Обычно учат вводить данные прямо с консольки, со stdin, в теории это должно чему-то научить, но по сути учит не умеющих в консольку людей ненавидеть консоль.
> Обычно учат вводить данные прямо с консольки, со stdin, в теории это
> должно чему-то научить,не чимунибуть, а работать с стдин. вы плять хеловордисты не умеете и элементарных консольных утилит написать, а уже передаете в поколение свою безмозглость.
>> Обычно учат вводить данные прямо с консольки, со stdin, в теории это
>> должно чему-то научить,
> не чимунибуть, а работать с стдин. вы плять хеловордисты не умеете и
> элементарных консольных утилит написать, а уже передаете в поколение свою безмозглость.Не каждой программе суждено быть фильтром.