Scanf не будет сканировать внутренние данные Struct

Мне нужна помощь!

Неважно, что я ввожу, я получаю тот же результат, как будто программа не читает ввод из scanf, какие-нибудь идеи?

Я попытался получить ввод отдельно, чтобы разделить scanf, чтобы получить 8 scanf. Но безуспешно.

Если бы вы могли помочь мне и указать на то, что я делал неправильно, я был бы признателен!

 struct point{
  double x;
  double y;
 }pt1,pt2,pt3,pt4;

 struct rect{
      struct point pt1;
      struct point pt2;
      struct point pt3;
      struct point pt4;
 };

  int main()
 {
    struct rect new_screen = {
       scanf("%f,%f",&new_screen.pt1.x,&new_screen.pt1.y),
       scanf("%f,%f",&new_screen.pt2.x,&new_screen.pt2.y),
       scanf("%f,%f",&new_screen.pt3.x,&new_screen.pt3.y),
       scanf("%f,%f",&new_screen.pt4.x,&new_screen.pt4.y),
    };
       printf("the middle between (%.2f,%.2f) and (%.2f,%.2f) is ",new_screen.pt1.x,new_screen.pt1.y,new_screen.pt3.x,new_screen.pt3.y);
       print_point(middle(new_screen.pt1,new_screen.pt3));
   return 0;
 }



    struct point middle(struct point pt1, struct point pt2)
    {
        struct point tmp = {((pt1.x+pt2.x)/2),((pt1.y+pt2.y)/2)};
        return tmp;
    }
    void print_point(struct point pt)
    {
        printf("(%.2f,%.2f)",pt.x,pt.y);
    }

     output 
     the middle between (2.00,2.00) and (0.00,0.00) is (1.00,1.00)

Вы используете формат %f для чтения значений double. Это неопределенное поведение (%f для типов float; %lf для double). Современные компиляторы обычно предупреждают об этом; если у вас нет, найдите варианты включения предупреждений или получите лучший компилятор.

Jonathan Leffler 02.05.2018 09:10

Пожалуйста, всегда включайте предупреждения в вашем компиляторе. Для GCC вы должны добавить -Wall -Wextra -Wpedantic. Это покажет вам ряд предупреждений.

Gerhardh 02.05.2018 09:13
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это здесь инициализация ...

struct rect new_screen = {
   scanf("%f,%f",&new_screen.pt1.x,&new_screen.pt1.y),
   scanf("%f,%f",&new_screen.pt2.x,&new_screen.pt2.y),
   scanf("%f,%f",&new_screen.pt3.x,&new_screen.pt3.y),
   scanf("%f,%f",&new_screen.pt4.x,&new_screen.pt4.y),
};

... не делает то, что вы думаете. scanf возвращает одно целое число (см. Его справочную страницу, чтобы узнать значение возвращаемого значения), но ваша структура содержит поля struct point. В сумме получается 8 дублей и 4 звонка на scanf. Из-за того, как инициализация работает в C, вы можете опустить фигурные скобки и инициализаторы для некоторых полей. Так что это, к сожалению, действительный код. Но он инициализирует только new_screen.pt1 и new_screen.pt2 (четыре вызова scanf инициализируют четыре двойных). То, что вы отсканировали в них, немедленно перезаписывается. Последние две точки не инициализируются фигурными скобками, поэтому они должны начинаться с нуля, снова перезаписывая все, что вы, возможно, отсканировали в них.

Короче говоря, предполагая, что все вызовы scanf не терпят неудачу (и мы игнорируем проблему со спецификаторами формата), вы, по сути, написали следующее:

struct rect new_screen = {
  { 2, 2 },
  { 2, 2 },
  { 0, 0 },
  { 0, 0 }
};

Менее ошибочной инициализацией будет:

struct rect new_screen;
scanf("%lf,%lf",&new_screen.pt1.x,&new_screen.pt1.y);
scanf("%lf,%lf",&new_screen.pt2.x,&new_screen.pt2.y);
scanf("%lf,%lf",&new_screen.pt3.x,&new_screen.pt3.y);
scanf("%lf,%lf",&new_screen.pt4.x,&new_screen.pt4.y);

Он не проверяет, что scanf прошел успешно (поэтому это только менее ошибочный), но он не будет вытеснять содержимое new_screen возвращаемым значением scanf. Я также исправил спецификатор формата (вы использовали %f, но переменные double требуют %lf).

Вышеупомянутые ошибки также свидетельствуют о том, насколько важна компиляция с включенными предупреждениями и как их устранять. Например, когда я скомпилировал ваш код с помощью gcc -pedantic-errors -Wall -Wextra, я получил следующие предупреждения:

warning: format '%f' expects argument of type 'float *', but argument 2 has type 'double *' [-Wformat=]
    scanf("%f,%f",&new_screen.pt1.x,&new_screen.pt1.y),

warning: missing braces around initializer [-Wmissing-braces]
    struct rect new_screen = {

warning: missing initializer for field 'pt3' of 'struct rect' [-Wmissing-field-initializers]
    };

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

Хорошо видно по запятым. Я думаю, что начинающему программисту нужно немного больше объяснений; это довольно незаметно.

Jonathan Leffler 02.05.2018 09:13

@JonathanLeffler - Хорошее предложение. Я попытался затронуть это немного больше в редактировании, надеюсь, достаточно, чтобы понять суть дела новичка. Я не знаю, как глубоко в это вникать, чтобы новичку не переборщить.

StoryTeller - Unslander Monica 02.05.2018 09:21

Я не знаю, слишком ли он подробен, но я могу предположить, что исходный инициализатор эквивалентен struct rect new_screen = { { 2, 2 }, { 2, 2 }, { 0, 0 }, { 0, 0 } };, потому что scanf() вызывает return 2 (если строки формата фиксированы), и эти возвращенные значения перезаписывают первые четыре элемента структур , а остальные поля инициализируются нулями после того, как вызовы scanf() установили значения. Таким образом, данные, считанные со стандартного ввода, стираются при инициализации. Я спорил, записывать ли в инициализаторах 2.0 вместо 2; лень оставила их целыми числами.

Jonathan Leffler 02.05.2018 09:29

@JonathanLeffler - Написание эквивалентного инициализатора - отличная идея. Я добавил это. Спасибо!

StoryTeller - Unslander Monica 02.05.2018 09:32

@JonathanLeffler - Проголосуйте за эти хорошие предложения находятся или нет. Так что все равно спасибо :)

StoryTeller - Unslander Monica 02.05.2018 09:34

@JonathanLeffler Большое спасибо! эта информация мне очень помогла! Я начал заниматься информатикой в ​​университете из интереса. Это оказалось очень сложно, но, поскольку такие люди, как вы, я продолжаю изучать что-то новое каждый раз, когда сталкиваюсь с проблемой, спасибо!

Milo 02.05.2018 10:04

@StoryTeller, спасибо! еще один вопрос - будет ли сканирование данных во внутренние структурные переменные лучше выполняться с помощью malloc?

Milo 02.05.2018 10:07

@YaroslavMiloslavsky - не понимаю, зачем тут нужен malloc. Нет никакого обращения к динамическому распределению памяти.

StoryTeller - Unslander Monica 02.05.2018 10:09

Другие вопросы по теме