【问题标题】:How to read a value that coincide with a specific string inside a text file?如何读取与文本文件中特定字符串一致的值?
【发布时间】:2016-09-09 02:22:44
【问题描述】:

我有以下文本文件:

1 Feb Jane Auckland LF1 190.21
2 Feb Jane Auckland BDHIWAY 390.62 
7 Feb Adeeva Sharif LSZ 2000.00
8 Feb Adeeva Sharif LF2 52.00
4 Feb Jane Auckland ILZERO 101.03 
9 Feb Jerome Velence ILFIVE 4110.00

如您所见,文本文件中有三个人(简·奥克兰、阿德瓦·谢里夫和杰罗姆·韦伦斯),但每个人都有附加值,并在文本文件中散布,被其他人隔开。

我想要做的是一次只读取一个人的文本文件。但是,我希望将它们的重合值(最后一个值)相加,以便我可以将它们通过我的税务功能并打印工资单并检查每个人。它看起来类似于:

Pay slip for Jane Auckland from file examplep1.txt
+-------------------------+
| Commission : $   681.86 |
| Tax        : $     0.00 |
|              ---------- |
| Net Pay    : $   681.86 |
+-------------------------+

OFFICIAL CHEQUE FOR BANK 'BBPL'
Please pay Jane Auckland an amount of $681.86
[  ]       WIC - 420 1337 911

Pay slip for Adeeva Sharif from file examplep1.txt
+-------------------------+
| Commission : $  2052.00 |
| Tax        : $   101.65 |
|              ---------- |
| Net Pay    : $  1950.35 |
+-------------------------+

OFFICIAL CHEQUE FOR BANK 'BBPL'
Please pay Adeeva Sharif an amount of $1950.35
[  ]       WIC - 420 1337 911

Pay slip for Jerome Velence from file examplep1.txt
+-------------------------+
| Commission : $  4110.00 |
| Tax        : $   631.78 |
|              ---------- |
| Net Pay    : $  3478.23 |
+-------------------------+

OFFICIAL CHEQUE FOR BANK 'BBPL'
Please pay Jane Auckland an amount of $3478.23
[  ]       WIC - 420 1337 911

这是我的税务职能:

    double calculateTax(double income)
    {
    double centsPerDollar;
    double initialTax;
    double minimumTax;

    income = round(income); //Rounds income to the nearest interger.

    if (income >= 0 && income <= 1517) //First tax bracket.
    {
        centsPerDollar = 0.00;
        initialTax = 0.00;
        minimumTax = 0.00;

        tax = 0.00;
        taxedIncome = income;
    }
    else if (income >= 1518 && income <= 3083) //Second tax bracket.
    {
        centsPerDollar = 0.19;
        initialTax = 0.00;
        minimumTax = 1517.00;

        tax = (income - minimumTax) * centsPerDollar + initialTax;
        taxedIncome = income - ((income - minimumTax) * centsPerDollar + initialTax);
    }
    else if (income >= 3084 && income <= 6667) //Third tax bracket.
    {
        centsPerDollar = 0.325;
        initialTax = 298.00;
        minimumTax = 3083.00;

        tax = (income - minimumTax) * centsPerDollar + initialTax;
        taxedIncome = income - ((income - minimumTax) * centsPerDollar + initialTax);
    }
    else if (income >= 6668 && income <= 15000) //Fourth tax bracket.
    {
        centsPerDollar = 0.37;
        initialTax = 1462.00;
        minimumTax = 6667.00;

        tax = (income - minimumTax) * centsPerDollar + initialTax;
        taxedIncome = income - ((income - minimumTax) * centsPerDollar + initialTax);
    }
    else if (income >= 15001) //Fifth tax bracket.
    {
        centsPerDollar = 0.45;
        initialTax = 4546.00;
        minimumTax = 15000.00;

        tax = (income - minimumTax) * centsPerDollar + initialTax;
        taxedIncome = income - ((income - minimumTax) * centsPerDollar + initialTax);
    }
    else { fprintf(stderr, "Must be a positive number."); } //Error check for negative numbers.
}

总而言之,我想要做的是用他们自己的价值观来个性化每个人,并将所述价值观通过我的税务功能并打印出每个人的工资单和支票,如示例所示。

提前致谢。

【问题讨论】:

  • 文本文件的第一个问题,名称组件由分隔字段的相同分隔符分隔。使用不同的分隔符,例如制表符 '\t' 或分号 ';',以免产生歧义。
  • 没有标准的函数可以直接跳到你的最终目标。最好将过程分解为文件解析,然后是最终结果整理。即读取每一行,解析,存储解析的信息,然后在文件完全解析后整理最终结果。
  • 您的方法可能使问题变得困难。为什么不将文件中的所有值读取到 struct 数组 中,然后按名称对数组进行排序,然后简单地将每个名称的值相加?您甚至可以创建一个单独的结构来保存名称,并为从文件读取的详细列表中填充的每个人求和。
  • 注意:不需要income &gt;= 1518 &amp;&amp; , income &gt;= 3084 &amp;&amp; ...
  • 简·奥克兰怎么会从给定的样本数据中得到两张薪水?哦,我明白了:这只是一个不完整的 search-n-replace 操作。没关系!

标签: c file text


【解决方案1】:

如何读取与文本文件中特定字符串一致的值?

读取每一行,解析并测试该值是否与指定的字符串匹配。

可以使用"%n"存储扫描的字符数并测试是否成功。

// open the file
// TBD code 

char buf[100];
while (fgets(buf, sizeof buf, istream)) {
  int count;
  char mon[100], first[100], last[100], code[100];
  double money;
  int n = 0; 
  // 1 Feb Jane Auckland LF1 190.21
  sscanf(buf, "%d %s %s %s %s %lf %n", &count, mon, first, last, code, &money, &n);
  if (n > 0 && buf[n] == 0) {
    if (strcmp(code, "specific string") == 0) {
      // found it!             
      printf("%s\n", code);
    }
  }
}

fclose(istream);

自信的 OP 可以处理查找税金和打印输出所需的其余代码。

【讨论】:

    【解决方案2】:

    这是一个简单的解决方案。我稍微更改了文件以消除歧义,并使用';' 作为每一行的字段分隔符。

    这段代码有注释,每一个细节都有解释

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    struct Record {
        char date[6];
        char name[50];
        char type[25];
        float value;
    };
    
    int
    compare_records(const void *const lhs, const void *const rhs)
    {
        /* Compare the names, since this is the field
         * you want to use for matching
         */
        return strcmp(((struct Record *) lhs)->name, ((struct Record *) rhs)->name);
    }
    
    int
    read_next_record(FILE *file, struct Record *record)
    {
        int result;
        /* Simply extract the record from the file.
         *
         * There are many valid methods, some are
         * more robust than this, but this is fast
         * and straight forward given your data.
         */
        result = fscanf(file, "%5[^;];%49[^;];%24[^;];%f\n",
            record->date, record->name, record->type, &record->value);
        return (result == 4);
    }
    
    void
    display_pay_slip_for(const char *const name, struct Record *first, size_t count)
    {
        float value;
        struct Record *next;
        struct Record *found;
        struct Record *final;
        struct Record key;
    
        /* Make a reacord with the name you want to find */
        strcpy(key.name, name);
        /* Perform a binary search on the data set */
        found = bsearch(&key, first, count, sizeof(*first), compare_records);
        if (found == NULL)
            return;
        /* Compute where the last record is */
        final = first + count - 1;
        /* Store the value in the current record */
        value = found->value;
        /* Search for records appearing BEFORE the
         * on found with binary search and take the
         * important data from them.
         */
        for (next = found - 1 ; ((next >= first) && (compare_records(next, found) == 0)) ; --next)
            value += next->value;
        /* Search for records appearing AFTER the
         * on found with binary search and take the
         * important data from them.
         */
        for (next = found + 1 ; ((next <= final) && (compare_records(next, found) == 0)) ; ++next)
            value += next->value;
        /* Display the result */
        fprintf(stdout, "Total for `%s' -> %f\n", name, value);
    }
    
    void
    display_file(const char *const filename)
    {
        FILE *file;
        struct Record records[100];
        size_t count;
    
        file = fopen(filename, "r");
        if (file != NULL) /* Check that the file DID open */
        {
            count = 0;
            /* Read records from the file, the specific method for reading
             * is irrelevant, if you have a function that does it the
             * actual implementation of such function is flexible as long
             * as it does what it has to do
             */
            while (read_next_record(file, &records[count]) != 0)
                ++count;
            /* Sort the records to be able to do a binary search.
             * It's not important for a few records, but many records
             * it's really important as it improves performance
             * dramatically.
             */
            qsort(records, count, sizeof(*records), compare_records);
            /* Simply, call a function where you search for all
             * the records associated with a given "match" in this
             * case the person name, and display the result.
             */
            display_pay_slip_for("Jane Auckland", records, count);
            display_pay_slip_for("Adeeva Sharif", records, count);
            display_pay_slip_for("Jerome Velence", records, count);
    
            /* Of course never forget this */
            fclose(file);
        }
        else
            fprintf(stderr, "error openning `%s'\n", filename);
    }
    
    int
    main(void)
    {
        display_file("data.txt");
        return 0;
    }
    

    唯一缺少的东西你已经实现了,如果你愿意的话,你可以在这段代码中使用它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-20
      • 2019-06-21
      • 1970-01-01
      • 2016-07-01
      • 1970-01-01
      相关资源
      最近更新 更多