【问题标题】:Extract a column of a list from a text file in C从C中的文本文件中提取列表的一列
【发布时间】:2016-02-18 11:12:35
【问题描述】:

这可能是一个简单的问题,答案很简单,但是通过网站搜索,除了我已经编写的 Python 代码,我没有找到任何东西(可能是因为我是 C 编程新手),而且效率很低。

假设我在timestamps.txt 文件中有一个数据列表,格式如下:

<large integer>, <integer between 1 and 8>
<large integer>, <integer between 1 and 8>

等等(文件大约4GB)...

我想做的只是将第二列复制到另一个文件,比如singles.txt

到目前为止我所做的工作有效,但这是一种相当幼稚的方法并且需要太多时间。这是我的代码:

int main(int argc, char const *argv[])
{
    FILE *input_file;
    FILE *output_file;
    char ch;
    int check = 0;

    input_file = fopen("timestamps.txt","r");
    output_file = fopen("singles.dat","w");
    if (!input_file)
        return -1;

    while((ch = getc(input_file))!=EOF)
        {

            if(check==1)
                {putc(ch,output_file);putc('\n',output_file);}

            if(ch == ',')
                check = 2;
            else
                check -= 1;

        }


    fclose(input_file);
    fclose(output_file);

    return 0;
}

我确定有更快的方法,但我似乎无法使任何工作。 任何帮助将不胜感激。

【问题讨论】:

  • 你现在得到了什么?
  • 除了我刚刚发布的代码,我只是尝试了fscanffprintf的组合尝试,但没有任何效果。

标签: c parsing file-management


【解决方案1】:

使用fgetsfputs 比多次调用getcputc 更快,您只需要一个缓冲区(在这种情况下是一个小缓冲区)来存储当前行:

int main(int argc, char const *argv[])
{
    FILE *input_file;
    FILE *output_file;
    char buf[128];
    char *ptr;

    input_file = fopen("timestamps.txt","r");
    output_file = fopen("singles.dat","w");
    if (!input_file)
        return -1; /* use EXIT_FAILURE instead of -1 */
    /* you forget to check output_file */
    while (fgets(buf, sizeof buf, input_file)) {
       ptr = strchr(buf, ','); /* find the comma */
       if (ptr != NULL) {
           fputs(ptr + 1, output_file); /* +1 to skip the comma */
       }
    }
    fclose(input_file);
    fclose(output_file);
    return 0;
}

【讨论】:

  • 这非常有效。不过,我没有在ptr 上加 1,而且效果很好。我写的是while((fgets(line, sizeof(line),input_file))!=NULL){ptr = strchr(line, ' '); fputs(ptr,output_file);}' '是因为逗号后面的空格
【解决方案2】:

您的想法还不错,但是您应该将变量 check 设为 0 或 1,具体取决于您是否要复制当前输入数据。而且您必须在每一行重新设置检查。

或者,您可以计算您所在的当前字段,并在该字段是您想要的字段时复制数据。

这是一个将wantsep 分隔的列逐字复制到输出文件的版本:

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

int main(int argc, char const *argv[])
{
    FILE *in = stdin;
    FILE *out = stdout;

    int want = 1;
    int col = 0;
    int sep = ',';

    for (;;) {
        int c = getc(in);

        if (c == EOF) break;

        if (c == sep) {
            col++;
        } else if (c == '\n') {
            col = 0;
            putc(c, out);
        } else if (col == want) {
            putc(c, out);
        }
    }

    return 0;
}

(我用过stdinstdout,因为我很懒,不想做苍蝇开合的事情。)

【讨论】:

  • 我这样做是因为逗号后面有一个空格,所以当它遇到逗号时我将它设置为2,然后空格使其变为1,最后它符合我需要的数字.
  • 是的,但你只会得到空格,因为在那之后,check 会为每个字符递减。您可以更改每个字符的状态,但只有在找到分隔符(逗号或换行符)时才会更改。
  • 不,如果我在到达逗号时将 check 设置为 1,我会得到空格。 if 在递减之前,所以它就像: if->不满足:检查是负数;如果->不满意:逗号->检查到2; if-> nothing: space->check 为 1;如果->满意!复制的数字:数字->检查归零,但数字已被复制
  • 好的,但这是一个非常专业的版本,它依赖于空格和一位数。 (我知道你说过它是一个从 1 到 8 的整数。无论如何,好像你已经得到了你要找的答案。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多