2015-12-02 4 views
1

На данный момент я получил этот простой код C, чтобы преобразовать дни, минуты и секунды только секунды:C - Преобразование подстроки в целое

EDITED (я понял проблему с atoi, как это исправляется право ?):.

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

int getseconds(char * time) 
{ 
    int seconds=0, i=0; 
    char buffer[3]; 
    while (*time != '\0') 
    { 
     switch (*time) 
     { 
      case 'h': buffer[i]='\0';i=0;seconds=seconds+atoi(buffer)*3600;break; 
      case 'm': buffer[i]='\0';i=0;seconds=seconds+atoi(buffer)*60;break; 
      case 's': buffer[i]='\0';i=0;seconds=seconds+atoi(buffer);break; 
      case ' ':break; 
      default: buffer[i]=*time;i++;break; 
     } 
     time++; 
    } 
    return seconds; 
} 

int main() 
{ 

    char *time = "12h 4m 58s"; 
    int seconds = getseconds(time); 
    printf("%d",seconds); 
    return 0; 
} 

Это работает, как я хочу, но нет другого способа сделать это, не создавая больше переменных (например, C#, где я просто нужно преобразовать «инлайн» есть ли C только функции которые преобразуются в переменные, а не в «inline»)?

C# Пример:

 string time = "12h 34m 58s"; 
     int seconds = int.Parse(time.Substring(0, 2)) * 3600 + int.Parse(time.Substring(4, 2)) * 60 + int.Parse(time.Substring(8, 2)); 

Вы можете определить количество линий разницы я думаю :).

+0

Перечитайте вопрос и удален. – andrewdleach

+0

Несвязанное примечание; 'buffer' не содержит строку в этом коде (строка представляет собой последовательность символов, за которой следует' \ 0'); если мусор после того, как он окажется цифрой, то atoi не вернет то, что вы ожидаете. – immibis

+0

Буфер @immibis - это просто «держатель», так как конкретная «строка» имеет только 2 числа, и я не буду выводить его, мне действительно нужно завершить его с помощью \ 0? – Exprove

ответ

3

Вы можете использовать atoi() или strtol(), чтобы сделать эту работу. Вам не нужно сначала извлекать подстроки, потому что эти функции останавливаются на первом символе, который не может быть преобразован. Вам просто нужно принять различное представление о том, где начинается строка. Таким образом, этот код достаточно аналогичен вашему C# Например:

int getseconds(const char * time) { 
    return atoi(time) * 3600 + atoi(time + 4) * 60 + atoi(time + 8); 
} 

Конечно, это сломает на некоторых некорректных входов, но так будет C# (хотя и не все же входов).

+0

Хм, этот пример интересен, это то, что мне нужно. Но только один вопрос в C# вы начинаете и заканчиваете подстроку, как работает atoi? Он просто видит, что следующий символ не является числом и возвращает число? – Exprove

+0

Как я писал в своем ответе 'atoi()' останавливается, когда достигает символа, который он не может преобразовать, т. Е. Тот, который не является базой-10 цифр. 'strtol()' делает то же самое, но имеет некоторые дополнительные функции, например, возможность обрабатывать базы, отличные от 10, и дает вам возможность выяснить, где он не прошел разбор. –

+2

Простые и элегантные, с теми же недостатками, что и версия C#. +1 – chqrlie

2

sscanf() с "%n" для обнаружения конца сканирования близко, но использует больше переменных.

int getseconds2(const char * time) { 
    int h,m,s; 
    int n = 0; 
    sscanf(time, "%d h%d m%d s %n", &h,&m, &s, &n); 
    if (n == 0 || time[n] != '\0') return -1; // failure 
    return h*3600 + m *60 + s; 
} 

"%n" сохраняет количество отсканированных символов. Поскольку используется в конце формата, тестирование, чтобы проверить, отличен ли он от нуля (исходное значение) и что time, закончившийся на нулевом символе, гарантирует целостность сканирования.

@chqrlie предложил неправильное соответствие функциональности C#.

// to match C# 
    if (n == 0) return -1; // failure 
+0

В отличие от примера C#, ваш 'sscanf' будет терпеть неудачу, если в конце' time' есть дополнительные символы. – chqrlie

+0

@chqrlie Удалив '|| time [n]! = '\ 0'', то эта совместимая функциональность может быть выполнена. – chux

+0

Хотя это отличный способ сканирования строки, такой как представленная OP, он попросил подход, который не связан с временными. –

1

Намного проще решение возможно:

int getseconds(const char* time) 
{ 
    int h, m, s = 0 ; 
    char sdelim = 0 ; 
    int check = sscanf(time, "%dh %dm %d%c", &h, &m, &s, &sdelim) ; 
    if(check == 3 && sdelim = 's') 
    { 
     s = ((h * 60) + m) * 60 + s ; 
    } 

    return s ; 
} 
+0

@chqrlie: Компилирует здесь просто отлично - какую ошибку вы видите? Зачем ему возвращать -1? Ни один из решений OP не делает это скорее вопросом дизайна, чем требованием. Зачем удалять переменную проверки? Это вопрос стиля. Я предпочитаю назначать тогда тест, а затем вызывать функцию или помещать сложное выражение в if(), потому что упрощает отладку (в символическом отладчике). – Clifford

+0

@chqrlie: Ах-chux исправил это, поэтому. Исправление позволяет очистить чек. Подпись функции была определена в исходном вопросе, но если вы настаиваете. – Clifford

+0

Он компилируется благодаря коррекции @chux. -1 помогают отличить синтаксический анализ от '00h 00m 00s', но OP, похоже, не заботится. Вы можете дополнительно упростить, удалив переменную 'check', но ясность имеет свои достоинства. – chqrlie

Смежные вопросы