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, Супермодераторы



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

Сейчас этот форум просматривают: mihaild


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

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