This question already has answers here:
How to compare pointer to strings in C
(3 answers)
Closed 8 years ago.
I try to make a clipboard logger. The idea is that every 5 seconds the program checks of the text on the clipboard is changed; but the problem is that at the beginning the clipboard is shown twice, and after that is shows nothing.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <windows.h>
DWORD WINAPI check()
{
char *strData;
char *oldData = "";
for(;;){
OpenClipboard(NULL);
HANDLE hClipboardData = GetClipboardData(CF_TEXT);
char *pchData = (char*)GlobalLock(hClipboardData);
strData = pchData;
GlobalUnlock(hClipboardData);
CloseClipboard();
if(strData == oldData)
{
//do nothing
}
else
{
printf("%s\n", strData); //here its print twice and then nothing what is not the intention
oldData = strData;
}
Sleep(5000);
}
}
int main()
{
printf("Hello\n");
printf("Your clipboard:\n");
HANDLE thread = CreateThread(NULL, 0, check, NULL, 0, NULL);
getchar();
return 0;
}
Can someone help me?
You have several problems...
If you want to keep a string you need to have it static, otherwise the variable is lost at the time you return from that function.
DWORD WINAPI check()
{
char *strData;
static char *oldData = NULL; // here you'd need static and use NULL by default
As mentioned by others, comparing strings is done with strcmp() or alike:
if(strcmp(strData, oldData) == 0)
However, now that oldData can be NULL you must verify that it is allocated:
if(oldData && strcmp(strData, oldData) == 0)
If a new string is given, then you want to free the old one and replace with the new one:
if(oldData) free(oldData);
oldData = strdup(strData);
Now it should work.
Related
This question already has answers here:
Why has this function no effect when called?
(3 answers)
Closed 3 months ago.
#include <stdio.h>
#include <stdbool.h>
#include "header.h"
int main() {
bool check = true;
while (check) {
test(check);
//printf("%d", check);
}
return 0;
}
this is my main.c file
and this is my header.c file
#include <stdbool.h>
void test(bool check)
{
while (true)
{
if(check){
check = false;
break;
}
}
}
i notice this while im doing the another programm , and it goes inifite loop.
why the check value doesnt change to false?
get a false value and end loop
C is pass-by-value, not by-reference.
This means that test() gets a copy of the value of the check variable's value. It has no way to reach back and change the caller's variable, that the argument is named the same as the variable does not matter.
To fix it, you need to pass the address of the value instead, using pointers:
void test(bool *check)
{
while (true)
{
if (*check){
*check = false;
break;
}
}
}
and then of course you need to explicitly pass the address, in main():
int main() {
bool check = true;
while (check) {
test(&check);
//printf("%d", check);
}
return 0;
}
Of course, it would be cleaner to return the new value, instead of passing the pointer.
I am trying to find the file(say marks.txt) in the particular path passed as argument to a function. Is it possible to give the filename and path as arguments to a function which checks if the file exists and prints out the path?
The below function only takes path as argument.
int fileexists(const char *path){
File *ptr = fopen(path, "r");
if (fptr == NULL)
return 0;
fclose(fptr);
return 1;
}
The required function prototype :
int fileexists(const char *path, const char *filename)
There are two parts to this question, and the right answers to them depend on what you're trying to do.
Concatenate a directory name and a file name to form a full path name.
Determine whether a file (referred to by a full path name) exists or not.
Concatenating a directory name and a file name is straightforward. Your friendsstrcpy and strcat will do most of the work. There are a few minor details to be careful of: (a) You'll need a big enough buffer for the full pathname, and you'll need to decide whether to use a fixed-size array (perhaps of size MAX_PATH), or a malloc'ed buffer; (b) you might need to insert an explicit '/' character (and it usually doesn't hurt to stick one in even if the directory string already ends in one); (c) under Windows you might want to use '\\' instead of '/'.
And then determining whether a file named by a full pathname exists is already well answered over at What's the best way to check if a file exists in C?. The big question to ask here is, are you asking whether the file exists in preparation to doing something with the file? If so, you have a serious vulnerability if you check for the file's existence, but then before you do the other thing, something else happens to cause the file to appear or disappear. So rather than checking-and-then-doing, it's usually better to just try doing the other thing, and deal gracefully with any errors.
The function you have checks if the file can be opened, but it will fail for some files that exist but you have no rights to open. I'd use stat instead. To concatenate the path and filename you can use string functions.
The usual Unix C APIs are dismal. It takes lots of effort to do the simplest of things correctly - and even then I'm not sure that I didn't forget some Unix-ism like signal handling or some obscure error cases. I.e. stuff that's rather trivial to get right in modern C++.
I wish someone designed a modern C system API and implemented it for at least Linux, so that our suffering would end...
Usually, string concatenation requires some higher level API to be done while maintaining a modicum of sanity. Thus, the example below uses a strbuilder class to build the string. This makes things vaguely readable and avoids most common mistakes.
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct strbuilder {
unsigned items, item;
size_t length, *lengths;
char *str, *dst;
};
bool strbuilder_pass(struct strbuilder *builder, int *rc);
void strcat_str(struct strbuilder *builder, const char *src);
void strcat_c_ifnone(struct strbuilder *builder, char c);
bool strbuilder_is_freed(const struct strbuilder *builder);
int fileExists(const char *path, const char *filename)
{
const char pathSep = '/';
int rc;
struct strbuilder bld = {0};
while (strbuilder_pass(&bld, &rc))
{
strcat_str(&bld, path);
strcat_c_ifnone(&bld, pathSep);
strcat_str(&bld, filename);
if (!rc)
{
struct stat statbuf;
printf("path = %s\n", bld.str);
rc = stat(bld.str, &statbuf);
}
}
assert(strbuilder_is_freed(&bld));
return rc;
}
int main()
{
int rc = fileExists("/", "dev");
assert(rc == 0);
return 0;
}
The string building is controlled by a strbuilder_pass function, which advances the string builder's state through five passes of operation:
Determine the number of items whose width has to be stored (avoids the need to call strlen twice).
Prepare the length storage vector. Determine the length of the buffer needed.
Prepare the output string buffer. Concatenate the elements into the buffer.
Use the output string buffer.
Free the output string buffer.
This API is not particularly special, but fits this use case. Some other ad-hoc approach would work too, but this is IMHO a bit more elegant.
void strbuilder_free(struct strbuilder *builder)
{
free(builder->lengths);
free(builder->str);
memset(builder, 0, sizeof(*builder));
}
bool strbuilder_pass(struct strbuilder *builder, int *rc)
{
if (!builder->length) {// start of pass 1
builder->length = 1; /*term*/
*rc = EAGAIN;
return true;
}
else if (!builder->lengths) // end of pass 1
{
builder->lengths = malloc(sizeof(*builder->lengths) * builder->items);
if (builder->lengths)
return true;
*rc = ENOMEM;
}
else if (!builder->str) // end of pass 2
{
builder->dst = (builder->str = malloc(builder->length));
builder->item = 0;
builder->length = 0;
if (builder->dst) {
*builder->dst = '\0';
return true;
}
*rc = ENOMEM;
}
else if (builder->dst) // end of pass 3
{
while (*builder->dst) { // include optional content
builder->dst++; // skip
builder->length++;
}
builder->dst = NULL;
*rc = 0;
return true;
}
else if (!builder->dst) // end of pass 4 (if any)
{}
else {
*rc = EINVAL;
}
strbuilder_free(builder);
return false;
}
void strcat_str(struct strbuilder *builder, const char *src)
{
if (!src)
return;
if (!builder->lengths) // pass 1
builder->items ++;
else if (!builder->str) // pass 2
{
size_t len = strlen(src);
builder->lengths[builder->item++] = len;
builder->length += len;
}
else if (builder->dst) // pass 3
{
size_t len = builder->lengths[builder->item++];
if (*builder->dst && (!len || *builder->dst != *src))
{
builder->dst++;
builder->length++;
}
memcpy(builder->dst, src, len);
builder->dst += len;
builder->length += len;
*builder->dst = '\0';
}
}
void strcat_c_ifnone(struct strbuilder *builder, char c)
{
if (!builder->lengths) {} // pass 1
else if (!builder->str) // pass 2
{
if (c) builder->length ++;
}
else if (builder->dst) // pass 3
{
if (!builder->length || builder->dst[-1] != c)
*(builder->dst) = c;
}
}
bool strbuilder_is_freed(const struct strbuilder *builder)
{
return !builder || (!builder->lengths && !builder->str);
}
You probably want something like this (no error checking for brevity):
...
#include <string.h> // for str* functions
#include <unistd.h> // for access
#include <stdlib.h> // for malloc
...
int fileexists(const char *path, const char *filename)
{
char *name= malloc(strlen(path) + strlen(filename) + 1);
strcpy(name, path);
strcat(name, filename);
int retval = access(name, F_OK) == 0;
free(name);
return retval;
}
Call like this:
if (fileexists("/some/path/", "somefilename.txt")) ...
I would like to add the auto completion on the shell I created. I could not put the entire code but I can tell you my shell is working!
So I tried to implement auto-completion by using the readline function but the result is not that great (see the code in commentary I tried): the auto-completion works but the problems are:
1. I need to press twice enter to get the command executed now. 2. I need to type twice the command (like "ls") to get it executed! Can you help me to fix this? thank you :)
#include <readline/readline.h>
#include <readline/history.h>
#include <stdlib.h>
#include <stdio.h>
#include "includes/ft_sh1.h"
int main(int ac, char **av, char **envp)
{
char *line;
t_env *e = NULL;
char *add;
if (!(e = (t_env *)malloc(sizeof(t_env))))
return (0);
e->envp = env_cpy(envp, 0, 0);
init_env(e);
while (1)
{
--> My question is only about this part below <--
ft_printf("shell$> ");
// add = readline( "shell ");
// add_history(add);
// printf("%s", add);
--> My question is only about this part above <--
get_next_line(0, &line);
get_pwd_env(e);
e->cmd = get_cmd(e, line);
if (ft_strcmp(line, "exit") == 0)
exit(0);
else if (ft_strncmp(e->cmd[0], "cd", 2) == 0)
cd_cmd(e);
else
ft_execute(av, line, e);
}
}
When you just uncomment the part of code in question, you still have the call
get_next_line(0, &line);
in your program, so no wonder that you need to type two command lines.
This question already has answers here:
How can I validate an email address using a regular expression?
(79 answers)
Closed 6 years ago.
I'm trying today to build a regex to make it match to email adress.
I've made one but not working in all the cases I want.
I would a Regex to match with all email address finishing with 2 characters after the dot or only the .com.
I hope to be clear enought,
aaaaaa#bbbb.uk --> should work
aaaaaa#bbbb.com --> should work
aaaaaa#bbbb.cc --> should work
aaaaaa#bbbb.ukk --> should not work
aaaaaa#bbbb. --> should not work
this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <regex.h>
int main (void)
{
int match;
int err;
regex_t preg;
regmatch_t pmatch[5];
size_t nmatch = 5;
const char *str_request = "1aaaak#aaaa.ukk";
const char *str_regex = "[a-zA-Z0-9][a-zA-Z0-9_.]+#[a-zA-Z0-9_]+.[a-zA-Z0-9_.]+[a-zA-Z0-9]{2}";
err = regcomp(&preg, str_regex, REG_EXTENDED);
if (err == 0)
{
match = regexec(&preg, str_request, nmatch, pmatch, 0);
nmatch = preg.re_nsub;
regfree(&preg);
if (match == 0)
{
printf ("match\n");
int start = pmatch[0].rm_so;
int end = pmatch[0].rm_eo;
printf("%d - %d\n", start, end);
}
else if (match == REG_NOMATCH)
{
printf("unmatch\n");
}
}
puts ("\nPress any key\n");
getchar ();
return (EXIT_SUCCESS);
}
"[a-zA-Z0-9][a-zA-Z0-9_.]+#[a-zA-Z0-9_]+\\.(com|[a-zA-Z]{2})$"
https://regex101.com/ is a very good tool for that
\. means a litteral dot ;
(|) means an alternative ;
$ means the end of the line, as we do not want some trailing chars after the match.
I have the following code to process the POST data in the microhttp server:
#include <microhttpd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#define PAGE "<html><head><title>libmicrohttpd demo</title>"\
"</head><body>libmicrohttpd demo!!</body></html>"
struct postStatus {
bool status;
char *buff;
};
static int ahc_echo(void * cls,
struct MHD_Connection * connection,
const char * url,
const char * method,
const char * version,
const char * upload_data,
size_t * upload_data_size,
void ** ptr) {
const char * page = cls;
struct MHD_Response * response;
int ret;
struct postStatus *post = NULL;
post = (struct postStatus*)*ptr;
if(post == NULL) {
post = malloc(sizeof(struct postStatus));
post->status = false;
*ptr = post;
}
if(!post->status) {
post->status = true;
return MHD_YES;
} else {
if(*upload_data_size != 0) {
post->buff = malloc(*upload_data_size + 1);
snprintf(post->buff, *upload_data_size,"%s",upload_data);
*upload_data_size = 0;
return MHD_YES;
} else {
printf("Post data: %s\n",post->buff);
free(post->buff);
}
}
if(post != NULL)
free(post);
response = MHD_create_response_from_buffer (strlen(page),
(void*) page,
MHD_RESPMEM_PERSISTENT);
ret = MHD_queue_response(connection,
MHD_HTTP_OK,
response);
MHD_destroy_response(response);
return ret;
}
int main(int argc,
char ** argv) {
struct MHD_Daemon * d;
d = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY,
9000,
NULL,
NULL,
&ahc_echo,
PAGE,
MHD_OPTION_END);
if (d == NULL)
return 1;
sleep(10000);
MHD_stop_daemon(d);
return 0;
}
I try the following CURL command to test the POST data processing:
curl -XPOST -d '{"email":"test#gmail.com","password":"test"}' 'http://192.168.1.17:9000'
But I get the output {"email":"test#gmail.com","password":"test". I don't get the last }. I tried larger length json inputs also. Still the same. Can't get the last curly brace. Can somebody please help out?
Thanks
EDIT: I got it working. I used strncpy(post->buff, upload_data, *upload_data_size) instead of snprintf.
Could someone please explain why didn't snprintf work?
ahc_echo() will be called at least two times for the request. The request data might be split up into multiple calls, and this fragmentation is very random (depends on how that request is buffered, and what each read() call on the socket returns). So your current code will only work with small requests, but are still unsafe.
MHD_create_post_processor() is a helper for parsing this partial buffers.
https://www.gnu.org/software/libmicrohttpd/tutorial.html#Processing-POST-data goes throught this
The reason
snprintf(post->buff, *upload_data_size,"%s",upload_data);
does not work, is that it should have been
snprintf(post->buff, *upload_data_size + 1,"%s",upload_data);
in order to match the memory size used in malloc(), which has room for the \0 termination.
strncpy(post->buff, upload_data, *upload_data_size);
Is actually dangerous, since it should have been
strncpy(post->buff, upload_data, *upload_data_size);
post->buff[*upload_data_size] = 0;
Since you need to make sure the result is zero terminated (it is just lucky that memory contains a zero already now, this is random behaviour when using malloc(), and not calloc()), and increasing the copy size to *upload_data_size + 1 would be wrong, since that would overflow the source by one byte, which also contains random data, or maybe even invalid memory.