Извлечение цифр и строк из строкового формата unspecifi c - PullRequest
2 голосов
/ 04 марта 2020

Я хочу извлечь все целые числа и соответствующие периоды времени из вывода ниже. После этого я хочу рассчитать итоговое время безотказной работы в днях. Расчет не является проблемой, но как я могу извлечь информацию из выделенной жирным шрифтом части строки?

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

Я думаю, что должно быть более элегантное решение? Я не ищу код, я просто хочу получить некоторые идеи.

Время работы системы 2 недели 5 дней 9 часов 4 минуты

Время работы системы 1 год 25 недель 11 дней 5 часов 4 минуты

Время работы системы: 9 часов 4 минуты

int bla(const char *line) {
   ndx = strtok(line, " ");
   while (ndx != NULL) {
     // extract and store data
     ...
     ndx = strtok(NULL, " ");
   }
   // calculate sum of days
   return days;
}

С наилучшими пожеланиями, Георг

Ответы [ 3 ]

2 голосов
/ 04 марта 2020

Этот код ниже работает:

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

#define MINUTE 1
#define HOUR   (MINUTE * 60)
#define DAY    (HOUR * 24)
#define WEEK   (DAY * 7)
#define MONTH  (DAY * 30)
#define YEAR   (DAY * 365)

int periodtominute(char *periodunit) {
  if (strstr(periodunit, "year") != NULL){
    return YEAR;
  }
  if (strstr(periodunit, "month") != NULL){
    return MONTH;
  }
  if (strstr(periodunit, "week") != NULL){
    return WEEK;
  }
  if (strstr(periodunit, "day") != NULL){
    return DAY;
  }
  if (strstr(periodunit, "hour") != NULL){
    return HOUR;
  }
  return MINUTE; // The priod unit is `minute`
}

int bla(const char *line) {
  char *linecopy = malloc(strlen(line) + 1);
  memcpy(linecopy, line, strlen(line));

  int totalminutes = 0;
  int periodtime;
  char *ndx = strtok(linecopy, " ");

  while (ndx != NULL) {
    periodtime = atoi(ndx);
    totalminutes += periodtime * periodtominute(strtok(NULL, " "));
    ndx = strtok(NULL, " ");
  }
  free(linecopy);
  return totalminutes;
}

int main() {
  char *first = "1 year 25 weeks 11 days 5 hours 4 minutes";
  int mins = bla(first);
  printf("%d\n", mins);

  char *second = "5 hours 4 minutes";
  mins = bla(second);
  printf("%d\n", mins);

}

Вывод:

793744
304

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

ПРИМЕЧАНИЕ: const char* нельзя передать strtok, поскольку strtok принимает char * для возможности изменения char *. Таким образом, метод состоит в том, чтобы скопировать параметр line в выделенную память и освободить его в конце функции.

1 голос
/ 04 марта 2020

Правильный инструмент для этого задания: strtol():

  • использовать переменные char *p; int val, seconds;
  • инициализировать его, чтобы он указывал на строку для анализа, инициализировать seconds до 0.
  • в al oop:
    • анализировать число с помощью `val = strtol (p, 0, & p);
    • пропустить пробелы в p: while (*p == ' ') p++;
    • если в конце строки вернуть число seconds.
    • проверить для различных возможных единиц, включая формы множественного числа, если вы найдете совпадение:
      • умножьте val на количество секунд в блоке и добавьте это к seconds,
      • , пропустите строку единицы
      • , продолжите l oop
    • если нет совпадения: пожаловаться на нераспознанную единицу и вернуть -1.

Вот простая реализация:

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

static struct unit {
    const char name[8];
    int seconds;
} const units[] = {
    { "year", 365 * 24 * 60 * 60 }, { "years", 365 * 24 * 60 * 60 },
    { "month", 30 * 24 * 60 * 60 }, { "months", 30 * 24 * 60 * 60 },
    { "week", 7 * 24 * 60 * 60 }, { "weeks", 7 * 24 * 60 * 60 },
    { "day", 24 * 60 * 60 }, { "days", 24 * 60 * 60 },
    { "hour", 60 * 60 }, { "hours", 60 * 60 },
    { "minute", 60 }, { "minutes", 60 },
    { "second", 1 }, { "seconds", 1 },
};

int parse_time(const char *p) {
    int seconds = 0;
    while (*p) {
        size_t i, n, len;
        int val = strtol(p, (char **)&p, 0);
        p += strspn(p, " \t\r\n");
        if (*p != '\0' && !(*p >= '0' && *p <= '9')) {
            len = strcspn(p, " \t\r\n");
            for (i = 0, n = sizeof(units) / sizeof(units[0]); i < n; i++) {
                if (strlen(units[i].name) == len && !memcmp(p, units[i].name, len))
                    break;
            }
            if (i == n) {
                printf("unknown unit: %.*s\n", (int)len, p);
                return -1;
            }
            p += len;
            val *= units[i].seconds;
        }
        seconds += val;
    }
    return seconds;
}

int main(int argc, char *argv[]) {
    char buf[256];
    if (argc > 1) {
        while (*++argv)
            printf("%s -> %d seconds\n", *argv, parse_time(*argv));
    } else {
        for (;;) {
            printf("> ");
            fflush(stdout);
            if (!fgets(buf, sizeof buf, stdin))
                break;
            printf(" -> %d seconds\n", parse_time(buf));
        }
    }
    return 0;
}
1 голос
/ 04 марта 2020

Используйте следующие функции для 'c'

long int strtol (const char * str, char ** endptr, int base)

char * strstr (const char * haystack , const char * needle)

сделайте сравнение с strstr () против "days" и "week", чтобы увидеть, какая строка имеет что из ptr strok (), затем вытащите значение numberri c с помощью strtol ()

Вы можете кодировать условное выражение в зависимости от того, что возвращается.

long days = 0;
char *ptr;

    //source is ptr from strtok

    if( strstr( source, "days" )){
       //                

        days = strtol(source, &ptr, 10);
       // now you have number of days 
       // ptr contains rest of string without numeric value
       // if days is zero there is no number
    }//... and so on


// example of strtol
char str[30] = "2030300 This is test";
   char *ptr;
   long ret;

   ret = strtol(str, &ptr, 10);
   printf("The number(unsigned long integer) is %ld\n", ret);
   printf("String part is |%s|", ptr);

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...