【问题标题】:Ignoring unnecessary characters while reading from file in C从C中的文件读取时忽略不必要的字符
【发布时间】:2015-05-04 12:29:00
【问题描述】:

我有一个编程作业,它提供了一个数据文件“candidatesdata.txt” 您应该阅读信息并破译姓名、性别、身高和体重。唯一的问题是每个数据记录之间的名称和逗号都有引号。文件如下:

Name,Gender,Height,Weight
"Tanner, Mark C.”,M,71.8,180.25
"Jinglehiemmerschmitt, John J.”,M,70.75,185.3
"Parker, Sarah J.",F,65.25,120.3

..继续

如何读取数据记录并忽略引号和逗号? 这是我到目前为止所拥有的,它删除了一些逗号和引号,但在此过程中它也删除了名称。

#include <stdio.h>

struct candidateinfo
{
    char name[50];
    char gender;
    double height;
    double weight;
}candidate;


    int main()
{
    int count =0;
    FILE *candidate_data;


    // Open file
    candidate_data = fopen("/Users/moisestrevino/Documents/CS 1324/Assignment #5/Assignment #5/candidatedata.txt","r");

    fscanf(candidate_data, "%*[^\n]");
    fgetc(candidate_data);

    // Get rid of unecessary letters

      while (count<40)
      {
          count++;

         fscanf(candidate_data,"\"%[^\"],%c,%lf,%lf\n", candidate.name, &candidate.gender, &candidate.height, &candidate.weight);

          printf("%s %c %lf %lf\n",candidate.name, candidate.gender, candidate.height, candidate.weight);
      }

    fclose(candidate_data);
    return 0;

 }

输出:

     Tanner, Mark C.  0.000000 0.000000
,M,71.8,180.25
  0.000000 0.000000
Jinglehiemmerschmitt, John J.  0.000000 0.000000
,M,70.75,185.3
  0.000000 0.000000
Parker, Sarah J.  0.000000 0.000000
,F,65.25,120.3
  0.000000 0.000000
Meeks, Kalvin R.  0.000000 0.000000
,M,57.25,210.2


cont...

【问题讨论】:

  • 必须首先阅读this
  • 另外请缩进你的代码
  • 我应该改用EOF吗?
  • 使用 fgetc() 而不是 fscanf()
  • 您的某些引号字符是非 ASCII 印刷引号 - 您是从 Word 文档中粘贴的吗?另外,引号的原因是名称字段内有逗号。

标签: c file struct


【解决方案1】:

您的代码包含很多问题。要说的太多了,所以这里是修复:

如果文件包含表单中的数据:

Name,Gender,Height,Weight

然后,

"Tanner, Mark C.",M,71.8,180.25
"Jinglehiemmerschmitt, John J.",M,70.75,185.3
"Parker, Sarah J.",F,65.25,120.3

那么下面的修复就可以解决了。

fopen之后,可以使用

fscanf(candidate_data, "%*[^\n]");
fgetc(candidate_data);

第一行扫描并丢弃所有内容,直到换行符为止。第二行使用换行符。之后,使用

fscanf(candidate_data, " \"%[^\"]\",%c,%lf,%lf", name, gender, height, weight);

假设您已经声明了一个名为name 的相当大的char 数组,一个名为genderchar 和两个名为heightweightdoubles,这是细分以上fscanf:

  • (space) 扫描并丢弃所有空白字符,直到第一个非空白字符。
  • \" 扫描文件中的 " 并将其丢弃。
  • %[^\"] 扫描所有内容,直到 " 并将其存储在 name 中。
  • \" 扫描文件中的 " 并将其丢弃。
  • , 扫描并丢弃逗号。
  • %c 扫描一个字符并将其存储在 gender 中。
  • , 扫描并丢弃逗号。
  • %lf 扫描 double 并将其存储在 height 中。
  • , 扫描并丢弃逗号。
  • %lf 扫描 double 并将其存储在 weight 中。

现在您可以打印每个值。通过将上述fscanf 放入循环中来读取更多数据。

但是你怎么知道数据什么时候结束呢?检查fscanf 的返回值。 fscanf 返回成功匹配和分配的输入项的数量,可以少于提供的数量,如果早期匹配失败,甚至为零。

在您的情况下,如果所有数据都已成功扫描,fscanf 将返回 4。因此,只需读取数据,直到 fscanf 不返回 4。


正如@chux 所建议的,您可以通过使用来防止缓冲区溢出
fscanf(candidate_data, " \"%49[^\"]\",%c,%lf,%lf", name, gender, height, weight);

49 告诉 scanf 最多扫描 49 个字符以查找 name(+1 表示 NUL 终止符)

【讨论】:

  • " \"%[^\"]",%c,%lf,%lf" --> " \"%[^\"]\",%c,%lf,%lf"(加斜杠)进一步建议" \"%49[^\"]\", %c ,%lf ,%lf"(加空格,宽度)
  • @chux,谢谢。错过了斜线。根据 OP 的文本文件格式,不需要空格。添加了其他建议。
  • 建议添加@Random832 对输入文件的评论,使用各种引用使"Tanner, Mark C.” " 对比。
  • @chux ,顺便说一句,我如何扫描 并在控制台中打印? fscanf 似乎没有按预期工作,打印 也会在控制台中打印奇怪的东西。
  • (这不是")是一个非ASCII字符。从控制台读取并正确打印是系统特定的 - 无法提供通用解决方案。打印通常涉及使用wprintf()wchar_t
【解决方案2】:

如果每行包含所有字段,则可以使用 str(r)chr+atof 代替,例如

char line[100];
while( fgets(line,100,candidate_data) )
{
  char *p = strrchr(line,',');
  weight = atof(p+1); *p=0;
  p = strrchr(line,',');
  height = atof(p+1);
  gender = *--p;
  *strrchr(line,'"')=0;
  strcpy( name, strchr(line,'"')+1 );
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-29
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    相关资源
    最近更新 更多