У меня есть функция, которая возвращает количество строк, символов и слов в массиве. По какой-то причине, когда я перебираю массив для печати значений, я получаю только правильное значение для строк, символы и слова возвращаются как 0. Все функции предопределены моим профессором, и моя работа состоит в том, чтобы заполнить их.
int main(int argc, char **argv)
{
int *myArray = get_counts(argv[1]);
for (int i = 0; i < 3; i++)
{
printf("%d\n", myArray[i]);
}
return 0;
}
int *get_counts(char *filename)
{
FILE *file;
file = fopen(filename, "r");
if (file == NULL)
{
printf("NULL FILE");
}
char c;
int h;
bool whitespace = true;
static int arr[3] = {0,0,0};
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
while (true)
{
h = fgetc(file);
if (feof(file))
{
break;
}
else if (ferror(file))
{
printf("error reading file");
}
arr[2] ++;
if (whitespace && !isspace(h))
{
arr[1] ++;
whitespace = false;
}
else if (!whitespace &&isspace(h))
{
whitespace = true;
}
}
fclose(file);
return arr;
}
@Jason Fan После первого цикла do-while возникает условие EOF.
Вам нужно сделать что-то другое, кроме как продолжать как обычно, если fopen не работает.
Использование переменной char
(например, c
) для хранения возвращаемого значения fgetc
опасно, поскольку она не может содержать все возможные возвращаемые значения (EOF (-1) или 0..255). В лучшем случае, если ваш файл содержит символ 0xff, он будет рассматриваться как преждевременный EOF. В худшем случае (в системе, где char
не имеет знака) он никогда не завершится.
После первого цикла do-while возникает условие EOF.
do
{
c = fgetc(file);
if (c == '\n')
{
arr[0] ++;
}
}while (c != EOF);
Таким образом, следующий цикл while не имеет никакого эффекта.
Вы должны использовать только один цикл для подсчета строк, слов и символов.
Обратите внимание, что переменная c
должна быть объявлена как имеющая тип int
int c;
Также необходимо выйти из функции, если файл не был открыт.
Лучший вариант, вероятно, — просто перебрать файл в одном цикле (вы также можете rewind()
после первого цикла). Используйте возвращаемое значение fgetc()
, чтобы определить, находитесь ли вы в EOF
вместо отдельных вызовов feof()
. Я также сделал массив результатов аргументом (out) вместо использования статической переменной (последняя не является реентерабельной, если вы когда-нибудь захотите вызывать это из нескольких потоков, и это легко сделать):
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
void get_counts(char *filename, int arr[3]) {
memset(arr, 0, 3 * sizeof(int));
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("NULL FILE");
return;
}
bool whitespace = true;
for(;;) {
int c = fgetc(file);
if (c == EOF)
break;
else if (c == '\n')
arr[0]++;
else if (whitespace && !isspace(c)) {
arr[1]++;
whitespace = false;
} else if (!whitespace && isspace(c))
whitespace = true;
arr[2]++;
}
fclose(file);
}
int main(int argc, char **argv) {
int myArray[3];
get_counts(argv[1], myArray);
for (int i = 0; i < 3; i++) {
printf("%d\n", myArray[i]);
}
}
Вывод в указанном выше файле:
39
94
715
Количество слов 94 не согласуется с wc -w
, но вы можете использовать другое определение того, что такое слово.
Рекомендуется разделить вычисления и ввод-вывод, поэтому рассмотрите возможность открытия и закрытия файла в main()
и передачи дескриптора файла. Например, становится проще использовать дескриптор файла stdin
, если вы не хотите использовать физический файл.
Используйте отладчик, чтобы пройтись по коду, чтобы выяснить, где находится ваша логическая ошибка и что происходит не так. Если вы не знаете, как пользоваться отладчиком, самое время начать учиться. Отладчик — это самый мощный инструмент, доступный программисту, и никогда не рано начать его использовать.