Extracting time from timestamp - c

I'm trying to extract the time section from an ISO8601 timestamp.
e.g. From the following timstamp"0001-01-01T17:45:33" I want to extract this part "17:45:33".

you have a few options.
lets say you have it in a variable char array called string.
now if you know that it the time will always be at the end of the string it`s very easy you can just do:
#define TIMEWIDTH 8
#include <stdio.h>
#include <string.h>
int main() {
const char string[] = {"0001-01-01T17:45:33\0"};
unsigned int strlength = strlen(string);
char temp[TIMEWIDTH + 1]; // add one for null character
printf("%s\n", string);
strncpy(temp, string + strlength - TIMEWIDTH, TIMEWIDTH + 1); // another + 1 for the null char
printf("%s\n", temp);
}
if it's more complex you have to do some more analyzing to find it. either manually or use different available tools like sscanf() or something else. make sure to specifiec widths for sscanfs().
http://www.tutorialspoint.com/c_standard_library/c_function_sscanf.htm
if the T indicates the start of the time you can look for it with strchr:
#include <stdio.h>
#include <string.h>
int main() {
const char string[] = {"0001-01-01T17:45:33\0"};
char *temp;
temp = strchr(string, 'T') + 1;
printf("%s\n", temp);
}
It really depends on how variable the input is... If it is just a singular example you can use either. Allthough the last one is more efficient.
You indicated that it is an ISO 8601 timestamp. then I would just use the 2nd method.

Related

How do I properly call the function I created to the main?

So I suck with functions and need to debug this. Im pretty sure the function ToPigLating does its job well at converting. However I just need help calling the function ToPigLatin inside of my main function. But when I try doing that I just get a bunch of error codes.
#include <stdlib.h>
#include <string.h>
#define LEN 32
char* ToPigLatin(char* word[LEN]){
char word[LEN];
char translation [LEN];
char temp [LEN];
int i, j;
while ((scanf ("%s", word)) != '\0') {
strcpy (translation, word);
//just pretend I have all the work to convert it in here.
} // while
}
int main(){
printf("Enter 5 words: ");
scanf("%s", word);
ToPigLatin();
}```
Roughly, variables only exist within the function they're declared in. The word in ToPigLatin exists only within ToPigLatin. It is not available in main. This lets us write functions without worrying about all the rest of the code.
You need to declare a different variable in main, it can also be called word, to store the input and then pass that into ToPigLatin.
Let's illustrate with something simpler, a function which doubles its input.
int times_two(int number) {
return number * 2;
}
We need to give times_two a number.
int main() {
// This is different from "number" in times_two.
int number = 42;
// We have to pass its value into time_two.
int doubled = times_two(number);
printf("%d doubled is %d\n", number, doubled);
}
Your case is a bit more complicated because you're working with input and memory allocation and arrays. I'd suggest just focusing on arrays and function calls for now. No scanf. No strcpy.
For example, here's a function to print an array of words.
#include <stdio.h>
// Arrays in C don't store their size, the size must be given.
void printWords(const char *words[], size_t num_words) {
for( int i = 0; i < num_words; i++ ) {
printf("word[%d] is %s.\n", i, words[i]);
}
}
int main(){
// This "words" variable is distinct from the one in printWords.
const char *words[] = {"up", "down", "left", "right"};
// It must be passed into printWords along with its size.
printWords(words, 4);
}
ToPigLatingToPigLating function expects to have a parameter like ToPigLating("MyParameter");
Hello there icecolddash.
First things first, there are some concepts missing. In main section:
scanf("%s", word);
You're probably trying to read a string format and store in word variable.
In this case, you should have it on your declaration scope. After some adjustment, it will look like this:
int main(){
char word[LEN];
As you defined LEN with 32 bytes maximum, your program will not be allowed to read bigger strings.
You're also using standard input and output funcitions as printf, and so you should ever include stdio.h, thats the header which cointains those prototypes already declared, avoiding 'implicit declaration' compiling warnings.
Next issue is how you're declaring your translation function, so we have to think about it:
char* ToPigLatin(char* word[LEN])
In this case, what you wrote:
ToPigLatin is a funcion that returns a char pointer, which means you want your function to probably return a string. If it makes sense to you, no problem at all. Although we got some real problem with the parameter char* word[LEN].
Declaring your variable like this, assume that you're passing an array of strings as a parameter. If I got it right, you want to read all five words in main section and translate each one of them.
In this case I suggest some changes in main function, for example :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LEN 32
#define MAX_WORDS 5
char *globalname = "translated";
char* ToPigLatin(char* word){
char *translation = NULL;
//Translation work here.
if ( !strcmp(word, "icecolddash") ){
return NULL;
}
translation = globalname;
return translation;
}
int main(){
char word[LEN];
char *translatedword;
int i;
printf("Enter 5 words: \n");
for ( i=0; i < MAX_WORDS; i++ ){
fgets(word, sizeof(word), stdin);
strtok(word, "\n"); // Just in case you're using a keyboard as input.
translatedword = ToPigLatin(word);
if ( translatedword != NULL ){
//Do something with your translation
//I'll just print it out as an example
printf("%s\n", translatedword);
continue;
}
// Generic couldn't translate message
printf("Sorry, I know nothing about %s\n", word);
}
return 0;
}
The above code translate every word in a fixed word "translated".
In case of reading the exact input "icecolddash", the program will output a generic error message, simulating some problem on translation process.
I hope this help you out with your studies.
There are a few things that I see.
#include <stdio.h>
#include <stdlib.h>
char* ToPigLatin(char* word){
printf(word);
return word;
}
int main(){
printf("Enter 5 words: ");
// declare the variable read into by scanf
char * word = NULL;
scanf("%s", word);
//Pass the variable into the function
ToPigLatin(word);
// Make sure you return an int from main()
return 0;
}
I left some comments in the code with some specific details.
However, the main thing that I would like to call out is the style of the way you're writing your code. Always try to write small, testable chunks and build your way up slowly. Try to get your code to compile. ALWAYS. If you can't run your code, you can't test it to figure out what you need to do.
As for the char ** comment you left on lewis's post, here is some reading you may find useful in building up your intuition:
https://www.tutorialspoint.com/what-does-dereferencing-a-pointer-mean-in-c-cplusplus
Happy coding!

How to rewrite part of a line in a text file in C

I am currently trying to create a program that allows a file full of names and marks to be modified and deleted. I currently can locate the name and find the target line, but I was wondering if there was a more effective way of allowing the line to be edited rather than just copying the line, making a new structure out of it, and allowing the user to change the particular values. If not I'm happy to go the long way, I was just hoping there is something more efficient
Deleting a bit can be done by skipping the undesired bytes, but there is no way to edit that part without memory allocation or copying. Here is a deletion example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *content = "John\nMichael\nAndrew\n";
char *target = strstr(content, "Michael");
int len_bef_tag = target - content;
int targlen = strchr(target, '\n') - target;
char *ptr = content;
/* deletion */
fwrite(ptr, 1, len_bef_tag, stdout);
ptr = target + targlen + 1;
printf("%s", ptr);
return 0;
}

Is there a function that can append to the front of a string without having to create two different char arrays in C?

Concatenating to the end of a string in C is easy:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char str[15] = "new ";
printf("old str = %s\n", str);
strcat(str, "word");
printf("new str = %s\n", str);
return 0;
}
Output:
old str = new
new str = new word
But when I append to the front of an array I do this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char str[15] = "word";
char newStr[15] = "new ";
printf("str = %s\n", str);
strcat(newStr, str);
printf("new str = %s\n", newStr);
return 0;
}
Output:
str = word
new str = new word
But is there a function that allows me to append to the front of a string in one line? To be more clear, Is there a way to append to the front of a string without having to create two different char arrays? I just feel that my code would look much cleaner if I could just do this:
semi-sudo code of append function
str = "word";
append(str, "new ");
and when printed would give the following output:
str = word
new str = new word
Something like this would make my life a lot easier since I've been working a lot with file inputs lately.
Thanks!
You can make your own:
#include <stdio.h>
#include <string.h>
char *strprepend(char str[], char const *prefix)
{
size_t slen = strlen(str);
size_t plen = strlen(prefix);
memmove(str+plen,str,slen+1);
memcpy(str,prefix,plen);
return str;
}
int main(int argc, char *argv[]){
char str[15] = "word";
printf("str = '%s'\n", str);
printf("new str= '%s'\n", strprepend(str,"new "));
return 0;
}
/*
Output:
str = 'word'
new str= 'new word'
*/
If you don't wish to copy strcat's unsafety, you can add a buffer-size check as well.
Nope, probably you should have a look at the FreeBSD kernel internals to see how they solve the problem with the TCP/IP stack. As they need to efficiently (this means no string copies are done if not necessary) build packets, and they have to add data to the front of it, they allocate some structures (called mbufs that build using small, preallocated and with several capacities) to build full packets. They also begin filling the data not at the beginning, but they reserve some space in front of it, in order to add it later on, when the amount of data to add is known. This is also done in linux, so it is also a good starting point.
By the way, it would be a good thing you explain your concrete problem... so it is possible to asses you in how to better and efficiently you can build your thing. Think that reallocation and copying data is normally bad habit, and it conduces to low performance and inefficient code. The best approach is to consider how you can develop things without having to move large blocks of memory around.

strtok: getting the value before the delimiter and not just the one after

I'm trying to split up a string into different parts in C. In C#, I just used split(), which created an array to access each part of the split string easily. Now in C I'm trying to split up strings like this: "STXS1-21|S2-23ETX". I want to get the numbers 21 and 23 alone. If I were to strtok with the delimiter string of "STX-|ETX", by my knowledge I'd get:
S1-21|S2-23ETX
21|S2-23ETX
S2-23ETX
23ETX
Im trying to get the numbers 21 and 23 alone though, so how would i accomplish that?
In your specific example you can do it like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char str[] = "STXS1-21|S2-23ETX";
char *sptr = str;
while (sptr = strchr(sptr, '-'))
printf("%d\n", atoi(++sptr));
return 0;
}
Program output:
21
23
As you didn't provide your code, I've had to guess that it is
#include <string.h>
#include <stdio.h>
int main()
{
char s[] = "STXS1-21|S2-23ETX";
const char *d = "-|ESTX";
char *p;
for (p = strtok(s, d); p; p = strtok(NULL, d))
puts(p);
return 0;
}
Obviously, when you run it, you get
1
21
2
23
for the four numerals in your input string. If these are predictably always there, just skip over them.
Remember the warnings in the strtok man page:
BUGS
Be cautious when using these functions. If you do use them, note that:
These functions modify their first argument.
These functions cannot be used on constant strings.
The identity of the delimiting byte is lost.
The strtok() function uses a static buffer while parsing, so it's not thread safe. Use strtok_r() if this matters to you.

Handling BSTRs on MacOSX in C

I've written some code in C for converting strings passed from VBA, when the C code is called from VBA from a MacOSX dylib. I got some good hints here, and since I only care about ASCII strings I've written the following functions to convert the BSTR to a simple char*:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "myheader.h"
size_t vbstrlen(BSTR *vbstr)
{
size_t len = 0U;
while(*(vbstr++)) ++len;
len = len*2;
return len;
}
void vbstochr(BSTR *vbstr, char** out)
{
int len2 = vbstrlen(vbstr);
char str[len+1];
int i;
for(i = 0; i < len; i++)
{
str[i] = (char) (((uint16_t*) vbstr)[i]);
}
str[i] = '\0';
asprintf(out, str);
}
int test(BSTR *arg1)
{
char* convarg;
vbstochr(arg1, &convarg);
return 1;
}
The myheader.h looks like this:
typedef uint16_t OLECHAR;
typedef OLECHAR * BSTR;
. I used uint16_t because of the 4 byte (not 2 byte) wchar_t in the MacOSX C compiler. I added a breakpoint after vbstochar is called to look at the content of convarg, and it seems to work when called from Excel.
So this works, but one thing I don't understand is why I have to multiply my len in the vbstrlen function by 2. I'm new to C, so I had to read up on pointers a little bit - and I thought since my BSTR contains 2 byte characters, I should get the right string length without having to multiply by two? It would be great if someone could explain this to me, or post a link to a tutorial?
Also, my functions with string arguments work when called in VBA, but only after the first call. So when I call a function with a BSTR* argument from a dylib for the first time (after I start the application, Excel in this case), the BSTR* pointer just points at some (random?) address, but not the string. When I call the function from VBA a second time, everything works just fine - any ideas why this is the case?!
A BSTR has an embedded length, you do not need to calculate the length manually.
As for the need to multiply the length by 2, that is because a BSTR uses 2-byte characters, but char is only 1 byte. You coded your vbstrlen() function to return the number of bytes in the BSTR, not the number of characters.
Since you are only interested in ASCII strings, you can simplify the code to the following:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "myheader.h"
size_t vbstrlen(BSTR *vbstr)
{
if (vbstr)
return *(((uint32_t*)vbstr)-1);
return 0;
}
void vbstochr(BSTR *vbstr, char** out)
{
size_t len = vbstrlen(vbstr);
char str[len+1] = {0};
for(size_t i = 0; i < len; ++i)
str[i] = (char) vbstr[i];
asprintf(out, str);
}
The chances are that the VB string is a UTF-16 string that uses 2 bytes per character (except for characters beyond the BMP, Basic Multilingual Plane, or U+0000..U+FFFF, which are encoded as surrogate pairs). So, for your 'ASCII' data, you will have alternating ASCII characters and zero bytes. The 'multiply by 2' is because UTF-16 uses two bytes to store each counted character.
This is almost definitive when we see:
typedef uint16_t OLECHAR;
typedef OLECHAR * BSTR;

Resources