#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"
, вы не хотите, чтобы она считывала, завершающий нулевой символ.