На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> вернуть поток stdin в дефалтное значение через freopen , C89 | C90
    Всем хай! Сходу к делу!

    Как известно, функцией freopen можно переназначать потоки. Штука интересная вроде бы.
    Например, нужно считать данные из файла (а не с консоли), то делаем так, например:

    ExpandedWrap disabled
          size_t records_count, i;
          const char* const name_file = "data.txt";
          freopen( name_file, "r", stdin );
       
          scanf( "%u", &records_count );
          for ( i = 0; i < records_count; i++ )
          {
              char buf[ 100 ];
              gets_s( buf, 99 );
              printf( "%s\n", buf );
          }


    теперь, например, функция gets_s хватает данные из файлового потока, а не консольного и не нужно юзать функцию аля fgets, передавая хендлер на файл и пр.

    Но проблема в том, как вернуть ОБРАТНО к дефалту, чтобы снова стал stdin, не прибегая к ВИНАПИ?? Может есть какой-то очень простой однострочный способ(

    пробовал так, но все рухнуло и все...
    ExpandedWrap disabled
          //freopen( NULL, "r", stdin );


    подскажите как быть-то?
      Цитата FasterHarder @
      Но проблема в том, как вернуть ОБРАТНО к дефалту, чтобы снова стал stdin, не прибегая к ВИНАПИ??
      Никак. freopen() предварительно закрывает поток, определяемый последним параметром, поэтому консольное устройство ввода (вывода), присоединённое к нему, более недоступно без повторного открытия. Но его можно просто открыть, пусть и fopen(). Проблема в том, что имена консольных устройств нестандартизированы, как ты верно заметил, так что без потери переносимости кода не напишешь.
      Возможно, тебе изначально имело смысл предусмотреть возможность параметризации потока, из которого читать.

      Добавлено
      Но пришлось бы, увы, пожертвовать
      Цитата FasterHarder @
      теперь, например, функция gets_s хватает данные из файлового потока, а не консольного и не нужно юзать функцию аля fgets, передавая хендлер на файл и пр.
        Qraizer, а вот смотри и поправь, плиз, если грубо ошибаюсь.
        Вроде как языку Си доступны 5 потоков: stdin (ввода), stdout (вывода), stderr (ошибок) и еще каких-то 2 неизвестных, но они есть...)

        По дефалту потоки stdin/stdout привязаны к консоли/дисплею, т е вводим с клавы и выводим на экран.
        Чтобы переключить поток stdin на файл(дисковый текстовый) можно сделать freopen, указать путь до файла, режим открытия и САМ ПОТОК, т е stdin.
        А, например, если надо переключить поток ВЫВОДА stdout НА ПРИНТЕР, как быть??? У файлов есть путь (имя), а у принтера что??

        Также, если пытаться переключиться, как ты говоришь через fopen обратно, то что указывать первым параметром (там путь char*), чтобы снова стал стандартный stdin с клавиатуры??

        Т е я не оч.понимаю такой момент: у файлов ЕСТЬ имя + все эти функции fopen, freopen как раз-таки требуют указать 1ым параметром путь и файлы подходят идеально, а вот для принтера, клавиатуры, экрана нет ведь пути (хотя где-то видел "CON" для назначения стандартного stdout на экран )

        поясни, плиз, эти моменты.

        Добавлено
        И все-таки странно, что можно переключить поток stdin с клавиатуры на файл, а обратно нельзя, хм...Неужели вся проблема в этом пути char*. Так-то ведь потоку все равно с чем работать "на том конце", будь-то файл, сканер, клавиатуры, трактор, океан и даже конфета, лишь оно имело соответствующий интерфейс...или я оч.грубо здесь ошибаюсь(
          Цитата FasterHarder @
          По дефалту потоки stdin/stdout привязаны к консоли/дисплею, т е вводим с клавы и выводим на экран.
          Именно потому, что нет стандартных имён этих устройств, Стандарт обязывает библиотеки времени выполнения сделать необходимые действия перед main(), чтобы программа просто уже могла с ними работать, если надо.
          Цитата FasterHarder @
          А, например, если надо переключить поток ВЫВОДА stdout НА ПРИНТЕР, как быть??? У файлов есть путь (имя), а у принтера что??
          Стандарт не определяет никаких предоткрытых потоков для принтеров. В конце концов работа с принтерами кардинально различается для разных моделей, стандартизировать там просто нечего.
          Цитата FasterHarder @
          Также, если пытаться переключиться, как ты говоришь через fopen обратно, то что указывать первым параметром (там путь char*), чтобы снова стал стандартный stdin с клавиатуры??
          Имя стандартного устройства ввода в твоей исполнительной среде.
          Цитата FasterHarder @
          Неужели вся проблема в этом пути char*.
          Да. Представь себе какую-нибудь STMку в стиралке. Какое у неё будет стандартное устройство ввода? У тебя это кнопки, ручки и регуляторы, а как это связывается с потоками ввода в прошивке? А может их вообще нет? А может быть там есть какой-нибудь отладочный интерфейс через RS-232? Стандарт не может ничего диктовать подобным приложениям.

          Добавлено
          Цитата FasterHarder @
          ... а вот для принтера, клавиатуры, экрана нет ведь пути (хотя где-то видел "CON" для назначения стандартного stdout на экран )
          В винде CON работает:
          ExpandedWrap disabled
            #include <stdio.h>
             
            void main( void )
            {
              FILE* p = fopen("CON", "at");
             
              fprintf(p, "Hello, world!\n");
              fclose(p);
            }
          Сообщение отредактировано: Qraizer -
            Qraizer, в целом так себе и представлял эти моменты с потоками, спс. за пояснения дополнительные!

            В общем можно выработать такие правила:
            1. Если в программе постоянно что-то вводится с клавиатуры и читается из файла, то не нужно ничего переназначать. Просто открывать все файлы через FILE*, fopen и все.
            2. Если программа заточена исключительно на считывание данных из файла, то можно направить stdin на заданный файл, при необходимости перенаправить на др. и пр., но при этом про ввод с консоли стоит позабыть)

            В общем можно вообще никогда не использовать этот freopen и все будет нормально в прожке, просто иногда (п.2) удобнее направить на файл.
            То есть в целом этот freopen каких-то колоссальных преимуществ не дает, а лишь ИНОГДА помогает упростить код..

            Qraizer, если в корне не согласен, то просьба пояснить.

            Добавлено
            для stdout есть "CON", неужели ничего нет для stdin(, как-то несправедливо)
              Цитата FasterHarder @
              для stdout есть "CON", неужели ничего нет для stdin(, как-то несправедливо)
              Почему это?
              ExpandedWrap disabled
                #include <stdio.h>
                 
                void main( void )
                {
                  FILE *p = fopen("CON", "at");
                  FILE *q = fopen("CON", "rt");
                  char  myName[16];
                 
                  fprintf(p, "How are you? "); fflush(p);
                  fscanf(q, " %15s", myName);
                  fprintf(p, "Hello, %s!\n", myName);
                 
                  fclose(q);
                  fclose(p);
                }
                Qraizer, спс за пояснения, тема достаточно интересная, но, как я понимаю, редко пригождается, поэтому эта тема на форуме будет мне служить подсказкой при необходимости, что да как :yes:
                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                0 пользователей:


                Рейтинг@Mail.ru
                [ Script execution time: 0,0334 ]   [ 16 queries used ]   [ Generated: 19.04.24, 15:21 GMT ]