Чтение регистра фиксированного размера с пробелами из файла - PullRequest
0 голосов
/ 02 июля 2019

Я пытаюсь прочитать регистр фиксированного размера из текстового файла в c.

Структура регистра следующая:

00030REGIST X1Y005.0

  • 5 символов для целого числа
  • 10 символов для строки (с пробелами)
  • 5 символов для числа с плавающей запятой

Когда япопробуйте прочитать регистр, я получаю следующий результат:

00030REGIST X1Y005.00.00000

Я получаю 0,00000 в конце строки

#include <stdio.h>
#include <stdlib.h>

int main () { 
    int id;
    float price;
    char desc[11];
    FILE * data_file;

    //Reading from file
    if(!(data_file = fopen("./products.txt","r"))){
        printf("\nError reading file\n");
        exit(2);
    }

    // The value of the register is 00030REGIST X1Y005.0
    // But i get                    00030REGIST X1Y005.00.00000
    while (fscanf(data_file,"%05d %[^\n]10s %05f", &id, desc, &price) != EOF) {
        printf("%05d%s%05f\n",id , desc, price);
    }

    fclose(data_file);

    return(0);
}

Ответы [ 2 ]

1 голос
/ 02 июля 2019

У вас есть:

while (fscanf(data_file,"%05d %[^\n]10s %05f", &id, desc, &price) != EOF)

Возможно, вам нужно:

while (fscanf(data_file,"%5d %40[^\n0-9] %5f", &id, desc, &price) == 3)

Значение 40 основано на размере desc (вы указываете на единицу меньше в строке форматачем в длине, объявленной для массива).Обратите внимание, что набор сканирования %[…] сам по себе является преобразованием.10s в вашей версии ищет конкретные символы 1, 0 и s (и это не удастся - следующим символом будет символ новой строки или конец файла, поскольку вы не указалиразмер для набора сканирования).И тест должен быть на ожидаемое количество конверсий;что-либо еще является ошибкой какого-либо рода.

Если имена регистров могут содержать цифры, вы попадаете в ловушку, потому что REGISTER XVY - это 12 символов, считая пробел (что противоречит вашему утверждению, что имена регистров имеют длину до 10 символов),Указание любого меньшего значения, чем 12, в %12[^\n0-9] не приведет к преобразованию этого имени и следующего числа, поскольку оно оставит нецифровые символы во входных данных.

Если у вас должны быть цифры в имени регистра, у вас естьпринять другую стратегию.Вы прочитали строку, затем удалили первые 5 цифр и конвертировали их, удалили последние 5 цифр и конвертировали их, и взяли то, что осталось в качестве имени регистра, возможно, убрав начальные и конечные пробелы.

1 голос
/ 02 июля 2019

Редактировать: я изменил программу, чтобы читать 10 строковых символов, которые могут включать цифры.

Спецификатор формата %[^\n]10s - странный гибрид %s и %[].Я предлагаю следующее, вот только одну строку для примера, и для ясности добавлены новые строки в вывод.

#include <stdio.h>

int main(void)
{
    int id;
    float price;
    char desc[11];
    char input[] = "00030REGIST X1Y005.0";
    int res = sscanf(input, "%d%10[^\n]%f", &id, desc, &price);
    if(res == 3) {
        printf("%05d\n%s\n%05f\n",id , desc, price);
    }
}

Вывод программы:

00030
REGIST X1Y
5.000000
...