如何防止C程序“挂起”?

4
我将尝试用我写的C程序(它应该像SICASM汇编器的第一遍一样)从SIC/XE程序中读取行。但是,如果SIC/XE代码的最后一行在助记符之后没有操作数,程序就会“挂起”(无法完成执行)。我只想摆脱这个问题,接下来将继续汇编。
这是获取输入的部分程序:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>

#define SIZE 51
#define LABEL_SIZE 9
#define MNEUMONIC_SIZE 8
#define OPERAND_SIZE 10

void getData(FILE* fpIn);
int hashFunc(char label[]);
unsigned long hex2int(char *a, unsigned int len);
bool checkMneumonic(char* mneumonic, int* bytes);

int main(int argc, char* argv[])
{
   FILE* fpIn = fopen(argv[1], "r");   
   if(fpIn != NULL)
      printf("\nFile open.");
   else
   {
      printf("\nError: Main needs an input file.\n");
      exit(EXIT_FAILURE);
   }

   getData(fpIn);

   fclose(fpIn);
   printf("\nFileClosed");

   printf("\n\n");
   return 0;
}

void getData(FILE* fpIn)
{
//debug printf("\nIn \"getData\" ");

   char label[LABEL_SIZE];
   char mneumonic[MNEUMONIC_SIZE];
   char operand[OPERAND_SIZE];
   int startAddr, currentAddr, PC = 0;
   bool gotValidMneu = true;
   int bytes;

   //open file for writing
   FILE* fpOut = fopen("output", "w");
   if(fpOut != NULL)
      printf("\n Ready to write.");

   fprintf(fpOut,"\n\tHash\tLabel\tAddress");

   char string1[10];
   char string2[10];
   int size;
   while( fscanf(fpIn, "%s", string1) != EOF)
   {         
      gotValidMneu = true;

      if(strcmp(string1, "LTORG") == 0)
         strcpy(string2, " ");
      else if(strcmp(string1, "RSUB") == 0)
         strcpy(string2, " ");
      else if(!feof(fpIn) && fgetc(fpIn) != '\n')
         fscanf(fpIn,"%s", string2);

      if(checkMneumonic(string1, &size) && !feof(fpIn))
      {
         strcpy(mneumonic, string1);
         strcpy(operand, string2);
         strcpy(label, " ");
      }
      else if(checkMneumonic(string2, &size) && !feof(fpIn))
      {
         strcpy(label, string1);
         strcpy(mneumonic, string2);
         fscanf(fpIn, "%s[\n]", operand);
      }
      else if( string1[0] == '.')
      {
         char junk[80];
         fgets(junk, 80, fpIn);
         gotValidMneu = false;
      }
      else
      {
         printf("\nError: got invalid mneumonic");
         gotValidMneu = false;
      }

      if(gotValidMneu)
      {
         //adjust the current address
         currentAddr = PC;

         //get the starting address
         if(strcmp(mneumonic, "START") == 0)
         {
            startAddr = hex2int(operand, strlen(operand) );
            PC = startAddr;
         }

         //mneumonic is "BASE"
         else if(strcmp(mneumonic, "BASE") == 0);

         //mneumonic is "RESW"
         else if(strcmp(mneumonic, "RESW") == 0)
         {
            PC += (3 * atoi(operand) );
         }

         //mneumonic is "BYTE"
         else if(strcmp(mneumonic, "BYTE") == 0 )
         {
            PC += atoi(operand);
         }

         //mneumonic is "END"
         else if(strcmp(mneumonic, "END") == 0);

         //check if the mneumonic is valid
         else if(checkMneumonic(mneumonic, &bytes) )
         {
            PC += bytes;
         }

         //got a bad mneumonic
         else
         {
            gotValidMneu = false;
            printf("\nError: \"%s\" is not a valid mneumonic.", mneumonic);
            fprintf(fpOut,"\nError: \"%s\" is not a valid mneumonic.", 
                    mneumonic);
         }

         if(gotValidMneu)
         {
            if(strcmp(label, " ") != 0 )
               fprintf(fpOut,"\n\t%d\t%s\t%x", hashFunc(label), label, 
                       currentAddr);
            printf("\n%x\t%s\t%s\t%s", currentAddr, label, mneumonic, operand);
         }

      }

      if(gotValidMneu)
      //flush the comments, if any
      while( '\n' != getc(fpIn) )
         getc(fpIn);

   } //end while
   fprintf(fpOut,"\n");
   fclose(fpOut);
   printf("\n Symbol table sent to file: \"output\".");
}

int hashFunc(char label[])
{
   int i, sum, hashVal;
   sum = 0;

   for(i = 0; i < strlen(label); i++)
      sum += label[i];

   hashVal = sum % SIZE;
//   printf("\nHashed Index: %d", hashVal);

   return hashVal;
}

unsigned long hex2int(char *a, unsigned int len)
{
    int i;
    unsigned long val = 0;

    for(i=0;i<len;i++)
       if(a[i] <= 57)
        val += (a[i]-48)*(1<<(4*(len-1-i)));
       else
        val += (a[i]-55)*(1<<(4*(len-1-i)));
    return val;
}

bool checkMneumonic(char mneumonic[], int* bytes)
{
   bool valid = false;
   char validMneumonic[MNEUMONIC_SIZE];

   FILE* fpIn = fopen("sicOps", "r");

   while( (fscanf(fpIn, "%s %d", validMneumonic, bytes) != EOF) )
   {
      if(strcmp(mneumonic, validMneumonic) == 0 )
      {
         valid = true;
         break;
      }
   }

   fclose(fpIn);
   return valid;
}

这里是我用来测试的文件:

ADDRES    START    100
. tests pc forward addressing
. tests base addressing
. tests pc backward addressing
NOW      +LDB     #BEGIN              load base register
XXX       BASE     BEGIN              tell assembler
YYY       LDA      BE                 A <- (m..m+2)
EN        RESW     4
BE        WORD     2
BEGIN     RESW     1
JUNK      RESW     2200
THERE     RESW     1
ZZZ       LDA      JUNK
MMM       STA      THERE
          END 

编辑:有很多新的代码。我简化了原始程序,编译和测试了它,但它卡住了。

3个回答

4

你的I/O代码看起来非常复杂(尽管只有这么几行代码)。

最好将整行读入缓冲区,然后在内存中分析该缓冲区,而不是试图实时决定如何构造读取过程。

只需使用fgets()来加载行,如果有的话可以使用getline()

回应评论,当然你仍然需要决定如何解析行,但不会存在“挂起”程序等待不存在的输入的风险。

你的行似乎由多达三个标记组成,由空格分隔,可选地跟随一条跨越整行的注释。应该不难想出如何将其拆分为这些部分。


在这种情况下,我还是需要决定是否解析,对吧?例如,如果在字符串中没有剩余内容时我尝试解析会发生什么?编辑:抱歉,我的意思是如果该行中只有一个字符串,并且我尝试从该行解析另一个字符串。 - IdeaSpy
是的,实际上Thiruvalluvar的帖子回答了那个问题。抱歉回复慢,我还在努力消化一切。 - IdeaSpy

1
使用fgets函数读取字符串,然后使用分词器将其拆分为以空格为分隔符的单词。在一个简单的for循环中使用strtok函数会使这个过程更加容易。

1

我不明白你发布的代码如何会挂起,无论是等待文件输入还是循环,因此似乎实际问题在于程序的其他地方。也许与发布的片段结合使用有关。

但我看到你使用了feof,这在C程序中几乎总是错误的,因为它只会在你达到文件末尾之后才返回true。应该使用各种输入调用的返回值。

编辑:

我实际上尝试了你的代码,添加了必要的最小代码,使其成为一个完整的可编译程序,并在你的示例输入上进行了尝试。它没有挂起。你应该始终尝试发布一个最小化、可工作的程序仍然表现出问题。现在你删除了似乎与问题相关的部分。


你说得对,我会再看一遍并编辑问题。 - IdeaSpy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接