#c #bash
#c #bash
Вопрос:
Я тестировал эту функцию на каком-то образце текстового файла, чтобы убедиться, что она работает должным образом.
#include <stdio.h>
#include <time.h>
#define BUF 100
int main(){
FILE *fp = fopen("my_huge_file.txt","r");
char str[BUF];
int count=0;
while( (fgets(str, BUF, fp)) != NULL ){
for (int i = 0; i<BUF;i ){
if (str[i] == 'A')
count ;
}
}
printf("We had %d 'A'sn",count);
}
Запуск этого с помощью time ./a.out
печати:
We had 420538682 'A's real 0m31.267s user 0m28.590s sys 0m2.531s
Затем я использовал time tr -cd A < my_huge_file.txt | wc -c
и вернулся:
420538233 real 0m13.611s user 0m10.688s sys 0m3.297s
Я также использовал метод подсчета python time count.py
:
c = 0
with open("my_huge_file.txt", 'r') as fp:
for line in fp:
c = line.count('A')
print(c)
420538233 real 0m33.073s user 0m30.232s sys 0m2.650s
Я не уверен, как расследовать это несоответствие. количество tr и python возвращает 420538233. Функция C возвращает 420538682.
Комментарии:
1. Вы используете
fgets
для чтения строки, но не соблюдаете границы строки при подсчете. В этой проблеме нет ничего ориентированного на строку. Вместоfgets
этого используйтеfgetc
. Это упрощает логику и устраняет текущую ошибку.
Ответ №1:
Попробуйте изменить:
for (int i = 0; i<BUF;i ){
Для
for (int i = 0; i<BUF amp;amp; str[i] ;i ){
Посмотрите, получите ли вы другой результат….
Комментарии:
1. Это сработало!
420538233
Я предполагаю, что из предыдущих циклов for были добавлены непустые символы?2. скорее всего; кроме того, обычно вы должны читать в буфер LINE_MAX (из limits.h).
Ответ №2:
Нет причин усложнять ваш код fgets
. (Проблема, с которой вы сталкиваетесь, заключается в том, что fgets
считывает строку и заполняет только часть вашего буфера, но вы считаете все в буфере, включая значения, которые не были получены из входных данных.) Просто считывайте по одному символу за раз:
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char **argv)
{
int c;
int count=0;
FILE *fp = argc > 1 ? fopen(argv[1], "r") : stdin;
if( fp == NULL ){
perror(argv[1]);
exit(EXIT_FAILURE);
}
while( (c = fgetc(fp)) != EOF ){
if( c == 'A' ){
count = 1;
}
}
printf("We had %d 'A'sn", count);
return 0;
}
Комментарии:
1. Спасибо! Разве fgets не будет буферизировать ввод-вывод и работать быстрее?
2. Оба
fgets
иfgetc
буфер ввода-вывода. Такое же количествоread
системных вызовов будет (почти наверняка) выполнено. Если вас это беспокоит, используйтеfread
вместо этого. Но вряд ли это будет значительным улучшением. Выgetc
также можете попробовать, но, опять же, разница вряд ли будет существенной.