while((my_char = (char)fgetc(infile)) != EOF){
Это плохие времена. fgetc
возвращает int
. Может представлять больше значений, чем char
. EOF
обычно -1
. Так как вы храните в char
, как вы ожидаете представить символ 0xff
? Вы не будете; в конечном итоге вы будете воспринимать это как EOF
. Вы должны сделать это:
int c;
while ((c=fgetc(infile)) != EOF)
{
char my_char = c;
Далее ...
token = (char *)malloc(sizeof(char));
Вам следует проверить возвращаемое значение malloc
. Вам также следует подумать о том, чтобы выделить больше, чем вам нужно, иначе каждый вызов realloc
может потенциально скопировать символы, которые вы видели до сих пор. Вы получите лучшую алгоритмическую сложность, скажем, сделав каждый размер выделения степенью 2. Кроме того, в отличие от C ++, в C вам не нужно приводить из void*
.
memset(token, '\0', 1);
strcpy(token, &my_char);
Это не то, что вы думаете, это значит. (&my_char)[1]
должно быть равно нулю, чтобы это работало, так что это неопределенное поведение. Вы должны попробовать это:
token[0] = my_char;
token[1] = 0;
Кроме того, вы выделили только 1 char
. Вам нужно 2, чтобы это сработало.
token = (char *)realloc(token, sizeof(token) + 1);
sizeof
волшебным образом не запоминает, сколько вы выделили в прошлый раз, он принимает только размер времени компиляции указанного типа, в данном случае эквивалентный sizeof(char*)
, который будет 4 или 8 на 32 или 64- битовые системы соответственно. Вам необходимо отслеживать реальный размер размещения в переменной. Также этот тип realloc
подвержен утечке памяти при сбое, вы должны сделать это:
void *ptr = realloc(token, new_length);
if (!ptr) { /* TODO: handle error */ }
token = ptr;
Двигаемся дальше ...
strcat(token, &my_char);
Это имеет то же неопределенное поведение, что и при последнем использовании &my_char
, как если бы это была строка C. Кроме того, даже если это сработало, это расточительно, поскольку strcat
должен пройти всю строку, чтобы найти конец.
Резюме моих предложений следующее:
int c;
size_t alloc_size = 0;
size_t current_len = 0;
char *token = NULL;
void *ptr;
while ((c = fgetc(infile)) != EOF)
{
if (is_digit(c))
{
if (alloc_size < current_len + 2)
{
if (!alloc_size)
{
// Set some arbitrary start size...
//
alloc_size = 64;
}
else
{
alloc_size *= 2;
}
if (!token)
ptr = malloc(alloc_size);
else
ptr = realloc(token, alloc_size);
if (!ptr)
{
free(token);
return -1;
}
}
token[current_len++] = c;
token[current_len] = 0;
}
}
/* TODO: do something with token... */
free(token);