Сначала попросите программу сообщить вам, что не так, проверив errno
, установленный при сбое, например, во время fseek
или ftell
.
Другие (tonio & LatinSuD)объяснил ошибку с обработкой стандартного ввода по сравнению с проверкой имени файла.А именно, сначала проверьте argc
(количество аргументов), чтобы увидеть, указаны ли какие-либо параметры командной строки if (argc > 1)
, рассматривая -
как особый случай, означающий stdin
.
Если параметры не указаны, то предположим, что входные данные (собираются) поступят из stdin
, который является потоком , а не файлом, и функция fseek
завершается с ошибкой.
В случае потока, где вы не можете использовать библиотечные функции, ориентированные на файл (например, fseek
и ftell
), вам просто нужно подсчитать количество прочитанных байтов (включая завершающие символы новой строки).) до получения EOF (конец файла).
Для использования с большими файлами вы можете ускорить его, используя fgets
для массива char для более эффективного чтения байтовв (текстовом) файле.Для двоичного файла вам нужно использовать fopen(const char* filename, "rb")
и использовать fread
вместо fgetc/fgets
.
Вы также можете проверить для feof(stdin)
/ ferror(stdin)
при использовании метода подсчета байтов для обнаружениялюбые ошибки при чтении из потока.
Пример ниже должен быть совместим с C99 и переносимым.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
long getSizeOfInput(FILE *input){
long retvalue = 0;
int c;
if (input != stdin) {
if (-1 == fseek(input, 0L, SEEK_END)) {
fprintf(stderr, "Error seek end: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (-1 == (retvalue = ftell(input))) {
fprintf(stderr, "ftell failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
if (-1 == fseek(input, 0L, SEEK_SET)) {
fprintf(stderr, "Error seek start: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
} else {
/* for stdin, we need to read in the entire stream until EOF */
while (EOF != (c = fgetc(input))) {
retvalue++;
}
}
return retvalue;
}
int main(int argc, char **argv) {
FILE *input;
if (argc > 1) {
if(!strcmp(argv[1],"-")) {
input = stdin;
} else {
input = fopen(argv[1],"r");
if (NULL == input) {
fprintf(stderr, "Unable to open '%s': %s\n",
argv[1], strerror(errno));
exit(EXIT_FAILURE);
}
}
} else {
input = stdin;
}
printf("Size of file: %ld\n", getSizeOfInput(input));
return EXIT_SUCCESS;
}