读取文件,并从临时变量

时间:2017-12-14 00:01:09

标签: c

最终目标是从文件创建一个字符串数组。所以我有一个文件,我需要从temp1,temp2,temp3等获取临时变量。我不知道提前有多少。我的第一个想法是从我使用strcat找到的变量创建一个普通字符串,然后使用标记拆分它。我以为我可以通过正常添加字符串来绕过这个。

while(feof(inputFile))
{ 
    fscanf(inputFile, " %s ", readIn);

    if(strcmp("AND", readIn) == 0 || strcmp("OR", readIn) == 0 || strcmp("NAND", readIn) == 0 || strcmp("NOR", readIn) == 0 || strcmp("XOR", readIn) == 0)
    {
        fscanf(inputFile,  "%s ", readIn);
        fscanf(inputFile,  "%s ", readIn);
        fscanf(inputFile, "%s ", tempVar);
        //printf("the char is %c", tempVar[0]);

        //check to see if  its a temp variable since temps are always lower case
        if(tempVar[0] == 't')
        {
            numVars++;
            tempHeaders = realloc(tempHeaders, sizeof(char*) * numVars);
            int temp = numVars -1;
            printf("the variable is %s and the number is %d\n", tempVar, temp);
            tempHeaders[numVars - 1] = tempVar;
        }                       

        numGates++;
    }
}

此时变量的数量是正确的,问题是在添加到数组tempHeaders时。数组的整个值将是文件的最后一个字,即如果最后一个字是out。 tempHeaders i - n都会出局。有任何想法吗?谢谢

我已经从while循环编辑了feof并更改为"而(fscanf(inputFile,"%s",readIn)!= EOF){"

样本输入将是

OR IN1 IN2 temp1
OR IN3 IN4 temp2
OR IN5 IN6 temp3
OR IN7 IN8 temp4
AND temp1 temp2 temp5
AND temp3 temp4 temp6
XOR temp2 temp6 OUT1

此时的样本输出

the variable is temp1 and the number is 0
the variable is temp2 and the number is 1
the variable is temp3 and the number is 2
the variable is temp4 and the number is 3
the variable is temp5 and the number is 4
the variable is temp6 and the number is 5
Printing OUT1 
Printing OUT1 
Printing OUT1 
Printing OUT1 
Printing OUT1 
Printing OUT1 
numGates = 7, numVars = 6 

印刷品应该是temp1,temp2,temp3等......

1 个答案:

答案 0 :(得分:1)

我做了一个工作样本来做我认为你打算做的事情:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char* strdup(const char *str)
{
  int len = strlen(str);
  char *str2 = malloc((len + 1) * sizeof (char));
  if (str2) strcpy(str2, str);
  return str2;
}

int main()
{
  FILE *f = stdin;
  /** @todo evaluation of command line arguments could
   * check whether input file given
   * and in that case override f with fopen().
   */
  /* read input */
  if (!f) {
    fprintf(stderr, "ERROR: Cannot read input!\n");
    return 1;
  }
  int nGates = 0, nVars = 0;
  char **vars = NULL;
  char buffer[80];
  for (int iLine = 1; fgets(buffer, sizeof buffer, f); ++iLine) {
    char *op = strtok(buffer, " \t\r\n");
    if (!op
      || strcmp(op, "AND") != 0 && strcmp(op, "OR") != 0 && strcmp(op, "XOR") != 0
      && strcmp(op, "NAND") != 0 && strcmp(op, "NOR") != 0) {
      fprintf(stderr, "ERROR in line %d: OP expected!\n", iLine);
      continue;
    }
    char *var;
    while (var = strtok(NULL, " \t\r\n")) {
      if (var[0] == 't') {
        ++nVars;
        vars = realloc(vars, sizeof (char*) * nVars);
        if (!vars) {
          fprintf(stderr, "ERROR: Out of memory!\n");
          return 1;
        }
        int iVar = nVars - 1;
        vars[iVar] = strdup(var);
        if (!vars[iVar]) {
          fprintf(stderr, "ERROR: Out of memory!\n");
          return 1;
        }
        printf("Var. #%d: '%s'\n", iVar, var);
      }
    }
    ++nGates;
  }
  /* evaluate input */
  printf("Report:\n");
  printf("nGates: %d, nVars: %d\n", nGates, nVars);
  for (int i = 0; i < nVars; ++i) {
    printf("vars[%d]: '%s'\n", i, vars[i]);
  }
  /* done */
  return 0;
}

我在cygwin上测试了bash中的代码(在Windows 10上):

$ gcc --version
gcc (GCC) 6.4.0

$ gcc -std=c11 -o testStrtok testStrtok.c

$ ./testStrtok <<'EOF'
OR IN1 IN2 temp1
OR IN3 IN4 temp2
OR IN5 IN6 temp3
OR IN7 IN8 temp4
AND temp1 temp2 temp5
AND temp3 temp4 temp6
XOR temp2 temp6 OUT1
EOF
Var. #0: 'temp1'
Var. #1: 'temp2'
Var. #2: 'temp3'
Var. #3: 'temp4'
Var. #4: 'temp1'
Var. #5: 'temp2'
Var. #6: 'temp5'
Var. #7: 'temp3'
Var. #8: 'temp4'
Var. #9: 'temp6'
Var. #10: 'temp2'
Var. #11: 'temp6'
Report:
nGates: 7, nVars: 12
vars[0]: 'temp1'
vars[1]: 'temp2'
vars[2]: 'temp3'
vars[3]: 'temp4'
vars[4]: 'temp1'
vars[5]: 'temp2'
vars[6]: 'temp5'
vars[7]: 'temp3'
vars[8]: 'temp4'
vars[9]: 'temp6'
vars[10]: 'temp2'
vars[11]: 'temp6'

$ 

注意:

  1. 我在OP的代码中找到realloc()来调整变量数组的大小(OP tempHeader,我的vars。我没找到的 - 为变量名本身分配内存。我使用了strdup()

  2. 我可以发誓我过去总是使用strdup()#include <string.h>用于正确的原型)。然而,gcc抱怨并且我发现:

      

    作为动态内存TR中的所有函数,如果实现定义了__STDC_ALLOC_LIB__,并且用户在包含string.h之前将__STDC_WANT_LIB_EXT2__定义为整数常量1,则只保证strdup可用。

    <{3>}中的

    我刚刚制作了自己的版本 - 它并不太复杂。

  3. cppreference.com就是这样一个功能......嗯。它已经很老了,并且有局限性,在某些情况下会使它变得危险。 (例如,你不应该在线程中使用它。)但是,除了这些问题之外,它完全满足需要(并且在此代码中没有多线程)。

  4. 我使用了一个固定大小的输入缓冲区char buffer[80];来保持样本的简短。在一个高效的项目中,我当然会做一些更复杂的事情,能够阅读“任意”长度的行 - 我当然需要更多的代码。

  5. 在OP的预期输出中,没有重复的变量。但是,代码示例不提供任何试图阻止它的代码。因此,我没有那么好。为此,必须插入以下代码(在++nVars;的唯一出现之前):

    int found = 0;
    for (int i = 0; i < nVars; ++i) {
      if (found = (strcmp(var, vars[i]) == 0)) break;
    }
    if (found) continue; /* continues the while (var = strtok(NULL, " \t\r\n")) loop */
  6. 提供的代码不会free()分配的内存。这是一个问题 - 操作系统将在离开main()后完成这项工作。但是,“干净”的解决方案是通过以下方式明确清除vars

    /* clean-up */
    for (int i = 0; i < nVars; ++i) free(vars[i]);
    free(vars);
  7. 建议更改为5.,输出为:

    $ gcc -std=c11 -o testStrtok testStrtok.c
    
    $ ./testStrtok <<'EOF'
    OR IN1 IN2 temp1
    OR IN3 IN4 temp2
    OR IN5 IN6 temp3
    OR IN7 IN8 temp4
    AND temp1 temp2 temp5
    AND temp3 temp4 temp6
    XOR temp2 temp6 OUT1
    EOF
    Var. #0: 'temp1'
    Var. #1: 'temp2'
    Var. #2: 'temp3'
    Var. #3: 'temp4'
    Var. #4: 'temp5'
    Var. #5: 'temp6'
    Report:
    nGates: 7, nVars: 6
    vars[0]: 'temp1'
    vars[1]: 'temp2'
    vars[2]: 'temp3'
    vars[3]: 'temp4'
    vars[4]: 'temp5'
    vars[5]: 'temp6'
    
    $
    

    strtok()

    上的现场演示