This is my code:
#include <string.h>
#include <ctype.h>
#include <stdio.h>
#include <regex.h>
int main(void)
{
char name[]= "Michael Corleone";
char inputName[40];
regex_t regex;
int return_value;
printf("Enter name: ");
fgets(inputName, sizeof(inputName), stdin);
// Remove new line from fgets
inputName[strcspn(inputName, "\n")] = 0;
// Regcomp string input by user as pattern
return_value = regcomp(®ex, inputName, 0);
// Regexec string that will match against user input
return_value = regexec(®ex, name, 0, NULL, 0);
if (return_value == REG_NOMATCH)
{
printf("Pattern not found.\n");
return 1;
}
else
{
printf("%s\n", name);
}
}
I try to match a string using regex. As you can see, my code works pretty well. There's a person store in array named Michael Corleone. Then, when user try to input: Michael or Corleone or Michael Corleone it will matched and print the full name!
But the problem is case-sensitivity. If user try to input those name in lowercase it will failed.
I try to use this inside regcomp: regcomp(®ex, "[a-zA-Z][inputName]", 0); It works when i try to type the name in lowercase. But then i found out, it also works when i type another name like John, Leon, or Angel. So, i think it match everything that is alphabets.
Do you guys have the solution, please? Thank You!
You need to replace the last argument to regcomp function (which is 0 now) with REG_ICASE:
return_value = regcomp(®ex, inputName, REG_ICASE); // 0 replaced with REG_ICASE
See the C demo.
From the regcomp documentation:
REG_ICASE
Do not differentiate case. Subsequent regexec() searches using this pattern buffer will be case insensitive.
Related
I am trying to make a shell program and am working on mkdir, I am reading in the user input and breaking it into segments using sscanf and then trying to use strcmp to check if the first word was "mkdir", the strcmp works if I leave the stdin as is without using sscanf. Can someone tell me why it doesn't work like this, and how to fix it?
Thanks,
//#include "parser.c"
#include <stdio.h>
# include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#ifndef MAX_BUF
#define MAX_BUF 200
#endif
int main(void)
{
while (1) {
printf("Enter a command: ");
char input[20];
char line[4][20];
fgets(input, 20, stdin);
sscanf(input, "%s %s", line[0], line[1]);
if(strcmp(line[0], "mkdir")) {
char path[MAX_BUF];
getcwd(path, MAX_BUF);
strcat(path, "/");
strcat(path, line[1]);
mkdir(path, 0700);
printf(path);
}
//printf("output %s", input);
}
}
Change your expression:
strcmp(line[0], "mkdir")
into:
strcmp(line[0], "mkdir") == 0
A match returns zero(a) which, when treated as a boolean, is false rather than true. In other words, your if is currrenly firing for anything other than mkdir.
There are a few other problems with your code, such as its inability to create directories longer than about thirteen characters (buffer size twenty minus one for the '\0' minus six for the "mkdir "), and the fact line[1] will be some arbitrary value if you were to just type in mkdir on its own. That won't end well :-)
You could get around that last one by checking to ensure the correct number of things were scanned, with something like:
if (sscanf(input, "%s %s", line[0], line[1]) != 2) {
output_some_error();
} else {
your_current_processing_of_line1_and_line2();
}
The general rule is: if a failure can affect your ability to proceed safely, you should probably check for, and act on, that failure.
(a) The call strcmp(a, b) will return a value as per the following table:
Situation:
a < b
a == b
a > b
Returns:
< 0
0
> 0
Boolean equivalent:
true
false
true
I'm trying to develop a C code that checks the validity of "Provisioning code" string using regular expressions.
A "provisioning code" format should respect the following law:
If not an empty string, this argument SHOULD be in the form of a hierarchical descriptor with one or more nodes specified. Each node in the hierarchy is represented as a 4-character sub-string, containing only numerals or upper-case letters. If there is more than one node indicated, each node is separated by a "." (dot). Examples: "TLCO" or "TLCO.GRP2".
I started development using the code in this link http://web.archive.org/web/20160308115653/http://peope.net/old/regex.html
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
int main(int argc, char *argv[]){
regex_t regex;
int reti;
char msgbuf[100];
/* Compile regular expression */
reti = regcomp(®ex, "^a[[:alnum:]]", 0);
if( reti ){ fprintf(stderr, "Could not compile regex\n"); exit(1); }
/* Execute regular expression */
reti = regexec(®ex, "abc", 0, NULL, 0);
if( !reti ){
puts("Match");
}
else if( reti == REG_NOMATCH ){
puts("No match");
}
else{
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
/* Free compiled regular expression if you want to use the regex_t again */
regfree(®ex);
return 0;
}
this code works fine but my problem is what's the best regular expression that should be input of the function regcomp.
I started to try with a regular expression that matches with string that contains exactly 4 characters uppercases or numerals that means example like TLCO or TLC2 trying with the regular expression "[A-Z0-9]{4}" but I get "No match" as output with matches examples like TLC2.
Is there a suggestion about the right regular expression that should be input of regcomp and matches with "provisioning code"?
You may use the following regex that will work alright if you also pass REG_EXTENDED flag to the regcomp method (for the $ and {m,n} modifier to work correctly):
^[A-Z0-9]{4}([.][A-Z0-9]{4})*$
C code:
reti = regcomp(®ex, "^[A-Z0-9]{4}([.][A-Z0-9]{4})*$", REG_EXTENDED);
Details
^ - start of string
[A-Z0-9]{4} - 4 uppercase ASCII letters or digits
([.][A-Z0-9]{4})* - zero or more sequences of:
[.] - a literal . char
[A-Z0-9]{4} - 4 uppercase ASCII letters or digits
$ - end of string.
I have successfully created a quiz program that first askes the user to input their name.
After the quiz is over, the score is first printed to screen and then would be printed into a username.txt file.
Meaning, the actual users name like John.txt or Amy.txt or bob.txt.
Right now, I have predefined
report_file = fopen ("username.txt","w");
This works 100% yet naturally I have failed to properly identify the files each time the quiz is run for different people and recorded into the file.
I've seen suggestions for sprintf, snprintf, ofstream, istream, and the like.
All are new concepts to me and have no clue how to move forward...any help would be greatly appreciated.
If anyone wants or cares to see my program it is quiet nice and I'd be happy to share but do not intend to burden anyone to read my entire program during this ask for help. :)
Your are not using "username.txt" for all users I hope. And what do you do with the name a user enters when he start the quiz?
You might need something like that in your code, see the docs for sprintf
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char** argv)
{
FILE* pf = NULL;
char username[250];
char userfile[255];
printf("username: ");
scanf("%s", username);
sprintf(userfile, "%s.txt", username);
pf = fopen(userfile, "w");
fprintf(pf, "%d", 100);
fclose(pf);
return 0;
}
You might also want to have a look at fopen to see what flags for opening you will need for your requirements
If you have their username, just save it into a char array, and then call open with O_CREAT set. This will create the file if its not created, and since you have their username, it will create a file with their username.
I've seen suggestions for sprintf, snprintf, ofstream, istream, and the like.
So why dont use them?
char buffer [256];
sprintf(buffer, "%s.txt", username);
report_file = fopen (buffer,"w");
username is obviously an zero terminated string which contains the name of the user
EDIT: For further information you can visit http://www.cplusplus.com/reference/cstdio/sprintf/
To create the file name from a user name, you could use snprintf():
#include <stdio.h>
#include <stdlib.h>
/* ... */
const char* filename_format = "%s.txt";
int n = -1;
char* filename = NULL;
if ((n = snprintf(NULL, 0, filename_format, username)) < 0 ||
(filename = malloc(n+1)) == NULL ||
snprintf(filename, n+1, filename_format, username) != n) {
free(filename);
return error;
}
/* use filename here... */
free(filename); /* clean up */
where username is a '\0'-terminated C string e.g., you could get it using readline():
#include <readline/readline.h> /* readline or editline, etc libraries */
/* ... */
char* username = NULL;
if ((username = readline("Enter your name: ")) == NULL) return error;
/* use username here... */
free(username); /* clean up */
To compile and link:
$ gcc -std=c99 your_source.c -o program-name -lreadline
I want to check if my system is zh_TW.UTF-8 or zh_CN.UTF-8.
Use the following code, I can tell that it is UTF-8.
But, how can I tell whether it is zh_TW or zh_CN?
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>
int
main(int argc, char *argv[])
{
//setlocale(LC_CTYPE,"");
setlocale(LC_ALL,"");
printf("%s\n",nl_langinfo(CODESET));
printf("%s\n",nl_langinfo(CRNCYSTR));
exit(EXIT_SUCCESS);
}
Try:
printf("%s\n", setlocale(LC_ALL, ""));
And, read this.
The function setlocale() returns a pointer to a string that contains the locale information. You can take a copy of it (but may not modify it, and subsequent calls to setlocale() may overwrite the previous value). The string can be used for setting the locale again in future.
char *loc_str = setlocale(LC_ALL, "");
if (loc_str == 0)
...failed to set locale...
printf("LC_ALL = %s\n", loc_str);
If you set one category, you get a string back that would allow you to reinstate that category. You could look at LC_COLLATE and see what is set:
char *loc_str = setlocale(LC_COLLATE, "");
if (loc_str == 0)
...failed to set locale...
printf("LC_COLLATE = %s\n", loc_str);
Etc.
It may or may not give you a human-readable value - but at least experiment to see what it in use.
You could also look at the LANG environment variable, or the LC_* environment variables.
On a POSIX-like system, there is a simple way: try the locale command:
system("locale");
or
FILE *handle = popen("locale", "r+");
size_t readn;
char buf[128];
while ((readn = fread(buf, 1, 128, handle)) > 0) {
fwrite(buf, 1, readn, stdout);
}
pclose(handle);
I'm trying to match a string "123,1234" using regex.h. Following pattern does the job:
"^[0-9]\{1,\},[0-9]\{1,\}$"
If I'm giving it as a commandline argument it works fine. But when I use it inside C code it does not work. Probably because identifying backward slashes as escape characters.
Sample Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
int main (int argc, char * argv[]){
regex_t regex;
int reti;
char msgbuf[100];
char * string, * pattern;
string = "123,1234";
pattern = "^[0-9]\{1,\},[0-9]\{1,\}$";
if(regcomp(®ex, pattern, 0))
{
fprintf(stderr, "Could not compile regex\n");
exit(107);
}
if(!(reti = regexec(®ex, string, 0, NULL, 0)))
{
printf("MATCH\n");
}
else if(reti == REG_NOMATCH)
{
printf("NO MATCH\n");
}
else
{
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(107);
}
regfree(®ex);
return 0;
}
How can I solve this?
Your regular expression is an ERE not a BRE, so you need to pass the REG_EXTENDED flag to regcomp. Then, as others have said, remove the backslashes too.
^[0-9]{1,},[0-9]{1,}$
Take out the \ backslashes. They escape the character immediately following.
To override the slash as an escape sequence, in C one uses a slash to escape a slash, so \ becomes \\.
However, since you are not passing the string to the command line, the curly braces { and } are not going to be caught by the shell's parser, so you could just try it without all of the slashes.
"^[0-9]{1,},[0-9]{1,}$"
If the slashes are being treated as escape characters, have you tried doubling up the slashes so that they are treated as escaped slashes?
ie
"^[0-9]\\{1,\\},[0-9]\\{1,\\}$"