繁体   English   中英

fscanf 打印未知值

[英]fscanf printing unknown values

我正在尝试使用 fscanf 获取一个文本文件并以相同的格式简单地打印它(最终它将用于填充结构数组)。

当我使用 fscanf 时,它会打印一些不属于文本的值,我不确定它们来自哪里。 我已将一小部分输入文本文件和 output 放在代码部分下方。

我想在页面上水平打印的值都在 output 的第一列,这让我觉得这与我如何定义我的 fprint 语句有关? 第一列中的每个正确值后面都是我不知道从何而来的值。

任何帮助将不胜感激。

#include <stdlib.h>

int count_lines(char file[]) {

  FILE* f = fopen(file, "r");          /* declaration of file pointer */
  char x;
  int c = 0;                                      /* declaration of variable */
  f = fopen(file, "r");
  if (f == NULL) {
    printf("Cannot open file for reading");
    return -1;
  }
  while ((x = fgetc(f)) != EOF) {
    if (x == '\n') {
      c = c + 1;
    }
  }
  if (fclose(f) != 0) {
    printf("File could not be closed.\n");
    return -1;
  }
  printf("Number of lines = %d\n", c);
  return c;
}

struct votes {
  char state[100];     /* state name */
  long dempv;          /* democrats popular votes */
  long demev;          /* democrats electoral votes */
  long reppv;          /* republicans popular votes */
  long repev;          /* republicans electoral votes */
};

void initialise_votes(char file[], struct votes* arr, int nlines) {
  FILE* f = fopen(file, "r");
  char temp1[20];
  long temp2;
  long temp3;
  long temp4;
  long temp5;

  if (f == NULL) {
    printf("Cannot open file for reading\n");
  }

  while (fscanf(f, "%s, %ld, %ld, %ld, %ld", temp1, &temp2, &temp3, &temp4, &temp5) != EOF) {
    printf("%s\t%ld\t%ld\t%ld\t%ld\n", temp1, temp2, temp3, temp4, temp5);
  }

  if (fclose(f) != 0) {
    printf("File could not be closed.\n");
  }
}


int main(void) {
  char s_in[] = "uselection2012.txt"; /* input data file */
  int nlines;
  struct votes* arr;

  nlines = count_lines(s_in);
  arr = (struct votes*)malloc(sizeof(struct votes) * nlines);

  initialise_votes(s_in, arr, nlines);

  return 0;
}

输入文件:

Alabama 795696 0 1255925 9
Alaska 122640 0 164676 3
Arizona 1025232 0 1233654 11
Arkansas 394409 0 647744 6
California 7854285 55 4839958 0

Output:

Alabama 6356696 -37862896       6380    0
795696  6356696 -37862896       6380    0
0       6356696 -37862896       6380    0
1255925 6356696 -37862896       6380    0
9       6356696 -37862896       6380    0
Alaska  6356696 -37862896       6380    0
122640  6356696 -37862896       6380    0
0       6356696 -37862896       6380    0
164676  6356696 -37862896       6380    0
3       6356696 -37862896       6380    0
Arizona 6356696 -37862896       6380    0
1025232 6356696 -37862896       6380    0
0       6356696 -37862896       6380    0
1233654 6356696 -37862896       6380    0
11      6356696 -37862896       6380    0
Arkansas        6356696 -37862896       6380    0
394409  6356696 -37862896       6380    0
0       6356696 -37862896       6380    0
647744  6356696 -37862896       6380    0
6       6356696 -37862896       6380    0
California      6356696 -37862896       6380    0
7854285 6356696 -37862896       6380    0
55      6356696 -37862896       6380    0
4839958 6356696 -37862896       6380    0
0       6356696 -37862896       6380    0

您的 scanf 格式字符串包含逗号,但您的输入数据不包含逗号。

请注意, fscanf返回 EOF 或成功扫描的值的数量。 您可以并且应该使用该返回值来检查错误,这样做会指出您代码中的问题。

fscanf格式字符串中的逗号告诉fscanf期望文件中有逗号,如果找不到它们就停止。

您的文件中没有逗号,因此fscanf在读取%s转换的“字符串”后停止。

从格式字符串中删除逗号。

测试fscanf的返回值是否等于您希望分配的项目数,而不仅仅是它不等于EOF

可避免的编码弱点导致 OP 的困难

如果代码根据 5 的期望结果而不是许多不正确的结果之一(如EOF, 0, 1, 2, 3, 4 )检查返回值,那么问题将很快缩小为 scanf 失败。

// while (fscanf(f, "%s, %ld, %ld, %ld, %ld", temp1, &temp2, &temp3, &temp4, &temp5) != EOF) {
while (fscanf(f, "%s, %ld, %ld, %ld, %ld", temp1, &temp2, &temp3, &temp4, &temp5) == 5) {

其他问题

空白

除了样式之外,在"%ld"之前放置一个" "没有任何价值,因为"%ld"已经消耗了可选的前导空白。

然而,在","之前放置一个空格以允许在','之前输入可选的前导空格是有价值的。

while (fscanf(f, "%s ,%ld ,%ld ,%ld ,%ld", temp1, &temp2, &temp3, &temp4, &temp5) == 5) {

缓冲区溢出

切勿在(f)scanf() function 中使用"%s" 使用宽度限制,否则有缓冲区溢出的风险。

// width   --------vv
while (fscanf(f, "%19s ,%ld ,%ld ,%ld ,%ld", temp1, &temp2, &temp3, &temp4, &temp5) == 5) {

fgetc()返回一个int

fgetc(f)返回 257 个不同的值。 使用int正确区分。

// char x;
int x;
...
while ((x = fgetc(f)) != EOF) {

行数可能会失败

数仅计算'\n'的数量。 如果文件仅包含"abc 1 2 3 4" ,没有'\n' ,则行数将报告为 0。

而是计算行首的数量。

count = 0;
int prior = '\n';
while ((x = fgetc(f)) != EOF) {
  if (prior == '\n') {
    count++;
  }
  prior = x;
  ...
}

暂无
暂无

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

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