2016-08-07 2 views
-1

Итак, я пытаюсь написать программу виртуального компьютера, которая читает данные из stdin. STDIN продолжает прибывать в виде (%d %s %d), данные в основном представляет собой программу с определенной задачей и выглядят следующим образом:Функция не читается из stdin правильно

01 READ 60 
02 LOAD 60 
03 SUB 61 
04 STOR 60 
05 BRNG 15 
06 READ 70 
07 LOAD 70 
08 ADD 80 
09 STOR 80 
10 LOAD 60 
11 SUB 61 
12 STOR 60 
13 BRNG 15 
14 BRAN 6 
15 WRIT 80 
16 HALT 99 
61 SET 1 
80 SET 0 

Существует функция, которая работает как компилятор и должна читать в тех данные по очереди, но по какой-то причине, когда эта функция работает, я получаю «программа неправильного формата теперь выйдет». Я пытаюсь понять, почему это происходит какое-то время, без каких-либо подсказок.

Программа читается в потоке stdin по строкам, и она должна останавливаться, когда больше нет stdin, и он должен проверить правильность формата и действительно ли он в правильном формате, так почему он не читает его правильно ? Моя личная догадка заключалась в том, что по какой-то причине он не читает строки за строкой, но я не уверен, что все!

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

int compile (int memory [], int* instructionCounter , int* instructionRegister ,int*operationCode ,int* operand){ 
    char s[80]; /* The buffer */ 
    *instructionRegister=0; 
    *operationCode=0; 
    while(((*instructionRegister)=scanf("%d %s %d", operationCode,s,operand)) != NULL){ /*Reads data line by line then stores the integer returned by fscanf to instructionRegister pointer so that I can check for formating */ 
     if((*instructionRegister) ==3){ /*Checks for improper format by comparing the current instructionRegister count to 3, returns improper format otherwise */ 
      if(*operand >9999|| *operand <0){ /* Checks for word overflow in compiler, makes sure that digits do not exceed 9999 */ 
       printf("attempts to place a word in memory that is larger than 4 digits, or attempted to pass in a negative value\n "); 
       exit(0); 
      } 
      /*Compares the string section of the code and checks if it matches the following words and then it converts it to it's 4 digit value by adding into it the operand */ 
      if(strcmp(s,"READ") == 0) { 
       memory[*operationCode] = 10 * 100 + *operand; 
      } 
      else if(strcmp(s,"WRIT") == 0) { 
       memory [*operationCode] = 11 * 100 + *operand; 
      } 
      else if(strcmp(s,"LOAD") ==0){ 
       memory [*operationCode] = 20 * 100 + *operand; 
      } 
      else if(strcmp(s,"PRNT") ==0){ 
       memory [*operationCode] = 12 * 100 + *operand; 
      } 
      else if(strcmp(s,"STOR") ==0){ 
       memory [*operationCode] = 21 * 100 + *operand; 
      } 
      else if(strcmp(s,"SET") ==0){ 
       memory [*operationCode] = *operand; 
      } 
      else if(strcmp(s,"ADD") ==0){ 
       memory [*operationCode] = 30 * 100 + *operand; 
      } 
      else if(strcmp(s,"SUB") ==0){ 
       memory [*operationCode] = 31 * 100 + *operand; 
      } 
      else if(strcmp(s,"DIV") ==0){ 
       memory [*operationCode] = 32 * 100 + *operand; 
      } 
      else if(strcmp(s,"MULT") ==0){ 
       memory [*operationCode] = 33 * 100 + *operand; 
      } 
      else if(strcmp(s,"MOD") ==0){ 
       memory [*operationCode] = 34 * 100 + *operand; 
      } 
      else if(strcmp(s,"BRAN") ==0){ 
       memory [*operationCode] = 40 * 100 + *operand; 
      } 
      else if(strcmp(s,"BRNG") ==0){ 
       memory [*operationCode] = 41 * 100 + *operand; 
      } 
      else if(strcmp(s,"BRZR") ==0){ 
       memory [*operationCode] = 42 * 100 + *operand;; 
      } 
      else if(strcmp(s,"HALT")==0){ 
       memory [*operationCode] =9999; 
      } 

      else { /* Prints back to the user that the compiler did not recognize one of them commands as it was going through it */ 
       printf ("This is an unknown command, commands are case sensitive, program will now exit \n"); 
       exit(0); 

      } 
     } 
     else{ /* Returns improper format if instructionRegister does not match 3*/ 
      printf("Improper Format, program will now exit \n"); 
      exit(0); 
     } 

    } 
    /* Checks if the instruction data contains a HALT, if not it would terminate */ 
    while(*instructionCounter<100){ 
     if (memory[*instructionCounter] == 9999){ 
      return 1; 
     } 
     else 
      (*instructionCounter)++; 
    } 
    printf("Halt was not found, program will now exit"); 
    exit (0); 
} 

Желаемая цель этой функции - считывать данные по строкам и хранить их в виртуальных ячейках памяти. Он должен проверить формат этих строк %d %c %d, чтобы он мог извлечь данные и сохранить их в памяти соответственно.

+3

Просьба указать [Минимальный, полный и проверенный пример] (http://stackoverflow.com/help/mcve) с некоторым примером входных данных и желаемого поведения. – MikeCAT

+1

Возможно, вы захотите прочитать [ссылку 'scanf' (и семейство)] (http://en.cppreference.com/w/c/io/fscanf). Функции не возвращают указатель, поэтому вы не должны сравнивать возвращаемое значение с 'NULL'. –

+0

Я переключил NULL на feof (stdin), но он все еще выдавал мне ошибку! –

ответ

0

Ваша проблема эта линия:

while(((*instructionRegister)=scanf("%d %s %d", operationCode,s,operand)) != NULL){ 

scanf() функция возвращает

  • количество успешных преобразований, который будет что-нибудь от 0 до 3, или
  • EOF в случае возникновения сбоя ввода (конец файла или ошибки чтения) перед успешным конверсией рений. Макрос EOF - некоторое отрицательное число, обычно -1.

Вы сравнивая возвращаемое значение NULL которое 0 (или (void *)0 или аналогичный). При вводе, который вы предоставили, цикл while будет продолжать считывание до тех пор, пока scanf() не вернет EOF. Это не сломается из цикла while, но это не получится следующий тест:

if((*instructionRegister) ==3){ 
     /* big snip */ 
    else{ 
     printf("Improper Format, program will now exit \n"); 
     exit(0); 
    } 

Решение, конечно, сравнить результат EOF вместо NULL.


Существует также потенциал переполнения буфера в вашем scanf() вызова. Спецификатор преобразования %s заставит scanf() писать за пределами буфера s[], если строка длиннее 79 символов. (Не забывайте, что это будет также написать окончание \0.)

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

scanf ("%d %79s %d", /*...*/) 

Если входная строка длиннее, чем 79 символов, вход будет не в состоянии соответствовать пробелы перед модификатором "%d" и scanf() будет возвращать 2, чтобы указать неполный результат.

+0

Большое спасибо за ответ, но я все еще переполняю! Переполнение плавающей точки и слов, я думаю, что Scanf не сканирует должным образом. До того, как я внес изменения в свою программу, я сканировал ее из файла с помощью fscanf и программы работал нормально, но когда я переключился на STDIN, он больше не будет работать. –

+0

@Mohammed: в коде, который вы опубликовали, нет плавающей запятой. Возможно, вам стоит опубликовать новый вопрос с кодом, который имеет отношение к этим проблемам –

+0

Я могу опубликовать всю программу, но она длинная. В основном у меня есть две функции, которые проверяют наличие ошибок: int checkSegmentationFa ult (int * operand) { if (* operand <0 || * operand> 100) { printf ("СЕГМЕНТАЦИЯ НЕИСПРАВНОСТЬ: Попытка получить доступ к неизвестному адресу \ n"); выход (0); } возвращение 0; } –

Смежные вопросы