Приведение символа из строки чтения файла в int сбрасывает ядро

#c #scanf #fgets #atoi

#c #scanf #fgets #atoi

Вопрос:

Привет, я довольно новичок в c и пытаюсь внедрить код. В первый день задача состоит в том, чтобы прочитать файл со следующим текстом (репрезентативным) внутри:

 forward 8
up 6
down 3
...
 

цель состоит в том, чтобы добавить числа в конце к int, выбранному словом перед числом.

Поскольку я новичок в c, я решил сделать это шаг за шагом и иметь следующий код для чтения просто зачитайте первую букву, чтобы решить, какое действие выполнить, а также число, которое я хочу сохранить как int value :

 FILE * file = fopen("./puzzle.input", "r");
char line[255];
while (fgets(line, sizeof(line), file)) {
    if (line[0] == 'f') {            
        last_pos = strlen(line);
        int value;
        sscanf(line[8], "%d", amp;value);            
    }
 

Это не удается с:

 [1]    3931 segmentation fault (core dumped)
 

Самое странное, что когда я printf("%c", line[8]) выводлю правильное число. Поэтому я подозреваю, что кастинг проходит ужасно неправильно. Я пробовал это atoi , и это также не сработало. Простое приведение его с (int) помощью возвращало неправильное число, всегда около 50.
Теперь мои вопросы:

  • Почему (int) возвращает что-то около 50
  • Как это исправить
  • Как я могу предотвратить это в будущем.

Большое вам спасибо, я с нетерпением жду обучения!

Комментарии:

1. line[8] это char (одна буква или также число от -128 до 127), sscanf хочет получить указатель на строку с нулевым завершением. Когда он пытается интерпретировать номер, который вы ему дали, как адрес памяти, он выходит из строя. Вы могли бы попробовать line 8 (пропустить первые 8 символов).

2. 50-см. en.wikipedia.org/wiki/ASCII — от 48 до 57 — это коды для цифровых символов.

3. Аргумент sscanf является указателем на char, попробуйте amp;line[8] . (Также включите предупреждения компилятора.) Но в целом это очень хрупкий способ создания синтаксического анализатора, возможно strtok , строка для разделения его на поля или что-то в этом роде.

4. А что, если строка короче 8 байт данных?

Ответ №1:

Существует несколько методов чтения целого числа после текста. Вы можете добавить временный буфер, чтобы пропустить первое слово.

 while (fgets(line, sizeof(line), file))
{
    int value = 0;
    char temp[255];
    if (sscanf(line, "%s %d", temp, amp;value) == 2)
        printf("%s, %dn", temp, value);
    //if (strcmp(temp, "forward") == 0) printf("...");
}
 

Или используйте strstr , чтобы увидеть, содержит ли строка "forward"

 while (fgets(line, sizeof(line), file))
{
    const char* key = "forward";
    if (strstr(line, key) == line) //line starts with "forward"
    {
        int value = 0;
        if (sscanf(line   strlen(key), " %d", amp;value) == 1)
            printf("%s, %dn", key, value);
    }
}
 

Или используйте strtok , чтобы разбить строку на word и atoi преобразовать word в целое число.

Обязательно инициализируйте переменную, иначе она будет содержать случайные значения, оставшиеся в памяти.

sscanf(line[8], "%d", amp;value); как вы можете видеть, неверно. Первым параметром должна быть строка, но line[8] это символ, и компилятор должен предупредить. Проблема с проверкой if (line[0] == 'f') заключается в том, что строка может содержать "forw 8" , вы не хотите, чтобы она считывала, завершающий нулевой символ.