-->

Saving new points in time with ctime overwrites th

2019-10-07 19:51发布

问题:

Preface: I've been learning C this past summer and only recently started learning C++ so I don't know very much of it yet.

I've been trying to write a C/C++ program that recognizes right and left mouse clicks in windows and saves which button was clicked and when into an array of pointers to strings char **clicks. I'm organizing it as a sequence like: button, time, button, time...

Whenever a mouseclick is detected, it takes either "R" or "L" and does this:

void writeClick(char *button) {
    static char **tracker = clicks;
    *tracker = button;
    tracker++;
    time_t seconds = time(NULL);
    *tracker = ctime(&seconds);
    tracker++;
}

My question: The issue you may have noticed is that each array element with the time will be pointing to the same string. The result is that the time will update on each mouse click, but it will only remember the last saved time. I figured I could solve the problem with strcpy, but if I want to save multiple strings then won't I need a new variable for each string? Or a new memory location each time or something? How should I do this?

I tried using strcpy like so:

strcpy(*tracker, ctime(&seconds));

But at the second click my program crashes and I'm not sure why.

Other information that may be useful:

I'm planning on sending the data into VBA because I want to turn it into an Excel spreadsheet.

I've yet to write the part of my code that dynamically increases the array whenever it gets full, but at the moment it's large enough (50 elements) to contain the data for a few clicks without crashing, so I know that's probably not the issue.

The part of my code that detects mouseclicks uses a Windows function and aside from that I don't think my code is affected by which OS I'm using. I don't have any issues with click detection (because I solved them all already).

A friend told me she would just use C++ strings and vectors to do the job, but I don't know them yet. I'll look them up but I'm hoping to find a solution without that if possible.

回答1:

From cppreference.com's page on ctime

Return value

Pointer to a static null-terminated character string holding the textual representation of date and time. The string may be shared between std::asctime and std::ctime, and may be overwritten on each invocation of any of those functions.

So yes, the next call to ctime or asctime can be expected to overwrite the buffer used by the previous call.

strcpy(*tracker, ctime(&seconds));

Most likely fails because no storage has been allocated for *tracker to hold the string in.

You could

*tracker = strdup(ctime(&seconds));

to allocate and copy, but this leaves you with the problem of keeping track of which elements of tracker you have to manually free. This will get incredibly nasty fast. If you wish to do this with C, you will either have to strdup and free everything, add in a book-keeping structure to tell you whether or not you dynamically allocated storage and thus must free, or do an extensive redesign.

Since you have tagged C++, follow your friend's advice and use std::vector and std::string.

Documentation on strdup.

Documentation on std::vector.

Documentation on std::string.