2013-03-20 5 views
1

Я пытался реализовать функцию getchar(), используя read() в unistd.h.Реализация getchar с чтением

Поскольку системные вызовы являются дорогостоящими, я хотел как можно меньше выполнять функции read().

Если я использую «getchar», он отлично работает. Однако в этом случае «мегаджет» не работает.

Может ли кто-нибудь указать, что я сделал неправильно ниже?

#include <stdio.h> 
#include <unistd.h> 

#define BUF_SIZE 1024 

int startIndex; 
int endIndex; 

int mygetchar(void){ 
    char buffer[BUF_SIZE]; 
    startIndex=0; 
    endIndex=0; 
    if(startIndex == endIndex){ 
    int r; 
    r = read(0,buffer,BUF_SIZE); 
    startIndex=0; 
    endIndex=r; 
    } 
    return buffer[startIndex++]; 
} 


int main(){ 
    char c; 
    int i=0; 
    do{ 
    c = mygetchar(); 
    putchar(c); 
    i++; 
    } 
    while(c != EOF); 
    return 0; 
} 
+0

Вам также нужно сделать «буфер» глобальным. В противном случае вы читаете и отбрасываете до 1023 символа на каждый вызов для чтения, а последующие вызовы на возврат мусора 'mygetchar'. – Anthony

ответ

1

Подумайте о своем буфере. Что происходит с буфером при завершении вызова функции? Он уходит.

Это означает, что для 1023 из 1024 вызовов ваш буфер является унифицированным, а ваши смещения указывают на бессмысленные данные.


В основном вам нужно глобальную переменную для буфера тоже:

static char buf[BUF_SIZE]; 
static size_t bufCur = 0; 
static size_t bufEnd = 0; 

int mygetchar(void) 
{ 
    // ... 
} 

(Обратите внимание, что статический довольно много бессмысленно, если ваш код в одном файле Если бы вы подтяните mygetchar. в заголовке и реализации файла, хотя, вы хотите использовать статический глобальный таким образом, чтобы сохранить его от связываемых с внешней стороны одного и того же блока компиляции)

(Забавный факт:. в 0 s для bufCur и bufEnd акта может быть левым неявным. Для ясности я бы поставил их, но standard dictates, чтобы они были инициализированы нулями.


Как Джонатан Леффлера отметил, если вы не планируете использовать буфер в другом месте (и я не знаю, где это было бы), нет никакой необходимости в глобальной. Вы можете просто использовать статическую переменную внутри функции:

void mygetchar(void) 
{ 
    static buf[BUF_SIZE]; 
    static size_t bufCur = 0; 
    static size_t bufEnd = 0; 
    // ... 
} 
+2

Ну, он на самом деле вызывает 'read' каждые 1024 вызова (при условии, что в файле достаточно, чтобы заполнить буфер за один вызов). Каждый последующий вызов возвращает индекс в неинициализированный массив, потому что 'buffer' является локальной переменной. – Anthony

+0

@ anthony-arnold Ах, ты прав. Я не заметил, что его позиции были глобальными :). – Corbin

+3

Или все три переменные могут быть сделаны «static» в функции. Это может быть лучше; это предотвратит доступ любого другого кода к переменным. –