EOF символ в XCode (Ctrl + D) - PullRequest
       11

EOF символ в XCode (Ctrl + D)

1 голос
/ 21 февраля 2010

Я выполняю задание hw, и мой профессор использует этот код для проверки нашей программы:

int main()
{
   const int SZ1 = 10;
   const int SZ2 = 7;
   const int SZ3 = 5;
   float array1[SZ1];
   float array2[SZ2];
   float array3[SZ3];

   DisplayValues(SortValues(GetValues(array1, SZ1), SZ1), SZ1);
   DisplayValues(SortValues(GetValues(array2, SZ2), SZ2), SZ2);
   DisplayValues(SortValues(GetValues(array3, SZ3), SZ3), SZ3);

   return EXIT_SUCCESS;
}

float *DisplayValues(float *p, size_t n)
{
   float previous = *p, *ptr, *end = p + n;

   setiosflags(ios_base::fixed);
   for (ptr = p; ptr < end; ++ptr)  // get each element
   {
      cout << *ptr << '\n';
      if (ptr != p)                 // if not first element...
      {
         if (previous < *ptr)       // ...check sort order
         {
            cerr << "Error - Array sorted incorrectly\n";
            return NULL;
         }
      }
      previous = *ptr;              // save this element
   }
   resetiosflags(ios_base::fixed);

   return p;
}
#endif

Я использую

float *GetValues(float *p, size_t n) 
{   
    float input;
    float *start = p;

    cout << "Enter " << n << " float values separated by whitespace: \n";

    while (scanf("%f", &input) == 1) {
        *p++ = input;
    }
    return start;
}

чтобы получить ввод из окна терминала в соответствии с его инструкциями, и использовать ctrl + d для ввода символа EOF, чтобы произошел первый вызов DisplayValues ​​(SortValues ​​(GetValues ​​(array1, SZ1), SZ1), SZ1). Однако остальная часть программы просто завершается, не позволяя мне снова вводить значения, когда DisplayValues ​​(SortValues ​​(GetValues ​​(array2, SZ2), SZ2), SZ2); называется. Есть ли причина или обходной путь для этого? Спасибо.

Ответы [ 2 ]

4 голосов
/ 21 февраля 2010

Символ CTRL D (шестнадцатеричный 04) сам по себе не является символом конца файла. Нажатие на эту последовательность клавиш сигнализирует драйверу терминала, что это конец входного потока, и любые дальнейшие чтения из этого потока будут обрабатываться так, как будто «файл» завершен. Фактически вы можете изменить символ, используемый для этого, с помощью команды stty в UNIX.

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

Но для этого потребуется вводить строки, а не числа с плавающей запятой (вы можете использовать fgets, чтобы получить строку, и sscanf, чтобы извлечь число с плавающей запятой после того, как вы проверили на наличие пустой строки).

Другая возможность - использовать -1 в качестве специального значения для часового режима (при условии, что -1 не является допустимым входным сигналом), но следите за сравнениями с плавающей запятой, иногда они не соответствуют ожидаемым.

Я предлагаю пойти по маршруту fgets/sscanf, но, поскольку вы должны получить n float, ваш GetValues должен идти примерно так:

float *GetValues (float *p, size_t n) {   
    float input;
    float *start = p;
    cout << "Enter " << n << " float values separated by whitespace: \n";
    while (scanf("%f", &input) == 1) {
        *p++ = input;
        if (--n >= 0)
            break;
    }
    return start;
}

, который перестанет получать значения, как только вы достигнете своего предела. Имейте в виду, что это не идеально. Я оставил там, по крайней мере, одну проблему из-за того, что это домашнее задание (в зависимости от ваших входных данных вы можете его не ударить).

Следует также отметить, что смешивать семантику ввода-вывода C ++ и C (cout и scanf) несколько необычно - вам действительно следует выбрать одну или другую. Если это назначение C ++, вы обнаружите, что C ++ имеет более богатый способ ввода / вывода. Если это C, то cout не имеет места в коде, и вам, вероятно, следует использовать printf. Я не говорю, что это не будет работать , просто это необычная смесь.

0 голосов
/ 21 февраля 2010

Проблема в использовании EOF в качестве разделителя. scanf будет читать в EOF, прежде чем он сможет получить следующий желаемый float. scanf вернет EOF, чтобы сообщить вам, что он нашел, но EOF не покинет буфер, поэтому при следующем вызове scanf он все равно будет читать EOF и сразу же возвращаться. См .: scanf

В вашей функции GetValues, поскольку у вас есть размер массива, вы должны просто читать числа до тех пор, пока у вас не будет столько чисел с плавающей запятой, вместо ожидания EOF. Таким образом вы предотвращаете переполнение, а также неправильно используете EOF.

...