fscanf не сканирует номера

В настоящее время я разрабатываю простое приложение C. Он принимает один файл в качестве аргумента командной строки, который имеет следующий формат:

1,2,3
4,5,6
7,8,9
etc.

Однако по какой-то причине fscanf никогда не сканирует числа! Вот пример:

#include <stdio.h>

int main(int argc, char **argv) {
    FILE *file = fopen(*argv, "r");
    int i1, i2, i3;
    while (fscanf(file, "%d,%d,%d", &i1, &i2, &i3) == 3) {
        printf("Doing stuff with %d, %d, and %d...\n", i1, i2, i3);
    }
    fclose(file);
    return 0;
}

Если вы запустите его с именем файла в качестве аргумента, он немедленно завершится, потому что fscanf возвращает 0. Я пробовал несколько вариантов этого, но безрезультатно. Как заставить fscanf правильно читать числа?


person LegionMammal978    schedule 27.01.2016    source источник
comment
Почему бы вам не проверить возвращаемое значение fopen()?   -  person Sourav Ghosh    schedule 27.01.2016
comment
@BLUEPIXY facepalm Не могли бы вы опубликовать это как ответ?   -  person LegionMammal978    schedule 27.01.2016
comment
@SouravGhosh Для моих целей можно предположить, что файл существует.   -  person LegionMammal978    schedule 27.01.2016
comment
@LegionMammal978 Не предполагайте. Проверьте и убедитесь. :)   -  person Sourav Ghosh    schedule 27.01.2016
comment
@SouravGhosh В любом случае это только для личного использования; p   -  person LegionMammal978    schedule 27.01.2016
comment
Это просто недоразумение. (он содержит команду на C.) Это часто бывает.   -  person BLUEPIXY    schedule 27.01.2016
comment
@SouravGhosh Хотя у вас есть общая мысль - ради всего святого, всегда проверяйте возвращаемые значения! -- Тут не поможет! Программа может открыть argv[0] в порядке, но, увы, она сможет сканировать только три числа, разделенные запятыми, из этих байтов в исключительных случаях ;-).   -  person Peter - Reinstate Monica    schedule 27.01.2016
comment
Что случилось с ответами?   -  person Peter - Reinstate Monica    schedule 27.01.2016
comment
Вы открываете исполняемый файл программы   -  person Jack    schedule 27.01.2016
comment
См.: stackoverflow.com/q/2050961/5399734   -  person nalzok    schedule 27.01.2016


Ответы (2)


Поверхностный ответ: был открыт неправильный файл, так как код должен был использовать argv[1], а не *argv.

Давайте посмотрим глубже.

В коде были проблемы и отсутствовала проверка ошибок по крайней мере в двух местах.

  1. FILE *file = fopen(*argv, "r"); не сопровождался тестом на file. Эта классическая проверка не обнаружила бы проблему OP, поскольку исполняемый файл можно было открыть.

  2. Возвращаемое значение из fscanf(file, "%d,%d,%d", &i1, &i2, &i3) было протестировано лишь слегка. Возвращаемые значения EOF 0 1 2 3 были возможны, но ожидались только EOF 3. Если бы код был протестирован на не-EOF 3, проблема была бы быстро обнаружена.

Урок, который следует усвоить: убедитесь, что код, особенно код, который ведет себя неправильно, имеет адекватную проверку ошибок. Экономит время программиста в долгосрочной перспективе.

#include <stdio.h>

int main(int argc, char **argv) {
  if (argc != 2) {
    fprintf(stderr, "Unexpected argument count %d.\n", argc);
    return 1;
  } 
  FILE *file = fopen(argv[1], "r");
  if (file == NULL) {
    fprintf(stderr, "Unable to open file: \"%s\"", argv[1]);
    return 1;
  } 
  int i1, i2, i3;
  int n;
  while ((n = fscanf(file, "%d,%d,%d", &i1, &i2, &i3)) == 3) {
    printf("Doing stuff with %d, %d, and %d...\n", i1, i2, i3);
  }
  if (n != EOF) {
    fprintf(stderr, "Unexpected scan failure count %d\n", n);
    return 1;
  }
  fclose(file);
  return 0;
}
person chux - Reinstate Monica    schedule 27.01.2016
comment
Большая часть этого была проверена в более ранних итерациях. Я проверил файл (это не был NULL), я посмотрел на возвращаемые значения fscanf (он продолжал возвращать 0) и проверил значения in (они никогда не менялись). - person LegionMammal978; 28.01.2016

Как отмечает BLUEPIXY, вы должны использовать второй элемент массива argv: argv[1]:

FILE *file = fopen(argv[1], "r");

Первый элемент (argv[0] или *argv) — это имя выполняемой программы — это не тот файл, который нужно открыть.

person Community    schedule 27.01.2016