For example i have a string about time like 134058 (hhmmss). What is the best way to parse and handle this data? I think i can do this with strncmp or some loops but i am not sure if it's the logical or efficant way.
And what kind of data type should i keep these variable with?
CodePudding user response:
There are some functions in stdlib.h
, atoi
and strtol
, which can not be used here.
Therefore, sticking with the answers from the comments is best.
#include <stdio.h>
#include <string.h> // for strlen
#include <ctype.h> // for isdigit
enum {TIME_LENGTH = 6};
int main(void) {
int hours, minutes, seconds;
char *input_string = "134058";
if (strlen(input_string) != TIME_LENGTH) {
return 1; // wrong length
}
for (int i = 0; i < TIME_LENGTH; i ) {
if (input_string[i] < '0' || input_string[i] > '9') {
return 1; // element not a digit
}
}
// just for completeness, seems like an overkill here
for (int i = 0; i < TIME_LENGTH; i ) {
if (!isdigit(input_string[i])) {
return 1; // element not a digit
}
}
// straight way, drop '* 1' if used
hours = (input_string[0] - '0') * 10 (input_string[1] - '0') * 1;
minutes = (input_string[2] - '0') * 10 (input_string[3] - '0') * 1;
seconds = (input_string[4] - '0') * 10 (input_string[5] - '0') * 1;
printf("Time: d:d:d\n", hours, minutes, seconds);
// from chux - Reinstate Monica
sscanf(input_string, "---", &hours, &minutes, &seconds);
printf("Time: d:d:d\n", hours, minutes, seconds);
// from Support Ukraine
hours = 10 * input_string[0] input_string[1] - 11 * '0';
minutes = 10 * input_string[2] input_string[3] - 11 * '0';
seconds = 10 * input_string[4] input_string[5] - 11 * '0';
printf("Time: d:d:d\n", hours, minutes, seconds);
return 0;
}
$ gcc -Wall parse_simple_time_string.c
$ ./a.out
Time: 13:40:58
Time: 13:40:58
Time: 13:40:58
$
CodePudding user response:
Depends what you mean by 'best'. Some examples shown already , they will also suit your needs. I prefer generic reusable methods; though of course the choice is up to you depending on how much you will re-use the code.
The following code allows range checking, and invalid string checking , haven't tested fully but once you've written the function once it can be re-used to suit. Any comments welcome.
#include <stdint.h>
#include <stdbool.h>
/**
* @param str string to parse
* @param len length of string to parse
* @param out value pointer
* @param min minimum allowed value
* @param max maximum allowed value
* @return true if parsed correctly, false if parse error
* @description convert part of a string to decimal number between specified range
* @example
* uint32_t hour;
* // function returns true and sets hour value to 12
* parseDecimalInt("12345",2,&hour,0,23);
*/
bool parseDecimalInt(const char* str, int32_t len, int32_t* out, int32_t min, int32_t max)
{
int32_t base = 1;
// convert string to len
*out = 0;
if (strlen(str) < len) // check string is longer than desired string to parse
return false;
if (len < 1)
return false; // invalid string length
len--;
while (len >= 0)
{
int8_t digit = str[len] - '0';
if (digit < 0 || digit > 9)
return false; // invalid number
*out = *out (base * digit);
base *= 10;
len--;
}
// outside bounds checks
if (*out < min)
return false;
if (*out > max)
return false;
return true;
}
void main()
{
int32_t hours, mins, secs;
const char* str = "123456";
// Parses TWO characters as decimal starting from ZEROTH character in string
if (!parseDecimalInt(&str[0], 2, &hours, 0, 23))
{
// error parsing hours - print something here and return
}
// Parses TWO characters as decimal starting from SECOND character in string
if (!parseDecimalInt(&str[2], 2, &mins, 0, 59))
{
// error parsing mins - print something here and return
}
// Parse TWO characters as decimal starting from FOURTH character in string
if (!parseDecimalInt(&str[4], 2, &secs, 0, 59))
{
// error parsing seconds - print something here and return
}
// if returned on error, hours mins, secs should be valid
// hours will be 12, mins will be 34, secs will be 56
}