简体   繁体   English

fgets() 在文件读取中获得的收益超出了应有的范围 - C

[英]fgets() gets more than it should in file reading - C

Currently I'm doing a practical work to collage in witch I have to read data from a file.目前我正在做一个实际的工作来拼贴我必须从文件中读取数据。

The file data structure is: "id name sex"文件数据结构为:“id name sex”

example:例子:

nm0025630   Vikas Anand M
nm0418131   Victor Janson   M
nm0411451   Dick Israel M
nm0757820   Leopoldo Salcedo    M

To read the currently I'm using this code:要阅读当前我正在使用此代码:

    fh = NULL;
    fh = fopen(ACTORS, "r");
    if (!fh) {
        exit(1);
    }
    while (!feof(fh)) {
        char sex, name[100], id[10];

        fgets(id, 10, fh);
        fgets(name, 100, fh);
        fgetc(sex);

        if (!feof(fh)) {
            hash_update_node(hash, get_id_num(id), name, sex);
            count++;
        }
    }

The problem is that it reads the name and the sex together.问题是它会同时读取名称和性别。 Any help is appreciated.任何帮助表示赞赏。

fgets(name, 100, fh); reads up to 99 character, when the name has less than 98 character the sex is also read if it has onlt one space before.最多读取 99 个字符,当名称少于 98 个字符时,如果之前只有一个空格,也会读取性别。

Because the name is may be composed of several words separated by spaces one way is to read all the line then extract the sex.因为名称可能由空格分隔的几个单词组成,一种方法是读取所有行然后提取性别。

Warning the first time you do while (!feof(fh)) { this is without any read before so feof cannot know if the file is empty or not then if you reach EOF or not.警告您第一次执行while (!feof(fh)) {这之前没有任何读取,因此feof无法知道文件是否为空,然后您是否达到 EOF。 I encourage you to detect the EOF looking at read result.我鼓励您检测读取结果的 EOF。

Also because you only save the read data when if (!feof(fh)){ you do not memorize the information from the last line.还因为您仅在if (!feof(fh)){您不记住最后一行的信息时才保存读取的数据。

Note also fgets saves the newline if there is enough place for it, it is more practical to use fscanf .还要注意fgets如果有足够的位置保存换行符,则使用fscanf更实用。

So one way can be:所以一种方法可以是:

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

#define ACTORS "/tmp/actors"

int main()
{
  FILE * fh = fopen(ACTORS, "r");

  if (!fh) {
    perror("cannot read " ACTORS);
    exit(1);
  }

  char name[100],id[10];

  while (fscanf(fh, "%9s %99[^\n]", id, name) == 2) {
    size_t sz = strlen(name);
    char sex = name[--sz];

    for (;;) {
      if (sz == 0) {
        puts("empty name");
        exit(2);
      }
      if (!isspace((unsigned char) name[--sz]))
        break;
    }

    name[sz+1] = 0;

    /*
    hash_update_node(hash, get_id_num(id) , name, sex);
    count++;
    */
    printf("id='%s', name='%s', sex=%c\n", id, name, sex);
  }

  fclose(fh);
  return 0;
}

Compilation and executions:编译和执行:

pi@raspberrypi:/tmp $ gcc -Wall r.c
pi@raspberrypi:/tmp $ ./a.out
cannot read /tmp/actors: No such file or directory
pi@raspberrypi:/tmp $ cat > actors
nm0025630 Vikas Anand M
nm0418131 Victor Janson M
nm0411451 Dick Israel M
nm0757820 Leopoldo Salcedo M
pi@raspberrypi:/tmp $ ./a.out
id='nm0025630', name='Vikas Anand', sex=M
id='nm0418131', name='Victor Janson', sex=M
id='nm0411451', name='Dick Israel', sex=M
id='nm0757820', name='Leopoldo Salcedo', sex=M
pi@raspberrypi:/tmp $ 

It seems the fields are separated by TAB characters in the file.似乎这些字段由文件中的 TAB 字符分隔。 If this is correct, you can parse the file with fscanf() :如果这是正确的,您可以使用fscanf()解析文件:

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

int local_file(void) {
    char sex, name[100], id[10];
    int count = 0;

    FILE *fh = fopen(ACTORS, "r");
    if (!fh) {
        exit(1);
    }
    while (fscanf("%9[^\t]%*1[\t]%99[^\t]%*1[\t]%c", id, name, &sex) == 3) {
        hash_update_node(hash, get_id_num(id), name, sex);
        count++;
    }
    return count;
}

Note however that this code will fail if any of the fields are empty.但是请注意,如果任何字段为空,则此代码将失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM