简体   繁体   English

fscanf 打印未知值

[英]fscanf printing unknown values

I am trying to use fscanf to take a text file and simply print it in the same format (eventually it will be used to populate an array of structures).我正在尝试使用 fscanf 获取一个文本文件并以相同的格式简单地打印它(最终它将用于填充结构数组)。

When I use fscanf it prints some values which are not part of the text and I'm not sure where they are coming from.当我使用 fscanf 时,它会打印一些不属于文本的值,我不确定它们来自哪里。 I have put a small part of the input text file and the output below the code section.我已将一小部分输入文本文件和 output 放在代码部分下方。

The values I want to print across the page horizontally are all in the first column of the output, which makes me think that its something to do with how I have defined my fprint statement?我想在页面上水平打印的值都在 output 的第一列,这让我觉得这与我如何定义我的 fprint 语句有关? Each of the correct values in the first column are followed by values which I don't know where have come from.第一列中的每个正确值后面都是我不知道从何而来的值。

Any help would be greatly appreciated.任何帮助将不胜感激。

#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;
}

Input file:输入文件:

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: 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

Your scanf format string includes commas, but your input data does not.您的 scanf 格式字符串包含逗号,但您的输入数据不包含逗号。

Note that fscanf returns either EOF, or the number of values successfully scanned.请注意, fscanf返回 EOF 或成功扫描的值的数量。 You can and should use that return value to check for errors, and doing so would have pointed you to the problem in your code.您可以并且应该使用该返回值来检查错误,这样做会指出您代码中的问题。

The commas in your fscanf format string tell fscanf to expect commas in the file and to stop if it does not find them. fscanf格式字符串中的逗号告诉fscanf期望文件中有逗号,如果找不到它们就停止。

There are no commas in your file, so fscanf stops after reading a “string” for the %s conversion.您的文件中没有逗号,因此fscanf在读取%s转换的“字符串”后停止。

Remove the commas from the format string.从格式字符串中删除逗号。

Test that the return value of fscanf equals the number of items you expect to be assigned, not just that it is not equal to EOF .测试fscanf的返回值是否等于您希望分配的项目数,而不仅仅是它不等于EOF

Avoidable coding weakness lead to OP's difficulty可避免的编码弱点导致 OP 的困难

Had code checked the return value against the desired result of 5 rather than one of the many incorrect ones like EOF, 0, 1, 2, 3, 4 , the issue would have been quickly narrowed to a scanf failure.如果代码根据 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) {

Other issues其他问题

White-space空白

No value, other than maybe style, to put a " " before "%ld" as "%ld" already consumes optional leading white-space.除了样式之外,在"%ld"之前放置一个" "没有任何价值,因为"%ld"已经消耗了可选的前导空白。

Yet there is value to put a space before the "," to allow for optional leading white-space input before the ',' .然而,在","之前放置一个空格以允许在','之前输入可选的前导空格是有价值的。

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

Buffer overflow缓冲区溢出

Never use "%s" in a (f)scanf() function.切勿在(f)scanf() function 中使用"%s" Use a width limit, else risk buffer overflow.使用宽度限制,否则有缓冲区溢出的风险。

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

fgetc() returns an int fgetc()返回一个int

fgetc(f) returns 257 different values. fgetc(f)返回 257 个不同的值。 Use an int to correctly distinguish.使用int正确区分。

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

Line count may fail行数可能会失败

Count of lines only counted the number of '\n' .数仅计算'\n'的数量。 Had the file only contained "abc 1 2 3 4" , with no '\n' , the line count would report as 0.如果文件仅包含"abc 1 2 3 4" ,没有'\n' ,则行数将报告为 0。

Instead count the number of line beginnings.而是计算行首的数量。

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