URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 10411
[ Назад ]

Исходное сообщение
"Проблема новичка "

Отправлено A6e3iana , 14-Янв-22 10:51 
Всем доброго времени суток. Изучаю программирование и решая задачу столкнулся с проблемой, нуждаюсь в объяснении что я делаю не так. Приступим:
Задача 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;
}


Содержание

Сообщения в этом обсуждении
"Проблема новичка "
Отправлено Аноним , 14-Янв-22 17:02 
Проблема в незнании сей. На глаз сразу вижу что гетстринг не работает, дальше и смотреть не хочется.



"Проблема новичка "
Отправлено parad , 15-Янв-22 09:42 
>[оверквотинг удален]
>         }
>         if (countword==number && str[i]!='
> ' && k<=wordsize-1) {
>            
> word[k]=str[i];
>            
> k++;
>         }
>         prev=str[i];
>     }

в этом цикле нету инкремента i.


"Проблема новичка "
Отправлено A6e3iana , 15-Янв-22 11:57 

> в этом цикле нету инкремента i.

Большое спасибо! Всё заработало! Даже обидно на невнимательности завалиться :(


"Проблема новичка "
Отправлено ACCA , 17-Янв-22 21:09 
Хороший пример, как НЕ НУЖНО писать программы. Сравни с этим:


#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;
}


"Проблема новичка "
Отправлено A6e3iana , 18-Янв-22 10:02 
> Хороший пример, как НЕ НУЖНО писать программы. Сравни с этим:

Приветствую! Спасибо за комментарий! Очень важен для меня ибо поднимает актуальные вопросы.

Первый: "Как выглядит промышленный код?" По задумке выношу реализацию в отдельные функции и в main оставляю только общую логику и организацию данных. На данном этапе на простых программах это избыточный код, но может быть такая привычка даст результаты в будущем?

Второй: "Как правильно учиться?" Где то прочел: пока не знаешь как устроенны и работают простые библиотечные функции не используй их, а пиши свои реализации". ПОДЧЕРКНУ: совет для стадии обучения. Мне он понравился вот и леплю как могу.

Из Примера подчеркнул:
Проверку входный данных - полезно, ЗАПОМНЮ!
Введение переменной хранящей разницу вместо постоянного сравнения и её имя "diff". ЗАПОМНЮ!
Это вообще мрак придумывать имена для переменных на англ да ещё как можно короче.

Что думаете о выше поставленных вопросах?



"Проблема новичка "
Отправлено Конч , 18-Янв-22 20:40 
>На данном этапе на простых программах это избыточный код, но может быть такая привычка даст результаты в будущем?

Изменения в конкретной функции затрагивают её поведение. Если ты кладёшь весь код в одну функцию и в ней много кода, при изменении может много что сломаться. Ну и лично у меня есть правило не класть в одну функцию кода больше, чем помещается на экране, правда вот, на си я обычно не пишу, на си бы я лимит строк мог бы и увеличить, возможно.
Просто если это читает другой человек, то для того, чтобы понять смысл функции, ему придётся мотать функцию туда-сюда. Если же она примерно умещается на экране (25-50 строк где-то - мой верхний лимит обычно), то и мотать не придётся.

>Где то прочел: пока не знаешь как устроенны и работают простые библиотечные функции не используй их, а пиши свои реализации

В принципе, совет хороший, вместе с алгоритмами учить, как делаются вот такие вот вещи. Жалко, что меня на такое не хватило, хотелось бы поизучать...
Но помимо этого стоит ещё читать чужой код. Я не читал и имею с этого последствия в понимании.

>Проверку входный данных - полезно, ЗАПОМНЮ!

По идее, везде, где есть внешние данные, должны быть проверки или слои проверок для того, чтобы не ставить кордоны по периметру внутреннего кода. Сверху, снизу, сбоку и так далее. Защитному программированию вообще никто не учит, а жалко.


"Проблема новичка "
Отправлено Конч , 18-Янв-22 20:41 
>затрагивают её поведение

Могут затрагивать.


"Проблема новичка "
Отправлено ACCA , 21-Янв-22 23:55 
> Первый: "Как выглядит промышленный код?" По задумке выношу реализацию в отдельные функции

Промышленный код выглядит, как дерьмо, размазаное по потолку криворукими обезьянами.


> и в main оставляю только общую логику и организацию данных. На
> данном этапе на простых программах это избыточный код, но может быть
> такая привычка даст результаты в будущем?

Результатом будет промышленный код. Писать нужно просто. Чем проще, тем лучше. Чтобы можно было с первого взгляда понять, что ты делаешь. Без углубления в общую логику и организацию данных.


> Второй: "Как правильно учиться?" Где то прочел: пока не знаешь как устроенны
> и работают простые библиотечные функции не используй их, а пиши свои
> реализации". ПОДЧЕРКНУ: совет для стадии обучения. Мне он понравился вот и
> леплю как могу.

Мы поняли.
Обрати внимание, что в моём примере использована только одна библиотечные функция (не считая печати) - strlen. И не написана ни одна новая.

Всё остальное сделано [за кадром] средствами операционной системы.


> Что думаете о выше поставленных вопросах?

Научишься. Попробуй найти книгу https://search.rsl.ru/ru/record/01001496775

И ещё - никогда не используй глобальные переменные.


"Проблема новичка "
Отправлено Конч , 30-Янв-22 16:51 
> И ещё - никогда не используй глобальные переменные.

А goto ему можно использовать?


"Проблема новичка "
Отправлено ACCA , 09-Апр-22 11:19 
>> И ещё - никогда не используй глобальные переменные.
> А goto ему можно использовать?

Это не некропост, просто пришлось подумать.

Если не использовать heap, а всю память брать из stack, то exception реализуется очень просто - переставляешь stack и выполняешь goto.

Походу malloc - крайне вредная функция. Это же COMMON BLOCK из FORTRAN.


"Проблема новичка "
Отправлено Конч , 18-Янв-22 20:25 
А вот я терпеть не могу стиль с { на той же строке.
Но это ладно, тут звезда сразу после типа - может подбить новичка думать, что звезда - часть типа.
Да и по паре действий в каждом if внизу не особо нужны.


"Проблема новичка "
Отправлено Конч , 18-Янв-22 20:28 
Обычно учат вводить данные прямо с консольки, со stdin, в теории это должно чему-то научить, но по сути учит не умеющих в консольку людей ненавидеть консоль.

"Проблема новичка "
Отправлено Аноним , 22-Янв-22 17:27 
> Обычно учат вводить данные прямо с консольки, со stdin, в теории это
> должно чему-то научить,

не чимунибуть, а работать с стдин. вы плять хеловордисты не умеете и элементарных консольных утилит написать, а уже передаете в поколение свою безмозглость.


"Проблема новичка "
Отправлено Конч , 30-Янв-22 16:50 
>> Обычно учат вводить данные прямо с консольки, со stdin, в теории это
>> должно чему-то научить,
> не чимунибуть, а работать с стдин. вы плять хеловордисты не умеете и
> элементарных консольных утилит написать, а уже передаете в поколение свою безмозглость.

Не каждой программе суждено быть фильтром.