簡體   English   中英

如何從文本文件(C)中讀取特定數據?

[英]How to read in specific data from a text file (C)?

我是C語言的新手(也是本網站的新手),並且對我正在從事的項目有疑問。 我卡住的部分是文件I / O東西,因為我在上一堂課中從未學過。 因此,輸入(.txt)文件如下所示:

REGISTERS
R5 11
R7 15
R21 4
MEMORY
4 12
12 92
[OTHER STUFF]

該文件為我們提供了任意的寄存器編號,后跟其內容(R0至31,省略了值為0的Regs)。 下一節將以類似的格式給出存儲位置,然后再次顯示內容。 然后是我以后可以處理的更多部分。

我的問題是:如何讀取寄存器/內存位置及其值? 目前,我有一個大小為32的數組來存儲內容,還有一個用於Reg號和值的變量(例如:Registers [regNumber] = regValue;),但是我不知道如何在單詞REGISTERS之后正確開始讀取值。

我試過的

我環顧四周,設法讀入只有一行的測試輸入文件:“ R5 11”。 為此,我做到了:

fscanf(file_ptr, "R%d %d", &regNumber, &regValue);

我打印了變量regNumber,regValue,它們正確地給了我5和11。但是,對於單詞REGISTERS之后的任意數量的行,我如何在單詞MEMORY處停下來呢?

我假定無論解決方案是什么,我都可以做同樣的事情來讀取MEMORY的位置和值。

您可以使用fgets()讀取文本文件的整行,然后使用strcmp或strncmp替換“ REGISTERS”和“ MEMORY”字符串文字的行。

您的input.txt格式化“ REGISTERS”之后的所有內容的格式都相同,直到“ MEMORY”為止,而“ MEMORY”之后的所有格式都相同。 盡管可能有更好的替代方法,但也許以下內容可能會起作用:

int main () {
   FILE *fp;
   char str[60];
   int input_type = 0; //you can enum this for the input types you have
   int line_num = 0;

   /* opening file for reading */
   fp = fopen("input.txt" , "r");
   if(fp == NULL) {
      perror("Error opening file");
      return(-1);
   }
   while( fgets (str, 60, fp)!=NULL ) { // dont really need the != NULL compare here.
      line_num++;
      /* Parse the next line in the file */
      if(strcmp(str,"MEMORY") == 0){
         //the next lines will be formatted like memory input lines
         input_type = 2; //This should be an enum or macro
         continue;
      }
      if(strcmp(str,"REGISTERS") == 0){
         //the next lines will be formatted like register input lines
         input_type = 1;//Also should be enum or macro
         continue;
      }
      switch(input_type){
         case 0:
            fprintf(stderr,"Failed to find REGISTER keyword%d\n",line_num);
            break;
         case 1:
            sscanf(str, "R%d %d", &regNumber, &regValue); //parse known string format
            do_something(&regNumber, &regValue);
            break;
         case 2:
            sscanf(str, "%d %d", &memNumber, &memValue); //parse known string format
            do_something_else(&memNumber, &memValue);
            break;
         default:
            fprintf(stderr,"Could not find input format at line %d\n",line_num);
            break;
      }
   }
   fclose(fp);

   return(0);
}

我不會在這里使用fscanf ,因為您無法向前看,看看下一行是REGISTERS還是MEMORY或其他。 從理論上講,您可以檢查fscanf的返回值,但是代碼很快就會變得非常混亂。

更好的解決方案是使用fgets來獲取整行。 如果該行等於REGISTERS\\n ,那么您知道下一行是寄存器行,等等。解析本身可以使用sscanf來完成,就像fscanf一樣,但是它不是從FILE*緩沖區中讀取,而是從字符串中讀取。

所以,我會做:

enum mode_t {
    REGISTERS = 0,
    MEMORY,
    ...,
    INVALID
};

int parse_file(FILE *file_ptr, int *registers, int some_other_params)
{
    if(file_ptr == NULL || registers == NULL)
        return 0;

    char line[1024];

    enum mode_t mode = INVALID;

    while(fgets(line, sizeof line, file_ptr))
    {
        if(strcmp(line, "REGISTERS\n") == 0)
        {
            mode = REGISTERS;
            continue;
        } else if(strcmp(line, "MEMORY\n") == 0) {
            mode = MEMORY;
            continue;
        } // keep adding if(strcmp.... as needed)

        if(mode == INVALID)
        {
            fprintf(stderr, "Invalid file format\n");
            return 0; // or a better error handling
        }

        int ret;
        switch(mode)
        {
            case REGISTERS:
                ret = parse_registers(line, registers);
                break;
            case MEMORY:
                ret = parse_memory(line, some_other_args);
                break;
            ...
        }

        // evaluate ret and do error handling if necessary
    }

    return 1;
}

使用mode解析狀態,可以確定要解析的部分。 然后,您必須編寫諸如parse_registersparse_memory類的函數parse_registers對行進行真正的解析,例如:

int parse_registers(const char *line, int *registers)
{
    if(line == NULL || registers == NULL)
        return 0;

    int regNumber, regValue;

    if(sscanf("R%d %d", &regNumber, &regValue) != 2)
    {
        fprintf(stderr, "Invalid format for REGISTER section\n");
        return 0;
    }

    if(regNumber < 0 || regNumber > 31)
    {
        fprintf(stderr, "Invalid register number %d\n", regNumber);
        return 0;
    }

    registers[regNumber] = regValue;

    return 1;
}

現在,您可以為文件的其他部分實現parse_memory和其他parse_xxx函數。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM