Я написал эту небольшую функцию, чтобы прочитать все данные от stdin
.Читать все данные stdin C
мне нужно знать, если эта функция POSIX совместимой (этим, я имею в виду, что будет работать под Unix и Unix-подобных системах) по крайней мере, он работает на Windows ...
char* getLine()
{
int i = 0, c;
char* ptrBuff = NULL;
while ((c = getchar()) != '\n' && c != EOF)
{
if ((ptrBuff = (char*)realloc(ptrBuff, sizeof (char)+i)) != NULL)
ptrBuff[i++] = c;
else
{
free(ptrBuff);
return NULL;
}
}
if (ptrBuff != NULL)
ptrBuff[i] = '\0';
return ptrBuff;
}
Функция читает все данные из stdin до получения '\n'
или EOF
и возвращает указатель на новое местоположение со всеми символами. Я не знаю, является ли это наиболее оптимальным или безопасным способом сделать это, и не знаю, работает ли это в Unix и Unix-подобных системах ... поэтому мне нужна небольшая помощь здесь. Как я могу улучшить эту функцию? или есть лучший способ получить все данные от stdin
, не оставляя мусор в буфере? Я знаю, что fgets()
вариант, но он может оставить мусор, если пользовательский ввод больше, чем ожидалось ... плюс, я хочу получить все символы, которые пользователь написал.
EDIT:
Новая версия getLine()
:
char* readLine()
{
int i = 0, c;
size_t p4kB = 4096;
void *nPtr = NULL;
char *ptrBuff = (char*)malloc(p4kB);
while ((c = getchar()) != '\n' && c != EOF)
{
if (i == p4kB)
{
p4kB += 4096;
if ((nPtr = realloc(ptrBuff, p4kB)) != NULL)
ptrBuff = (char*)nPtr;
else
{
free(ptrBuff);
return NULL;
}
}
ptrBuff[i++] = c;
}
if (ptrBuff != NULL)
{
ptrBuff[i] = '\0';
ptrBuff = realloc(ptrBuff, strlen(ptrBuff) + 1);
}
return ptrBuff;
}
Последнее редактирование:
Это последняя версия функции char* readLine()
. Теперь я не вижу больше ошибок и лучших способов улучшить его, если кто-то знает лучший способ, просто скажите мне, пожалуйста.
char* readLine()
{
int c;
size_t p4kB = 4096, i = 0;
void *newPtr = NULL;
char *ptrString = malloc(p4kB * sizeof (char));
while (ptrString != NULL && (c = getchar()) != '\n' && c != EOF)
{
if (i == p4kB * sizeof (char))
{
p4kB += 4096;
if ((newPtr = realloc(ptrString, p4kB * sizeof (char))) != NULL)
ptrString = (char*) newPtr;
else
{
free(ptrString);
return NULL;
}
}
ptrString[i++] = c;
}
if (ptrString != NULL)
{
ptrString[i] = '\0';
ptrString = realloc(ptrString, strlen(ptrString) + 1);
}
else return NULL;
return ptrString;
}
См. Это сообщение в блоге: http://powerfield-software.com/?p=65 - он также использовался как ответ на пару вопросов здесь, на SO. – paxdiablo
Да, ваша функция POSIX, я тестировал ее с помощью gcc в Linux и, похоже, работает так, как ожидалось. –
Выделение одного байта в такое время может привести к квадратичной производительности - что не очень хорошо. Вы должны выделять блоки данных одновременно, возможно удваивая пространство, выделяемое каждый раз, когда вам нужно больше места. Следует также отметить, что 'ptrBuff = realloc (ptrBuff, new_size);' утечка памяти при сбое распределения, потому что вы пишете NULL по единственному указателю на предыдущее распределение памяти. 'Free (ptrBuff);' является безопасным, потому что 'free (NULL)' является no-op. Он не освобождает память, потому что 'ptfBuff' больше не указывает на нее. Используйте 'void * new_space = realloc (ptrBuff, new_size);' и проверьте значение nullness. –