Сканирование из файлов

#c #enums #unions #scanf

#c #перечисления #объединения #scanf

Вопрос:

В настоящее время я пытаюсь отсканировать одну строку из файла, но у меня проблема со строками. Это пример строки, над которой мой профессор посоветовал мне поработать.

 enum status{MEM,PREP,TRAV}
union type { double int day, char* title, float cost}

13953 P 12 26 2011 1 5 2012 2 A 3.30 249.00 A 2.0 148.00 MEM Cuba Christmas 3 0 2 Sierra Del Rosario, Cuba
  

Меня устраивает все, что принимается в момент (например, Рождество на Кубе), когда я сканирую это из ФАЙЛА. Я прочитал первую часть данных, просто используя fscanf() , но MEM — это перечислимый тип с типом объединения, который определяет следующий ввод. Моя проблема заключается в синтаксисе сканирования. Я пытался использовать getline, начинающуюся с MEM, но я столкнулся с проблемами с маркировкой, поскольку в городе / стране могут быть пробелы. Не уверен, какие другие виды сканирования использовать, которые я просматривал sscanf() , но не был уверен, работает ли это с файлами.

ОБНОВЛЕНО:

 int main(void);
{
 int m, length = 100;
 char *word, file_name[100];
 FILE *file_point
 printf("Please enter file name with .txt extension:");
 scanf("%s", file_name);
 file_point = fopen(file_name,"r");

  while (fscanf(file_point, "%d", amp;m) != EOF)
  {

  temp.dest_code = m;
  fscanf(file_point, " %c %d %d %d %d %d %d %d",
     amp;temp.area_code,
     amp;temp.Smonth, amp;temp.Sday, amp;temp.Syear,
     amp;temp.Emonth, amp;temp.Eday, amp;temp.Eyear,
     amp;temp.leg_num);
  for (n=0; n < temp.leg_num; n  )
    {
      fscanf(file_point," %c %f %f",
         amp;temp.tleg[n].travel_type,
         amp;temp.tleg[n].travel_time,
         amp;temp.tleg[n].cost);
    }
  fscanf(file_point," %d %d %d ",
     amp;temp.adult,
     amp;temp.child,
     amp;temp.infant);


  temp_name = (char *)malloc(length   1);
  getline (amp;temp_name, amp;length, file_point);

  word = strtok(temp_name, ",");

  temp.dest_name=(char *)malloc(strlen(word) 1);
  strcpy(temp.dest_name, word);

  word = strtok(NULL, ",");

  temp.dest_country=(char *)malloc(strlen(word) 1);
  strcpy(temp.dest_country,word2);

  printf("name:%s country:%sn", temp.dest_name, temp.dest_country);
      printf("adult:%d , child:%d , infant:%d n", temp.adult, temp.child, temp.infant);

   }
}
  

Это был код, который я использовал в качестве основы, который я придумал, но не уверен, как обращаться с перечисляемым и объединением. Я думал о том, чтобы сделать что-то вроде:

 getline(amp;status, amp;length, file_point);
  

но как мне преобразовать строку в целое число или с плавающей точкой?

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

1. Ах да, забыл упомянуть, что я сканирую эту единственную строку из файла

2. не могли бы вы опубликовать какой-нибудь код, чтобы показать нам, что вы пытались сделать с этого момента?

3. enum В конце нужна точка с запятой. union Также нужна точка с запятой в конце, а запятые должны быть с запятой. Однако, если вы скомпилировали свой код, то проблема в том, что вы не скопировали и не вставили свой код.

Ответ №1:

Если я правильно понимаю вашу проблему (я не уверен, что понимаю), то вы сталкиваетесь с проблемой отображения ‘MEM’ (или ‘PREP’, или ‘TRAV’) во входных данных в виде строки, и вам нужно понять, как обрабатывать следующие данные. enum Предполагает, что вы, возможно, захотите преобразовать строку MEM в значение MEM в перечислении.

Трудно полностью автоматизировать такое преобразование. Проще всего было бы просто распознать строки и решить, что делать, основываясь на строке:

 if (strcmp(found_string, "MEM") == 0)
    ...do the MEM stuff...
else if (strcmp(found_string, "PREP") == 0)
    ...do the PREP stuff...
else if (strcmp(found_string, "TRAV") == 0)
    ...do the TRAV stuff...
else
    ...report unknown type code...
  

Однако вы можете создать структуру для обработки преобразования строки в значение перечисления.

 struct StateConv
{
     const char *string;
     enum state  number;
};

static struct StateConv converter[] =
{
    { "MEM",  MEM  },
    { "PREP", PREP },
    { "TRAV", TRAV },
};
enum { NUM_STATECONV = sizeof(converter) / sizeof(converter[0]) };

enum state state_conversion(const char *string)
{
    for (int i = 0; i < NUM_STATECONV; i  )
    {
        if (strcmp(string, converter[i].string) == 0)
            return(converter[i].number);
    }
    fprintf(stderr, "Failed to find conversion for %sn", string);
    exit(1);
}
  

Вам нужна лучшая стратегия обработки ошибок, чем «выход при ошибке».

Ваш код сканирования должен будет прочитать слово, а затем вызвать state_conversion() . Затем, в зависимости от того, что вы получите обратно, вы можете прочитать оставшиеся (следующие) данные правильным образом для заданного вам состояния.

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

1. ах, хорошо, я получал много ошибок, пытаясь обработать это как строку

Ответ №2:

Нет, вы не можете сделать это так, как пытаетесь. MEM в вашем файле имеет строковый тип, вам нужно проанализировать его, как вы анализируете строку, а затем установить значение вашего перечисления в соответствии с этой строкой. Например, когда вы хотите проанализировать тип вашего статуса (MEM, PREP, TRAV):

 char typeBuffer[6];
fscanf(file_point,"%5s",typeBuffer);
  

Затем вручную сравните содержимое буфера типов:

 status stat;
if (strcmp(typeBuffer, "MEM") == 0){
     stat = MEM;
}
  

Преобразование между строковым типом и перечислением не может быть неявным.

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

1. typeBuffer Один слишком мал для чтения ‘PREP’ или ‘TRAV’ — вам нужно как минимум 5 там, и, вероятно, больше, чтобы допускать ошибки. Было бы неплохо использовать "%5s" и измерение 6; это позволяет вам отказаться от «ПЕРЕМЕЩЕНИЯ» без переполнения переменной.