【问题标题】:Can't figure out how to isolate number and replace it无法弄清楚如何隔离数字并替换它
【发布时间】:2019-11-28 20:50:24
【问题描述】:

我所做的是使用我提取数据并将其放入新文件的第一组代码,因此它只是值

这是我第一组代码的输入文件:

original input

这是我的第二组代码的输入文件,这是我的主要问题:

second set of input code

然后在第二组代码中是读取新文件的位置,因此它使用 fgetc 输出数字,我现在如何使用这个应用一个简单的公式? 具体来说,该公式会将任何 10 值转换为 0 值 我试过了,因为 fgetc 是 unsigned char 我尝试在 if 语句中使用二进制数 10

这是我目前的代码:

#include<stdio.h> 

int main() 
{ 
    FILE* ptr = fopen("Data.txt","r"); 
    if (ptr==NULL) 
    { 
        printf("no such file."); 
        return 0; 
    } 

    FILE*fp = fopen("/data flow/NEWdata.txt", "w+");

        int x;
  int count=0;
    char buf[100];
    fscanf(ptr,"%*s %*s %*s %*s %*s %*s %*s %s ",buf); //skip first line and stuff before first value(column names)
    while (fscanf(ptr,"%*s %*s %*s %*s %s  ",buf)==1) 
    {

        fprintf(fp, "%s\n",buf);
    }
    fclose(fp); 
    return 0; 
} 

第二组代码

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

int main () {
   FILE *fp;
   char str[100];

   /* opening file for reading */
   fp = fopen("NEWdata.txt" , "r");
   if(fp == NULL) {
      perror("Error opening file");
      return(-1);
   }
   int i;
   while( fgets (str, 100, fp)!=NULL ) {
      /* writing content to stdout */
      sscanf (str,%u,i);
    printf(%u,i);

   }
   fclose(fp);

   return(0);
}

我所谓的命令行 enter image description here

我得到的错误如下 enter image description here

 if (measure = 10)
            fprintf (ofp, "%f\n", measure - 10);
        else
            fprintf (ofp, "%f\n", measure);
#include <stdio.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */
#define MAXF   32

int main (int argc, char **argv) {

    char buf[MAXC];     /* buffer to hold each line read from file */
    size_t n = 0;       /* line counter */
   FILE *fp, *ofp;     /* file pointer, output file pointer */

    if (argc < 3 ) {    /* validate 2 arguments given for in/out filenames */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename outfilename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen ("Data.txt", "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

    if ((ofp = fopen ("NEWdata.txt", "w")) == NULL) {
        perror ("fopen-argv[2]");
        return 1;
    }

    if (!fgets (buf, MAXC, fp)) {   /* read/discard 1st line */
        fputs ("error: EOF on read of first line.\n", stderr);
        return 1;
    }

    while (fgets (buf, MAXC, fp)) { /* read all remaining lines */
        char date[MAXF], time[MAXF], prod[MAXF], unit[MAXF];
        double measure;

        if (sscanf (buf, "%s %s %s %lf %s", /* validate all 5 fields */
                    date, time, prod, &measure, unit) != 5) {
            fprintf (stderr, "error: invalid format, line: %zu\n", n + 1);
            continue;
        }

        /* do whatever you need with the separated values.
         * if measure is 10.xx, then make measure 0.xx
         */
        if (measure = 10)
            fprintf (ofp, "%f\n", measure - 10);
        else
            fprintf (ofp, "%f\n", measure);

        n++;    /* increment line counter */
    }
}

【问题讨论】:

  • 然后只需阅读第一行并将其丢弃。建议使用fgets
  • char* buf[100]; 这不是你想要的。应该是char buf[100];
  • 我将其更改为 char 但 fgets 无法正常工作,此时这段代码让我发疯@kaylum
  • 定义“不工作”。除非您显示代码并更清楚地描述问题,否则无法帮助您。
  • @kaylum 在网上学习后我开始陷入困境,但如果我做得对,我的问题是应用公式,因为 fgetc 是无符号字符,使用 fgets 不起作用我的情况

标签: c scanf readfile data-manipulation fgetc


【解决方案1】:

如果我理解正确并且您想从Data.txt 中读取值,并且如果Measurement 的值是10,您想将该值设置为0。正如我在评论中所指出的,您的 Measurement 值是一个 floating-point 数字(double 在下面使用)。由于无法以 floating-point 格式精确表示所有数字,因此浮点数的比较本质上是不精确的。 (10.0 可以精确表示,但请注意限制)。见Is floating point math broken?Why Are Floating Point Numbers Inaccurate?

在到达那里之前,避免硬编码文件名或在代码中使用幻数main() 接受允许您将信息传递给代码的参数。您可以简单地将要读取的文件名作为程序的第一个参数传递或将文件名作为输入。例如

#include <stdio.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */
#define MAXF   32

int main (int argc, char **argv) {

    char buf[MAXC];     /* buffer to hold each line read from file */
    size_t n = 0;       /* line counter */
    FILE *fp;           /* file pointer */

    if (argc < 2 ) {    /* validate 1 argument given for filename */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

使用fgets() 和缓冲区(例如,MAXC 的字符数组,最大字符数),您可以读取和丢弃第一行。 (*不要忘记验证读取):

    if (!fgets (buf, MAXC, fp)) {   /* read/discard 1st line */
        fputs ("error: EOF on read of first line.\n", stderr);
        return 1;
    }

现在只需循环读取带有fgets() 的每个后续行到同一个缓冲区中,然后将该缓冲区传递给sscanf() 以从行中解析您需要的值,例如

    while (fgets (buf, MAXC, fp)) { /* read all remaining lines */
        char date[MAXF], time[MAXF], prod[MAXF], unit[MAXF];
        double measure;

        if (sscanf (buf, "%s %s %s %lf %s", /* validate all 5 fields */
                    date, time, prod, &measure, unit) != 5) {
            fprintf (stderr, "error: invalid format, line: %zu\n", n + 1);
            continue;
        }

(注意:如果该行的格式不正确,您的读取不会像使用fscanf() 那样失败。这里通过使用fgets() 读取,您会消耗一行 at时间,无论格式如何,然后使用sscanf() 解析行中的值。如果行格式与您的 format-string 不匹配,您只需丢弃该行并读取下一行.)

现在您可以对date, time, prod, measure &amp; unit 中的值进行任何操作。在这里,我们将简单地比较 measure 以查看它是否为 10.0 或大于 11.0(不包括),然后从值中减去 10.0,使值 0.xxx10.xxx 相同。如果你愿意(取决于你),你可以简单地输出0.0

        /* do whatever you need with the separated values.
         * if measure is 10.xx, then make measure 0.xx
         */
        if (10.0 <= measure && measure < 11.0)
            printf ("measurement[%2zu]: %.3f   (was %.3f)\n",
                    n, measure - 10., measure);
        else
            printf ("measurement[%2zu]: %.3f\n", n, measure);

        n++;    /* increment line counter */
    }
}

这就是您想要的简单示例。 (1) 使用fgets() 读取和(2) 使用sscanf() 解析的基本原理可以涵盖广泛的输入情况。你会一遍又一遍地使用它。这样做而不是直接使用 fscanf() 的原因是为了防止单行的格式错误导致 matching-failure,其中从输入流中提取的字符停止在输入中留下违规字符-stream 未读,等着你下次尝试输入时再次咬你。

完整的例子是:

#include <stdio.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */
#define MAXF   32

int main (int argc, char **argv) {

    char buf[MAXC];     /* buffer to hold each line read from file */
    size_t n = 0;       /* line counter */
    FILE *fp;           /* file pointer */

    if (argc < 2 ) {    /* validate 1 argument given for filename */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

    if (!fgets (buf, MAXC, fp)) {   /* read/discard 1st line */
        fputs ("error: EOF on read of first line.\n", stderr);
        return 1;
    }

    while (fgets (buf, MAXC, fp)) { /* read all remaining lines */
        char date[MAXF], time[MAXF], prod[MAXF], unit[MAXF];
        double measure;

        if (sscanf (buf, "%s %s %s %lf %s", /* validate all 5 fields */
                    date, time, prod, &measure, unit) != 5) {
            fprintf (stderr, "error: invalid format, line: %zu\n", n + 1);
            continue;
        }

        /* do whatever you need with the separated values.
         * if measure is 10.xx, then make measure 0.xx
         */
        if (10.0 <= measure && measure < 11.0)
            printf ("measurement[%2zu]: %.3f   (was %.3f)\n",
                    n, measure - 10., measure);
        else
            printf ("measurement[%2zu]: %.3f\n", n, measure);

        n++;    /* increment line counter */
    }
}

输入文件示例

$ cat dat/data_timestamp.txt
TimeDateStamp Product Measurement Unit
2019-11-09 16:54    FS2012  0.344   SLPM
2019-11-09 16:54    FS2012  0.344   SLPM
2019-11-09 16:54    FS2012  0.344   SLPM
2019-11-09 16:54    FS2012  0.344   SLPM
2019-11-09 16:54    FS2012  0.136   SLPM
2019-11-09 16:54    FS2012  0.136   SLPM
2019-11-09 16:54    FS2012  0.136   SLPM
2019-11-09 16:54    FS2012  0.136   SLPM
2019-11-09 16:54    FS2012  0.047   SLPM
2019-11-09 16:54    FS2012  0.047   SLPM
2019-11-09 16:54    FS2012  0.047   SLPM
2019-11-09 16:54    FS2012  0.047   SLPM
2019-11-09 16:54    FS2012  1.991   SLPM
2019-11-09 16:54    FS2012  1.991   SLPM
2019-11-09 16:54    FS2012  1.991   SLPM
2019-11-09 16:54    FS2012  10.0    SLPM
2019-11-09 16:54    FS2012  10.661  SLPM
2019-11-09 16:54    FS2012  10.991  SLPM
2019-11-09 16:54    FS2012  11.0    SLPM

使用/输出示例

下面,我展示了10 被缩减为0 的位置:

$ ./bin/read_data_timestamp dat/data_timestamp.txt
measurement[ 0]: 0.344
measurement[ 1]: 0.344
measurement[ 2]: 0.344
measurement[ 3]: 0.344
measurement[ 4]: 0.136
measurement[ 5]: 0.136
measurement[ 6]: 0.136
measurement[ 7]: 0.136
measurement[ 8]: 0.047
measurement[ 9]: 0.047
measurement[10]: 0.047
measurement[11]: 0.047
measurement[12]: 1.991
measurement[13]: 1.991
measurement[14]: 1.991
measurement[15]: 0.000   (was 10.000)
measurement[16]: 0.661   (was 10.661)
measurement[17]: 0.991   (was 10.991)
measurement[18]: 11.000

检查一下,让我知道这是否接近您的需要。我可能仍然会误解您通过 100 尝试实现的目标,但如果我误解了,请在下方发表评论,我很乐意提供进一步的帮助。

写入输出文件作为编程的第二个参数

要将调整后的Measurement 值单独写入您选择的输出文件,您只需在命令行上输入文件名后提供您要使用的输出文件名,然后使用argv[2] 打开一个文件进行输出(main() 的第二个命令行参数)变化很小。只需添加另一个FILE* 指针ofp(用于输出文件指针),然后打开该文件进行写入:

    FILE *fp, *ofp;     /* file pointer, output file pointer */

    if (argc < 3 ) {    /* validate 2 arguments given for in/out filenames */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename outfilename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

    if ((ofp = fopen (argv[2], "w")) == NULL) {
        perror ("fopen-argv[2]");
        return 1;
    }

然后使用fprintf输出调整后的测量值,例如

        if (10.0 <= measure && measure < 11.0)
            fprintf (ofp, "%.3f\n", measure - 10.);
        else
            fprintf (ofp, "%.3f\n", measure);

(程序的其余部分完全相同)

#include <stdio.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */
#define MAXF   32

int main (int argc, char **argv) {

    char buf[MAXC];     /* buffer to hold each line read from file */
    size_t n = 0;       /* line counter */
    FILE *fp, *ofp;     /* file pointer, output file pointer */

    if (argc < 3 ) {    /* validate 2 arguments given for in/out filenames */
        fprintf (stderr, "error: insufficient input,\n"
                         "usage: %s filename outfilename\n", argv[0]);
        return 1;
    }

    /* open file/validate file open for reading */
    if ((fp = fopen (argv[1], "r")) == NULL) {
        perror ("fopen-argv[1]");
        return 1;
    }

    if ((ofp = fopen (argv[2], "w")) == NULL) {
        perror ("fopen-argv[2]");
        return 1;
    }

    if (!fgets (buf, MAXC, fp)) {   /* read/discard 1st line */
        fputs ("error: EOF on read of first line.\n", stderr);
        return 1;
    }

    while (fgets (buf, MAXC, fp)) { /* read all remaining lines */
        char date[MAXF], time[MAXF], prod[MAXF], unit[MAXF];
        double measure;

        if (sscanf (buf, "%s %s %s %lf %s", /* validate all 5 fields */
                    date, time, prod, &measure, unit) != 5) {
            fprintf (stderr, "error: invalid format, line: %zu\n", n + 1);
            continue;
        }

        /* do whatever you need with the separated values.
         * if measure is 10.xx, then make measure 0.xx
         */
        if (10.0 <= measure && measure < 11.0)
            fprintf (ofp, "%.3f\n", measure - 10.);
        else
            fprintf (ofp, "%.3f\n", measure);

        n++;    /* increment line counter */
    }
}

如果我随后使用两个参数(例如输入和输出文件名)调用我的程序,如下所示:

$ ./bin/read_data_timestamp2 dat/data_timestamp.txt dat/measure_val.txt

我将从我的输入文件 dat/data_timestamp.txt 中读取结果并将结果写入我的输出文件 dat/measure_val.txt(您可以为输出文件使用任何您喜欢的文件名,但您的输入将是 Data.txt)。

生成的输出文件

$ cat dat/measure_val.txt
0.344
0.344
0.344
0.344
0.136
0.136
0.136
0.136
0.047
0.047
0.047
0.047
1.991
1.991
1.991
0.000
0.661
0.991
11.000

让我知道这是否解决了问题。

【讨论】:

  • 这看起来就是我要找的东西,但乍一看我不明白使用文件,所以如果我要使用我的文件,它会去哪里......至于休息,我理解,但明天会更深入,因为这里太晚了,明天我会在休息时回复你提前谢谢你......我只是想知道如何使用我自己的文件,因为这些文件可能会有所不同,所以我想知道在哪里改变它所以输入是一致的
  • 如果您只想将Measurement 值单独输出到新文件,您可以简单地输出值(删除measurement[%2zu] 并将输出重定向到新文件,(例如@987654376 @)。或者,您可以将输出文件名作为第二个参数传递并打开一个文件进行写入(例如FILE *ofp;)然后ofp = fopen (argv[2], "w");(不要忘记validate 它实际上是打开的)然后使用fprintf (ofp, "%.3f\n", measure);(或measure - 10.0)写入文件。
  • 是的,我明白这一点,但我不明白你的输入文件是从哪里进入程序的,因为你的文件被称为“$ cat dat/data_timestamp.txt”,但我没有看到它,是什么让我困惑
  • 哦——记住避免硬编码文件名的建议。我的输入文件名是我在命令行上提供的dat/data_timestamp.txt。 (例如./prog filename)。 argv[1] 是第一个命令行参数(argv[2],第二个等等)所以如果你想要一个使用重定向的新文件,你会做./prog filename &gt; outfilename。我将在命令行上放一个使用两个文件名的示例,您可以进行比较。
  • 看看,让我知道这是否可以解决问题。文件名(输入和输出)只是作为您的两个参数在命令行上传递。在 Dev-C++ 中,您将有一个对话框,允许您在项目设置之一中指定程序参数。无论如何,我只是从命令行编译和运行所有东西——更快,更少担心在你的 IDE 中找到设置。我没有 Dev-C++,但大多数 IDE 在您的项目选项中提供了命令行参数对话框。
猜你喜欢
  • 1970-01-01
  • 2014-12-18
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多