簡體   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