2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Олимпиадное программирование, с++, ввод
Сообщение12.04.2015, 20:53 


25/12/14
78
Правила запрещают работу с файлами.

Например в задаче входной поток содержит набор целых чисел отделённых друг от друга произвольным количеством пробелов и переводов строк.

Как реализовать такое считывание данных в c++?

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение12.04.2015, 21:07 
Заслуженный участник


09/05/12
25179
Как раз при потоковом вводе-выводе (стандартном для C++) этой проблемы просто нет. Возьмите программу
Используется синтаксис C++
#include<iostream>

using namespace std;

int main()
{
        int a,b,c;
        cin >> a >> b >> c;
        cout << (a+b+c) << endl;
}
 

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

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение12.04.2015, 21:25 


25/12/14
78
Pphantom
Если мы не знаем сколько чисел будет вводиться?

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение12.04.2015, 21:40 
Заслуженный участник


09/05/12
25179
integer в сообщении #1003149 писал(а):
Если мы не знаем сколько чисел будет вводится?
А в чем разница?

Ну, например, такой вариант. Остановка - при вводе нуля.
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include<iostream>

using namespace std;

int main()
{
        int a,s=0;
        do
        {
                cin >> a;
                s+=a;
        }
        while(a);
        cout << s << endl;
}
 


P.S. Не обижайтесь, но, вообще говоря, при наличии проблем такого уровня заниматься олимпиадным программированием несколько рано.

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение12.04.2015, 22:16 


25/12/14
78
Pphantom
Ок, я наверное не могу объяснить нормально, что мне нужно конкретно. 0 не может останавливать ввод.

Вот оригинальное условие задачи.
Цитата:
Исходные данные
Входной поток содержит набор целых чисел A_i (0 ≤ A_i ≤ 10^18), отделённых друг от друга произвольным количеством пробелов и переводов строк. Размер входного потока не превышает 256 КБ.
Результат
Для каждого числа Ai, начиная с последнего и заканчивая первым, в отдельной строке вывести его квадратный корень не менее чем с четырьмя знаками после десятичной точки.

Исходные данные
1427 0

876652098643267843
5276538

Результат
2297.0716
936297014.1164
0.0000
37.7757



Уже как бы разобрался с проблемой. Тестирующая система принимает задание как правильное если использовать код с таким считыванием:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
#include <iomanip>
using namespace std;
struct stack
{
        double value;
        stack *next;
} *head;
stack *add(double);

stack *output();

int main()
{
        double value;
        while (cin >> value)
                head = add(value);

        output();
        system("pause");
        return 0;
}

stack *add(double value)
{
        stack *str = new stack;
        str->value = value;
        str->next = head;
        return str;
}


stack *output()
{
        stack *str;
        double value;
        while (head != 0)
        {
                str = head;
                value = sqrt(head->value);
                cout << fixed << setprecision(4) << value << endl;
                head = head->next;
                delete str;
        }
        return NULL;
}


 


-- 12.04.2015, 22:27 --

Pphantom в сообщении #1003156 писал(а):
P.S. Не обижайтесь, но, вообще говоря, при наличии проблем такого уровня заниматься олимпиадным программированием несколько рано.

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

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение12.04.2015, 22:31 
Заслуженный участник


09/05/12
25179
integer в сообщении #1003172 писал(а):
Ок, я наверное не могу объяснить нормально, что мне нужно конкретно. 0 не может останавливать ввод.

Вот оригинальное условие задачи.
С этого и нужно было начинать. :D

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение13.04.2015, 07:48 


27/08/14
206
Довольно странное условие. Обычно в этом случае вначале указывается количество чисел, чтобы участники думали над задачей, а не как правильно считать все данные :-).
Вот пример, как можно правильно считать данные:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>

using namespace std;

int main()
{
  while (true)
  {
    int a;
    cin >> a;
    if (!cin.good()) break;
    cout << a << endl;
  }
  return 0;
}
 


Кстати, если используете std, то нет необходимости изобретать свой стек - используйте стандартный.

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение13.04.2015, 08:52 


10/04/12
704
integer в сообщении #1003149 писал(а):
Pphantom
Если мы не знаем сколько чисел будет вводиться?


Закончился поток — значит все числа ввелись. Чем не вариант?

Используется синтаксис C++
#include <iostream>

int main()
{
    int a;
    while (std::cin >> a) {
        std::cout << a << std::endl;
    }

    std::cout << "Terminated" << std::endl;
    return 0;
}


Дает

Используется синтаксис Bash
$ g++ test.cpp
$ ./a.out
1 2 3 4
1
2
3
4
1 2
1
2
Terminated
 


Для того, чтобы послать конец потока в консоль, надо нажать Ctrl+D

Кстати, все решение у меня поместилось в четыре строки:

Используется синтаксис C++
#include <cmath>
#include <iomanip>
#include <iostream>
#include <stack>

using namespace std;

int main()
{
    stack<double> buf;
    for (double tmp; cin >> tmp; buf.push(tmp));
    for (; !buf.empty(); buf.pop())
        cout << fixed << setprecision(4) << sqrt(buf.top()) << endl;
    return 0;
}

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение13.04.2015, 18:24 


25/12/14
78
mustitz в сообщении #1003285 писал(а):
Закончился поток — значит все числа ввелись. Чем не вариант?

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

Оказывается, что в заданиях, если в задании
входные данные
первая строка содержит: 2
вторая строка содержит: 2 4 6
третья строка содержит: 3 3 3
выходные данные
yes
no

то результат программы может быть такой
Используется синтаксис Bash
$ g++ test.cpp
$ ./a.out
2
2 4 6
yes
3 3 3
no
 


Я думал, что должно быть строго как в примере.
Используется синтаксис Bash
$ g++ test.cpp
$ ./a.out
2
2 4 6
3 3 3
yes
no
 

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение13.04.2015, 19:29 


11/12/14
893
integer в сообщении #1003436 писал(а):
Я не очень разбираюсь как работают стандартные потоки в c++


Дело вообще не в С++, а скорее в POSIX и скажем так некотором стандарте как работают консольные программы в целом ряде операционных систем (обычно и говорится что они POSIX-совместимые). Есть такие понятия как стандартный ввод, стандартный вывод, переменные окружения, консоль и прочая и они вместе с файлами и прочим образуют некоторую типовую "среду исполнения" с некоторыми типовыми возможностями.
Растёт оно из юниксов, где запустив программу она получает "поток ввода" и "поток вывода", если запускать просто program.exe, то это консоль на ввод и консоль на вывод. Консоль тоже не просто так, а есть специфика как она работает - обычно она как раз и блокирует выполнение программы при считывании потока на ввод пока вы не нажмёте ENTER или завершение ввода (CTRL+D). Поэтому получается как получается, всё верно.
С другой стороны можно приказать под потоком ввода и/или вывода считать файлы в файловой системе, тогда программа будет их исправно считывать и работать "автономно": program.exe <input.txt >output.txt
Такой подход довольно распространён в мире юниксов и позволяет работать с программой и в "ручном" и в "автоматическом" режиме.

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение14.04.2015, 16:42 


25/12/14
78
А как сделать ввод до конца потока для scanf?
Нашел такой код на сайте посвященном олимпиадному программированию. Это правильно? И как послать конец ввода?
Используется синтаксис C++
int a;
while (scanf_s("%d", &a) != EOF)
{
...    
}
 


Просто такой код нормально работает.
Используется синтаксис C++
int a;
while (scanf_s("%d", &a))
{
...    
}
 

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение14.04.2015, 17:53 
Заслуженный участник


04/05/09
4582
Оба неправильные, хотя первый вариант неправильней. Второй сработает правильно только при отсутствии ошибок ввода.
Вам надо научится читать документацию. В ней написано, что возвращает функция scanf_s(), а именно: 0 в случае конца потока ввода, и EOF в случае ошибки ввода. А если ещё точнее, проверять надо на соответствие количеству вводимых полей - в данном случае это 1.

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение14.04.2015, 18:45 


25/12/14
78
venco
До конца входного потока и до конца потока это одно и тоже или нет?
Почему первый неправильней?
Допустим мы ошиблись при вводе и ввели символ. тогда условие
Используется синтаксис C++
scanf_s("%d", &a) != EOF
ложно и цикл прекращается.

-- 14.04.2015, 19:07 --

И почему если ввести не число, а символ, то программа зацикливается, а не прекращается?
Используется синтаксис C++
int n;
while (scanf("%d", &n) != EOF)
{
        cout << "!!!" << endl;
}

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение14.04.2015, 19:08 
Заслуженный участник


04/05/09
4582
integer в сообщении #1003855 писал(а):
venco
До конца входного потока и до конца потока это одно и тоже или нет?
Есть ещё выходной поток (stdout), и у него тоже может быть конец или ошибки.
integer в сообщении #1003855 писал(а):
Почему первый неправильней?
Допустим мы ошиблись при вводе и ввели символ. тогда условие
Используется синтаксис C++
scanf_s("%d", &a) != EOF
ложно и цикл прекращается.
Потому что в системе, которая будет тестировать ваш код не будет ошибок во входных данных, а вот конец как раз будет. Т.е. если проверять только конец (0), то код будет засчитан, а если проверять только ошибки (EOF=-1), то на конце ввода ваш код сломается.

 Профиль  
                  
 
 Re: Олимпиадное программирование, с++, ввод
Сообщение14.04.2015, 19:47 


25/12/14
78
venco в сообщении #1003868 писал(а):
если проверять только ошибки (EOF=-1), то на конце ввода ваш код сломается.

Все, понял.
Только не понятно, почему если ввести символ, то происходит зацикливание, а не выход из цикла
Используется синтаксис C++
int n;
while (scanf("%d", &n) != EOF)
{
        cout << "!!!" << endl;
}

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 19 ]  На страницу 1, 2  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group