从C中的文件读取字符和字符串

时间:2019-03-11 18:03:01

标签: c c-strings file-processing

我正在一个项目中,在该项目中,我将具有读取或写入命令,然后具有文件中一行上的地址。格式如下:

R 0x...
W 0x...

文件长数千行。我试图读取命令并将其放在buf1中,并将地址读取到buf2中。我尝试使用fgets / fgetc以及fscanf"%*c %s"来做到这一点,反之亦然。每次执行此操作时,buf2都会正确获取地址,但是命令命中或未命中。这是我的代码:

char buf1, buf2[64];
int readcount = 0, writecount = 0, other = 0;
while(!feof(trace)){
printf("\nFile is open");
fgetc(trace);
fgets(buf2,16,trace);
printf("\nBuf1 is: %c",buf1);
printf("\nBuf2 is: %s",buf2);

我不断得到的输出是:

The address is: E  
File is open  
Buf1 is: ?  
Buf2 is:  0x123456  

The address is: V  
File is open  
Buf1 is: ?  
Buf2 is:  0x234567  

The address is: g  
File is open  
Buf1 is: ?  
Buf2 is:  0x345678  

The address is: x  
File is open  
Buf1 is: ?  
Buf2 is:  0x345678  

我觉得问题出在我对文件读取功能的理解上。为什么buf1无法正确读取?

1 个答案:

答案 0 :(得分:2)

(我在R 0x...W 0x...是在同一行而不是在同一行的情况下回答了这个问题)

如果您确定 文件的每一行都包含R<space>0x...<space>W<space>0x...,则可以这样做

int main()
{
  FILE * fp = fopen("in", "r");

  if (fp == NULL) {
    puts("cannot open 'in'");
    return -1;
  }

  char line[100];

  while (fgets(line, sizeof(line), fp)) {
    char c1, c2;
    unsigned n1, n2;

    errno = 0;
    if ((sscanf(line, "%c %x %c %x", &c1, &n1, &c2, &n2) == 4) && !errno) {
      // just to indicate it read well
      printf("%c:%x:%c:%x\n", c1, n1, c2, n2);
    }
    else {
      printf("invalid line %s\n", line);
    }
  }

  puts("done");
  fclose(fp);
}

编译与执行

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra f.c
pi@raspberrypi:/tmp $ cat in
R 0x1 W 0x2
A 0x123 Z 0x345
C 0x0 Z 0x678
pi@raspberrypi:/tmp $ ./a.out
R:1:W:2
A:123:Z:345
C:0:Z:678
done

请注意,我首先阅读了该行,以免被换行符打扰


如果您可以有多个空格和/或在字段之间和/或甚至在行的开头都可以使用制表符,则可以使用 strtok

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

int getChar(char * c, char * s, int n)
{
  if (s == NULL) {
    printf("field %d is missing\n", n);
    return 0;
  }
  if (s[1] != 0) {
    printf("invalid field %d : '%s'\n", n, s);
    return 0;
  }

  *c = s[0];
  return 1;
}

int getUnsigned(unsigned * u, char * s, int n)
{
  if (s == NULL) {
    printf("field %d is missing\n", n);
    return 0;
  }

  char c;

  errno = 0;
  if ((sscanf(s, "%x%c", u, &c) != 1) || (errno != 0)) {
    printf("invalid field %d : '%s'\n", n, s);
    return 0;
  }

  return 1;
}

int main()
{
  FILE * fp = fopen("in", "r");

  if (fp == NULL) {
    puts("cannot open 'in'");
    return -1;
  }

  char line[100];

  while (fgets(line, sizeof(line), fp)) {
    char c1, c2;
    unsigned n1, n2;

    if (getChar(&c1, strtok(line, " \t"), 0) &&
        getUnsigned(&n1, strtok(NULL, " \t"), 1) &&
        getChar(&c2, strtok(NULL, " \t"), 2) &&
        getUnsigned(&n2, strtok(NULL, " \t\n"), 3)) /* warning \n is added */
      // just to indicate it read well
      printf("%c:%x:%c:%x\n", c1, n1, c2, n2);
  }

  puts("done");
  fclose(fp);
}

编译和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra ff.c
pi@raspberrypi:/tmp $ cat in
 R 0x1   W  0x2
A    0x123 Z 0x345
    C 0x0  Z     0x678
pi@raspberrypi:/tmp $ ./a.out
R:1:W:2
A:123:Z:345
C:0:Z:678
done