corner case of parsing a time military time string - c

usually, most military times are like this
12:34:56
I already figured an method to extract the Hours,mins and secs into their own strings.
However, there is a corner case that i can't seem to figure out
example:
12::
after extracting the number and converting to integers, result is 0. That is good.
However, i need two 0's to properly represent the time
char *hh = argv[2];
char *mm, *ss;
char *array[3];
char *temp =strchr(argv[2],':');
mm = temp + 1;
/*if(*mm == ':'){
*mm = "00";
}*/
*temp = '\0';
temp = strchr(mm, ':');
ss = temp+1;
*temp = '\0';
if you look at the commented if part, that is my attempt to check if the next pointed value is a semicolon. If it is, all i need to do is it with two 0's.
Any clue how to deal with this?

It would be much better to extract this data as integers, not strings.
Something like:
bool parse_hms(int *hours, int *minutes, int *seconds, const char *hms)
{
*hours = *minutes = *seconds = 0;
return sscanf(hms, "%d:%d:%d", hours, minutes, seconds) > 0;
}
should work. Note that the function assumes that all three pointers are valid. It returns true if at least one of the numbers was parsed out. Non-parsed numbers will be set to 0 (which of course is also valid as an element value).

Related

Access and store value by index in a pointer

I've got an assignment where I have to sum whole numbers up to 100 digits.
They gave me this struct to represent big numbers (I think there are better ways to represent this, but I'm not allowed to modify it):
typedef struct {
char* string;
int lengthError;
} BigNumber;
Where string is the number itself and lengthError is the length of the number or an error that is a previously defined enum.
I've also have the implementation of the sum function
BigNumber *sum(BigNumber* num1, BigNumber* num2) {
BigNumber* result = malloc(sizeof(BigNumber));
int limit = getLength(num1->lengthError, num2->lengthError);
result->string = malloc(limit);
int digitResult;
int index = limit -1;
int carry = 0;
while(index != -1) {
int d1 = ((int)num1->string[index]) - ((int)'0');
int d2 = ((int)num2->string[index]) - ((int)'0');
digitResult = d1 + d2 + carry;
if (digitResult > 9) {
digitResult = digitResult - 10;
carry = 1;
} else {
carry = 0;
}
itoa(digitResult, &result->string[index], 10); //I think this is the problem
index--;
}
result->string[limit] = '\0';
printf("result: %s\n", result->string);
return result;
}
I haven't finished writing that function, I know there are a lot of flaws in it, but the problem is that I can't get to sum 12 + 12. The result I get is 2.
I thought approaching this problem by picking the lasts character of both numbers, transform them into an int and sum them having in mind the carry digit. After I got the result in digitResult I try to convert it to a char and store it in the corresponding position of the result->string pointer
Once it has finished the operation, I add an \0 at the last position of the result->string.
So the question is, how do I make this operation to work as desired? Debugging the code, I noticed that the first time it stores the first result in result->string, following the example above this would be a number 4, it stores trash in that position instead. In the second addition, I store a number 2 correctly and that's the final result I get in when I print the result.
Your use of the itoa function is a problem (though, as you have also suggested, maybe not the only one).
The itoa function converts its first argument into a null-terminated string - so, as well as writing the character representation of digitResult at the indicated place in the string, it also adds a '\0' character after it. Thus, your string will always be terminated immediately after the last digit you write, and 12 + 12, giving 24 will appear to be just the first character: 2.
What you can do instead is to convert the digit yourself (reversing the operation you used to get the d1 and d2 values), then just directly set the string element to the converted digit.
So, instead of:
itoa(digitResult, &result->string[index], 10);
use:
result->string[index] = (char)(digitResult + '0');

C- Find array length from pointer

So I've got this here:
#include <stdio.h>
char halloString[] = "Ha::ll::o";
char perfumeString[] = "47::11";
char veryLongString[] = "47::11::GHesd::dghsr::bfdr:hfgd46dG";
char *extract (char *input) {somethinghappenshere}
where extract needs to get all characters after the last double ":" of given input:
"o" for halloString
"11" for perfumeString
"bfdr:hfgd46dG" for veryLongString
In short, my issue is finding the length of the string *input points to. As far as I understand it that won't be happening without making something really sketchy.
Am I correct in assuming the length cannot be acquired in a good way?
And if so would it be a horrible idea to do, for example:
char stringToProcessTemp1[50];
char stringToProcessTemp2[50];
char stringToProcess[50];
for (int i = 0; i < 50; i++) {
stringToProcessTemp1[i] = input + i;
}
for (int i = 0; i < 50; i++) {
stringToProcessTemp2[i] = input + i;
}
for (int i = 0; i < 50; i++) {
if (stringToProcessTemp1[i] == stringToProcessTemp2[i]) {
stringToProcessTemp[i] = stringToProcessTemp1[i];
}
}
Later checking where the first empty index is and saving everything before it as the used String as from my very limited experience in C when you go outside of an array you tend to get different outputs every time therefore making the chance both Temp strings match for an extra element directly after the last one of the original string what I'd consider low enough.
It's honestly the only idea I've got right now.
Finding the length of a string is no problem. strlen will do that for you. However, you don't even need that.
You can use the strstr function to find a substring within a string, in this case "::". When you find one, keep looking right after the last one you found until you don't find it anymore, then the last one you found is the one you want. Then you want the substring that starts right after it.
char *extract(char *input)
{
char *last = NULL, *start = input, *curr;
while ((curr == strstr(start, "::")) != NULL) {
last = curr; // keep track of the last "::" found
start = last + 1; // move the starting string to right after the last "::"
// move up 1 instead of 2 in case of ":::"
}
if (last != NULL) {
last +=2; // We found one; move just past the "::"
}
return last;
}
C strings, which are really only an array of characters, are by definition terminated by '\0'. So, for a well formed C string you can always get the length of the string by using strlen().
If, however, your string is not null-terminated, there is no way to determine it's length, and it is not a C string by definition any more, but just an array of characters.

How to add numbers between two string array in c

Sometimes we need to calculate very long number which couldn't hold any numerical data type of C. As we know all common numerical data type has limitation.
I'm beginner and I think... it is possible by string. My question is:
How can I add two strings?
Sample Input:
String 1: 1234
String 2: 1234
Output
Result : 2468
[Note: Numbers can be very very long in Strings. Unlimited]
Do not convert to a number. Instead, add as you (must) have learned in basic eductation: one pair of digits at a time, starting from the lowest (rightmost) and remember to carry the tens forwards (to the left).
The length of the source strings does not matter, but you must be sure the result char array is large enough for the longest input value plus one (optional) digit.
The algorithm is so simple that I will not "type the code" (which is off-topic for Stack Overflow). It boils down to
carryOver = 0
loop:
result0 = inputA0 + inputB0 + carryOver
if result0 > '9'
carryOver = 1
result0 -= 10
else
carryOver = 0
go to loop while there is still input left ...
where the 0 in the variable names indicate the index of the current digits under consideration.
Edit This Answer does not allow carry overs but infinity long add operations. It does not solve the problem of the user. But it is an implementation example and the user asked for one. This is why I will let the answer stay here and not delete it.
You can use atoi (ascii to int)
Do you realy mean C or C++?
This code can't calculate 8+3 = 11 but 5+3 = 8. There is no carry over.
int temp;
const inst size_of_array;
char one[size_of_array];
char two[size_of_array];
char result[size_of_array];
for(int i = 0; i < size_of_array; i++)
{
temp = atoi(one[i]) +atoi(two[i]);
results[i] = numberToCharacter(temp);
}
char numberToCharacter((int temp)
{
if(temp == 1)
{
return('1'):
} ///..
}
Parse the string variables to integer variables. Calculate sum of them, then parse the result to string.
Here is a fiddler.
Here is the code:
#include <stdio.h>
int main(void) {
//Declaring string variables
char string1[10] = "1234";
char string2[10] = "1234";
//Converting them to integer
int int1 = atoi(string1);
int int2 = atoi(string2);
//Summing them
int intResult = int1 + int2;
//Printing the result
printf("%d", intResult);
return 0;
}

Structure variable in an if statement

I need to make an C application for school and im stuck at one bit. I filled my struct with word from a file wich works fine, except for the time it just prints a random integer i guess?
My code:
char buffer[20];
int i;
for(i = 0; i < 10; i++) {
fgets(buffer,20,fp);
apcWordList[i].pcWord = strdup(buffer);
apcWordList[i].cMaxScore = 0;
apcWordList[i].tTime = time(NULL);
}
fclose(fp);
Now what i wanted to do was this(sSecretWord is the word the person guessed and score the points he got for guessing the word):
for(i = 0; i < 10; i++) {
fgets(buffer,20,fp);
if(apcWordList[i].pcWord == sSecretWord && score > apcWordList[i].cMaxScore) {
apcWordList[i].cMaxScore = score;
apcWordList[i].tTime = time(NULL);
}
}
but it crashes and I am really confused how to compare the variables and change them when needed. I hope I have explained it well enough and my English could be read well.
Assuming pcWord is a char *, you cannot compare that pointer using ==, most of the time.
There is no string data type in C, a string is never a single value.
You must use strcmp():
if(strcmp(apcWordList[i].pcWord, sSecretWorD) == 0 &&
score > apcWordList[i].cMaxScore)
The rest of your code makes little sense, I'm afraid. The loop has a typo, and there's no connection between the fgets() and the if. I don't think the fgets() should be in the second part of the code, at all.
The following expression in your if condition
apcWordList[i].pcWord == sSecretWord
compares the memory addresses they evaluate to and not the values stored at those memory locations which is probably what you want. You should use strcmp instead to compare the strings pointed to by above two variables.
strcmp(apcWordList[i].pcWord, sSecretWorD) == 0

Can't figure out hexadecimal conversion with pointers in C

So I am getting pretty frustrated with this and feel the only way to figure out exactly what I am doing wrong is to ask you fine people. I am trying to convert a string of characters (contains number values) to hexadecimal. Here is my code (note, I haven't placed the switch for 10-15 to letters yet; I just wanted to make sure I was getting back integer values when I ran this... no luck):
void toHex(char *inString){
char *charVal = inString;
char decVal[100];
for(int i = 0; decVal[i] != '\0'; i++){
decVal[i] = *charVal;
charVal++;
}
char storeMod[100];
int i = 0;
int testVal = atoi(decVal);
for(i; testVal >= 16; i++){
int a = testVal;
testVal = testVal/16;
storeMod[i] = a;
}
int a = 0;
char hexval[100];
hexVal[0] = '0';
hexVal[1] = 'x';
for(int j = i+2; j>=2; j--){
hexVal[j] = storeMod[a];
a++;
}
printf("%s hex valu\n", hexVal);
return;
}
For example, an input of 300 returns ,#
I have also tried:
char hexVal[100];
sprintf(hexVal,"%x",*inString);
strcpy(instring,hexVal);
which returns a hex value of 3fa844e0 for 300 which is obviously wrong as well. Any help is appreciated, I need to do this for octals too so I have to figure this concept out and see what I am doing wrong.
Instead of:
sprintf(hexVal,"%x",*inString);
Use:
sprintf(hexVal, "%x", atoi(inString));
As has been pointed out, you can replace your whole function with:
printf("%lx\n", strtol(inString, NULL, 10));
But, if this is for school or personal gratification, you seem to know the two main steps.
Convert the string to an integer
Encode the integer back into a string of the right base.
For step one, step through the number left-to-right (which is easy in a string) multiplying a running result by 10, and adding the current digit.
For step two, simply run through the number four bits(one hex digit) at a time, inserting that plus '0'. If you've started from the LSB, remember to reverse the string.

Resources