@newmersedez

Парсинг строки не через strtok на СИ. В чем заключается ошибка?

Здравствуйте, возникла проблема, и, в силу моей неопытности, я уже два часа ломаю голову, почему же так происходит.

Есть входной файл с операциями. Например, такое содержимое:
myvar=15;
bg=25;
ccc=bg+myvar;
print ccc;
bg=ccc*myvar;
print;

На данном этапе мне необходимо произвести парсинг строки, чтобы, к примеру, получилось "myvar" "=" "15";

В функции parse_string() я описываю сам процесс парсинга, но почему-топ прога не работает, она просто виснет. Как я выяснил, причина в строках free(buf), однако я не понимаю, почему так. Я знаю, что строку можно распарсить через strtok, но я хочу сохранить знаки операций.

Вот сам код(Код на с, вставил с++, тк на форуме нет возможности вставить код си)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
 
typedef struct memoryCell
{
    char    *name;
    int     data;
}memoryCell;
 
int     variable_processing(FILE *file, memoryCell *variables);
char    **parse_string(char string[]);
 
int     main(int argc, char *argv[])
{
    int         result;
    FILE        *file;
    memoryCell  *variables;
 
    if(argc != 2)
    {
        perror("Arguments error");
        exit(-1);
    }
    if(!(file = fopen(argv[1], "r")))
    {
        perror("File error");
        exit(-2);
    }
    result = variable_processing(file, variables);
    if(result != 0)
    {
        printf("Error in line %d!\n", result);
        return (-1);
    }
    fclose(file);
    return 0;
}
 
/*task - variables processing
returns 1 if correct*/
int     variable_processing(FILE *file, memoryCell *variables)
{
    char    **parsed_string;
    char    buf[BUFSIZ];
    int     size;
 
    size = 0;
    variables = NULL;
    while(!feof(file))
    {
        fgets(buf, sizeof(buf), file);
        strtok(buf, "\n");
        parsed_string = parse_string(buf);
    }
 
    return (0);
}
 
char    **parse_string(char string[])
{
    int     i;
    int     j;
    int     k;
    int     size;
    char    **parsed_string = NULL;
    char    *buf = NULL;
 
    size = 0;
    k = 0;
    for(i = 0; i < strlen(string); i++)
    {
        if(isdigit(string[i]) || isalpha(string[i]))
        {
            j = i;
            while(isdigit(string[j]) || isalpha(string[j]))
            {
                buf = (char *)realloc(buf, ++k * sizeof(char));
                buf[k - 1] = string[j];
                j++;
            }
            parsed_string = (char **)realloc(parsed_string, ++size * sizeof(char *));
            parsed_string[size - 1] = (char *)malloc(strlen(buf) * sizeof(char));
            strcpy(parsed_string[size - 1], buf);
            free(buf);
            k = 0;
            i = j - 1;
        }
        else
        {
        buf = (char *)malloc(sizeof(char));
        buf[0] = string[i];
        parsed_string = (char **)realloc(parsed_string, ++size * sizeof(char *));
        parsed_string[size - 1] = (char *)malloc(strlen(buf) * sizeof(char));
        strcpy(parsed_string[size - 1], buf);
        free(buf);
        }
    }
    for(i = 0; i < size; i++)
        printf("%s ", parsed_string[i]);
    printf("\n");
    return (parsed_string);
}
  • Вопрос задан
  • 430 просмотров
Решения вопроса 1
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
sizeof(char)

Всегда равен 1 согласно стандарту, сэкономь нам и себе время.

while(isdigit(string[j]) || isalpha(string[j]))
            {
                buf = (char *)realloc(buf, ++k * sizeof(char));
                buf[k - 1] = string[j];
                j++;
            }

После этого цикла buf не закрыт 0-терминатором, работать с ним как со строкой нельзя.

parsed_string[size - 1] = (char *)malloc(strlen(buf) * sizeof(char));
strcpy(parsed_string[size - 1], buf);

Переполнение буфера, потому что strcpy копирует strlen(buf) символов строки + 1 нулевой байт.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@newmersedez Автор вопроса
Здравствуйте еще раз. Почему не работает, если в else дописать free(buf)? Без него все работает, парсит без ошибок и вылетов
char    **parse_string(char string[], int *size)
{
    int     i;
    int     j;
    int     k;
    char    **parsed_string = NULL;
    char    *buf = NULL;

    *size = 0;
    k = 0;
    for(i = 0; i < strlen(string); i++)
    {
        if(isdigit(string[i]) || isalpha(string[i]))
        {
            j = i;
            while(isdigit(string[j]) || isalpha(string[j]))
            {
                buf = (char *)realloc(buf, ++k * sizeof(char) + 1);
                buf[k - 1] = string[j];
                j++;
            }
            buf[k] = '\0';
            parsed_string = (char **)realloc(parsed_string, ++(*size) * sizeof(char *));
            parsed_string[(*size) - 1] = (char *)malloc(strlen(buf));
            strcpy(parsed_string[(*size) - 1], buf);
            free(buf);
            k = 0;
            i = j - 1;
        }
        else
        {
            buf = (char *)malloc(2);
            buf[0] = string[i];
            buf[1] = '\0';
            parsed_string = (char **)realloc(parsed_string, ++(*size) * sizeof(char *));
            parsed_string[(*size) - 1] = (char *)malloc(strlen(buf));
            strcpy(parsed_string[(*size) - 1], buf);
            // free(buf);
        }
    }
    for(i = 0; i < *size; i++)
        printf("'%s' ", parsed_string[i]);
    printf("\n");
    return (parsed_string);
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы