【问题标题】:How do you read tab delimited strings from a txt file and put them into variables?如何从 txt 文件中读取制表符分隔的字符串并将它们放入变量中?
【发布时间】:2012-06-06 05:35:48
【问题描述】:

我有一个文件正在尝试读取和填充变量。该文件由以下内容组成:

0\ttake a nap\n
1\tstudy heap-based priority queue\n
101\treview trees for Midterm 2\n
3\tdo assignment 7\n

这可能很难阅读,但是您可以看到有一个整数开头,然后是一个制表符,然后是一个字符串,然后是一个换行符。我需要取整数并将其放入变量中,检测制表符,并将制表符后面的字符串放入变量中,检测换行符,获取两个变量并使用信息创建一个节点,然后重新开始下一行。经过数小时的互联网搜索,这是我想出的:

char activity[SIZE];
 char position[SIZE];
 char line[100];

  FILE *infile;
  char *inname = "todo.txt";

  int i = 0;


  infile = fopen(inname, "r");
  if (!infile) {
    printf("Couldn't open %s for reading\n");
    return 0;
  }
while(i < 100 && fgets(line, sizeof(line), infile) != NULL){
        sscanf(line, "%s\t%s", position, activity);
        printf("%s\n", position);
        printf("%s\n", activity);
        i++;
    }

在上面的 txt 文件上运行这个测试代码时,我得到了这个结果:

0
take
1
study
101
review
3
do

所以,在我看来,它正在获取第一个数字(作为字符串)并将其放入变量中,查看选项卡,并在选项卡之后抓取第一个序列并在将其放入另一个变量后停在那里.我该如何纠正这种情况?

【问题讨论】:

    标签: c file


    【解决方案1】:

    您可以尝试更改sscanf

    sscanf(line, "%s\t%[^\n]", position, activity);
    

    %s 说明符在遇到空白时停止。这就是为什么它只读取 study 而不是 study 基于堆的优先级队列%[^\n] 告诉它:“读到换行符”。另一个问题:您应该测试sscanf 返回的值,以确保它填充了所需数量的对象。


    您也可以将第一个整数读取为整数,将position 更改为int 并使用%d 而不是%s

    编辑

    为了让自己清楚,我的建议是:

    int position;
    sscanf(line, "%d\t%[^\n]", &position, activity);
    

    【讨论】:

    • 是的,我尝试使用 position 来执行此操作,结果只是给了我变量 position 的地址(例如 1003020010)我会尝试您的其他建议。
    • @FeralShadow 奇怪。您是否也将sscanf 中的position 更改为&amp;position
    • 这似乎没有什么不同。如果我在 printf 语句中将 %s 更改为 %d ,它会给我内存地址。如果我将位置类型更改为 int,并将 printf 保留为 %s,它会给我我需要的数字。另外,我也将位置的 sscanf 更改为 %d,所以看起来它真的需要作为字符串读取?
    • 无论如何,您对 %[^\n] 的建议非常有效。我会找到一种将位置字符串转换为整数的方法。
    • @FeralShadow 我很高兴它成功了 :-) 查看我的编辑;如果这不起作用,总是有strtoul
    【解决方案2】:

    以下对我的用例非常有效。我想将制表符分隔文件的前两个字段读入字符串变量,然后将每行的其余部分读入最终字符串变量。

    代码如下:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main()
    {
       unsigned char     string1 [255];
       unsigned char     string2 [255];
       unsigned char     string3 [255];
    
       /* read from stdin until done */
       while(!feof(stdin))
       {
          fscanf( stdin, "%[^\t]\t%[^\t]\t%[^\n]\n", string1, string2, string3 );
          printf( "%s\t%s\t%s\n",                    string1, string2, string3 );
       }
    
       return(0);
    }
    

    我正在从 STDIN 读取数据,因为我使用该程序创建了一个命令行过滤器。

    fscanf 代码说明:

    %[^\t] - any character that is not a TAB
    \t     - the TAB character
    %[^\n] - any character that is not a NEWLINE
    \n     - the NEWLINE character
    

    因此,我的 fscanf 正在读取直到第一个 TAB 的所有字符(包括空格但不包括 TAB 本身)并将字符串放入 var string1,直到第二个 TAB 的所有字符(包括空格但不包括 TAB 本身)和将字符串放入 var string2 中,然后将记录的所有剩余字符(制表符、空格、除 NEWLINE 之外的所有字符)读取到 NEWLINE 到 string3 中。

    在我的真实程序中,我对string1和string2进行了特定的处理。我的输出是与 string3 一起处理的结果。换句话说,我的输出也是制表符分隔的,而 string3 的原始内容保持不变。

    如果您有一个包含三个或更多字段的制表符分隔文件,那么以下(在 Linux 上)应该是正确的:

    cat FILE | ABOVE_PROGRAM > OUT_FILE
    diff FILE OUT_FILE       # This should yield nothing (no differences)
    

    希望这将有助于其他人处理制表符分隔的文件。

    【讨论】:

      猜你喜欢
      • 2023-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-18
      • 1970-01-01
      • 2021-01-11
      相关资源
      最近更新 更多