I've been stuck with the dcl program from chapter 5.12 in K&R C. It is basically a program which accepts a C variable/function/table declaration and prints a description of it in English. It works for simple declarations such as int a but fails with more complicated ones. For example, when I enter int (*pf)() I get the output
error: expected name or (dcl)
Syntax error
: int
error: expected name or (dcl)
: function that returns pf
Below is the portion of the code related to the program. The getch() and ungetch() functions are in a separate file.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "getch.h"
#define MAXTOKEN 100
enum { NAME, PARENS, BRACKETS };
void dcl(void);
void dirdcl(void);
int gettoken(void);
int tokentype;
char token[MAXTOKEN];
char name[MAXTOKEN];
char datatype[MAXTOKEN];
char out[1000];
int main(void)
{
while (gettoken() != EOF) {
strcpy(datatype, token);
out[0] = '\0';
dcl();
if (tokentype != '\n')
printf("Syntax error\n");
printf("%s: %s %s\n", name, out, datatype);
}
return 0;
}
void dcl(void)
{
int ns;
for (ns = 0; gettoken() == '*'; )
ns++;
dirdcl();
while (ns-- > 0)
strcat(out, " pointer to");
}
void dirdcl(void)
{
int type;
if (tokentype == '(') {
dcl();
if (tokentype != ')')
printf("error: missing )\n");
} else if (tokentype == NAME)
strcpy(name, token);
else
printf("error: expected name or (dcl)\n");
while ((type=gettoken()) == PARENS || type == BRACKETS) {
if (type == PARENS)
strcat(out, " function that returns");
else {
strcat(out, " array");
strcat(out, token);
strcat(out, " of");
}
}
}
int gettoken(void)
{
int c;
char *p = token;
while ((c = getch()) == ' ' || c == '\t')
;
if (c == '(') {
if ((c = getch()) == ')') {
strcpy(token, "()");
return tokentype = PARENS;
} else {
ungetch(c);
return tokentype = ')';
}
} else if (c == '[') {
for (*p++ = c; (*p++ = getch()) != ']'; )
;
*p = '\0';
return tokentype = BRACKETS;
} else if (isalpha(c)) {
for (*p++ = c; isalnum(c = getch()); )
*p++ = c;
*p = '\0';
ungetch(c);
return tokentype = NAME;
} else
return tokentype = c;
}
Could you please help me pinpoint the mistake?
On p124 Brian and Dennis say "Since the programs are intended to be illustrative, not bullet-proof, there are significant restricts on dcl."
The final sentence in the paragraph has this version of the author's final cop-out:
"These improvements are left as exercises."
This could be a good time to dust off yacc.
Related
static char inpbuf[MAXBUF], tokbuf[2 * MAXBUF],
*ptr = inpbuf, *tok = tokbuf;
The array inpbuf is intended to store the user typed command and
its arguments. The array tokbuf is intended to store each extracted tokens from inpbuf,
such that, each element in the array char *arg[MAXARG + 1]; (in proc_line.c) is properly
assigned using the information in tokbuf in order later on to invoke execvp system call in
runcommand.c
I just want to get rid of tokbuf used in userin.c and make the program work can someone help me
userin.c
#include "smallsh.h"
static char inpbuf[MAXBUF], tokbuf[2 * MAXBUF],
*ptr = inpbuf, *tok = tokbuf;
int inarg(char c);
int userin(char *p)
{
int c, count;
ptr = inpbuf;
tok = tokbuf;
printf("%s", p);
count = 0;
while (1)
{
if ((c = getchar()) == EOF)
return(EOF);
if (count < MAXBUF)
inpbuf[count++] = c;
if (c == '\n' && count < MAXBUF)
{
inpbuf[count] = '\0';
return count;
}
if (c == '\n')
{
printf("smallsh: input line too long\n");
count = 0;
printf("%s ", p);
}
}
}
int gettok(char **outptr)
{
int type;
*outptr = tok;
while (*ptr == ' ' || *ptr == '\t')
ptr++;
*tok++ = *ptr;
switch (*ptr++) {
case '\n':
type = EOL;
break;
case '&':
type = AMPERSAND;
break;
case ';':
type = SEMICOLON;
break;
default:
type = ARG;
while (inarg(*ptr))
*tok++ = *ptr++;
}
*tok++ = '\0';
return type;
}
//****************************************************************************************
static char special[] = { ' ', '\t', '&', ';', '\n', '\0' };
int inarg(char c)
{
char *wrk;
for (wrk = special; *wrk; wrk++)
{
if (c == *wrk)
return (0);
}
return (1);
}
runcommand.c
#include "smallsh.h"
#include <unistd.h>
#include <stdlib.h>
int runcommand(char **cline, int where)
{
pid_t pid;
int status;
switch (pid = fork()) {
case 1:
perror("smallsh");
return (-1);
case 0:
execvp(cline[0], cline);
perror(*cline);
exit(1);
}
//code for parents
if (where == BACKGROUND)
{
printf("[process id %d]\n", pid);
return (0);
}
if (waitpid(pid, &status, 0) == -1)
return (-1);
else
return (status);
}
The main idea of the program is to code text into morse and decode morse into text.
But the program is broke, i don't know why the program doesn't work when i write the space between two words, and i have this problem with the code and decode.
void encode_out(const char *s){
for(;;++s){
char ch = *s;
if(ch == '\0')
break;
if(isalpha(ch)){
ch = toupper(ch);
fputs(table[ALPHA][ch - 'A'], stdout);//`-'A'` depend on the sequence of character code
} else if(isdigit(ch))
fputs(table[NUM][ch - '0'], stdout);
else if(ch == ' ')
fputc('/', stdout);//need rest space skip ?
else
;//invalid character => ignore
fputc(' ', stdout);
}
fputc('\n', stdout);
}
static void decode_out_aux(MTree *tree, const char *s){
if(tree == NULL) return;
if(*s == '\0')
fputc(tree->value, stdout);
else if(*s == '/')
fputc(' ', stdout);
else if(*s == '.')
decode_out_aux(tree->dot, ++s);
else if(*s == '-')
decode_out_aux(tree->bar, ++s);
}
void decode_out(const char *s){
char *p;
while(*s){
p = strchr(s, ' ');
if(p){
if(p-s != 0){
char code[p-s+1];
memcpy(code, s, p-s);
code[p-s]='\0';
decode_out_aux(root, code);
}
s = p + 1;
} else {
decode_out_aux(root, s);
break;
}
}
fputc('\n', stdout);
}
static void insert_aux(MTree **tree, char ch, const char *s){
if(*tree == NULL)
*tree = calloc(1, sizeof(**tree));
if(*s == '\0')
(*tree)->value = ch;
else if(*s == '.')
insert_aux(&(*tree)->dot, ch, ++s);
else if(*s == '-')
insert_aux(&(*tree)->bar, ch, ++s);
}
static inline void insert(char ch, const char *s){
if(*s == '.')
insert_aux(&root->dot, ch, ++s);
else if(*s == '-')
insert_aux(&root->bar, ch, ++s);
}
void make_tree(void){
root = calloc(1, sizeof(*root));
//root->value = '/';//anything
int i;
for(i = 0; i < 26; ++i)
insert('A'+i, table[ALPHA][i]);
for(i = 0; i < 10; ++i)
insert('0'+i, table[NUM][i]);
}
static void drop_tree_aux(MTree *root){
if(root){
drop_tree_aux(root->dot);
drop_tree_aux(root->bar);
free(root);
}
}
void drop_tree(void){
drop_tree_aux(root);
}
There are probably some other issues, but at least you need to fix this:
void encode_out(const char *s)
In this function, s is an input parameter and it looks certain that you are modifying its content, therefore s cannot have const modifier. Change that to:
void encode_out(char *s)
Look for other functions in your program that have similar problems, such as decode_out
char *text;
char *morse;
...
scanf("%s", &text);
encode_out(&text);
printf("Enter the morse code: ");
scanf("%s", &morse);
decode_out(&morse);
text and morse are pointers, do not add reference operator.
text is uninitialized pointer, it cannot be used in scanf. The usage is as follows:
char text[100];
scanf("%s", text);
For the rest of the code, it is unlikely to work and over complicated. Use a translate function to compare each morse code.
char translate(const char* buf)
{
for (int i = 0; i < 26; i++)
if (strcmp(buf, alpha[i]) == 0)
return 'A' + (char)i;
if (strcmp(buf, "/") == 0)
return ' ';
for (int i = 0; i < 10; i++)
if (strcmp(buf, num[i]) == 0)
return '0' + (char)i;
//to indicate an error:
return '?';
}
Use strtok to break the morse code in to parts, translate each part and add to output:
char *decode(const char* src)
{
char *code = malloc(strlen(src) + 1);
char *dst = malloc(strlen(src) + 1);
strcpy(code, src);
int dst_len = 0;
char *token = strtok(code, " ");
while (token)
{
dst[dst_len++] = translate(token);
token = strtok(NULL, " ");
}
free(code);
dst[dst_len] = 0;
return dst;
}
int main(void)
{
char *dst = decode(".... . .-.. .-.. --- / .-- --- .-. .-.. -..");
printf("%s\n", dst);
free(dst);
return 0;
}
output: "HELLO WORLD"
I'm trying to write a VERY basic shell program in C. The problem I am facing is trying to fill my argv array of character pointers with the words taken from input. When I attempt to print out the contents of the argv array after attempting to fill it using the parse() function below I get a segmentation fault. I know this means that I am probably trying to access part of the argv array that is out of bounds. However, even when supplying only one argument to fill the array, I still get the segfault. The printf call used to print argc returns the correct value for argc based on input, but the second printf call with *argv[0] is the one causing the segfault. I am wondering if my error is in the way I am attempting to print the contents of argv, or if the error is because I am attempting to fill argv incorrectly.
EDIT: I should add that the getword() function takes in a line of text and returns the first word delimited by spaces, and a number of other delimiters. I can post all the delimiters it breaks the words up by if necessary, but I do not think the problem is because of getword().
EDIT 2: Added in the header file and included the #include statement in main.
EDIT 3: Added the getword function under main(), and getword.h below p2.h
Here is p2.h, the header file included in main:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "getword.h"
#include <signal.h>
#define MAXITEM 100
getword.h:
#include <stdio.h>
#include <string.h>
#include <strings.h>
#define STORAGE 255
int getword(char *w);
int parse(char *, char *[]);
Here is the main function :
#include "p2.h"
int main() {
pid_t pid, child_pid;
int argc, inputRedirect;
char *devNull;
devNull = (char *) malloc(10);
strcpy(devNull, "/dev/null");
char *argv[MAXITEM];
char commandLine[STORAGE];
for (;;) {
printf("p2: ");
scanf("%s", commandLine);
argc = parse(commandLine, argv);
printf("argc = %d\n", argc);
if(argc == 0)
continue;
printf("*argv = %s\n", *argv[0]);
child_pid = fork();
if (child_pid < 0) {
printf("Cannot fork! Terminating...");
exit(1);
} else if (child_pid == 0) {
inputRedirect = open(devNull, O_RDONLY);
dup2(inputRedirect, STDIN_FILENO);
close(inputRedirect);
execvp(*argv, argv);
}
else {
for(;;) {
pid = wait(NULL);
if(pid == child_pid)
break;
}
printf("Child's pid is %d\n", child_pid);
}
}
killpg(getpid(), SIGTERM);
printf("p2 Terminated.\n");
exit(0);
}
int parse(char *commandLine, char *argv[]) {
int i, argc = 0;
char *commandPointer = commandLine;
while (*commandPointer != '\0') {
*argv = commandPointer;
argc++;
getword(commandPointer);
}
*commandPointer = '\0';
*argv = '\0';
return argc;
}
getword.c:
#include "getword.h"
#include <stdlib.h>
/*Function Prototypes*/
int tilde(char *p, int i);
int BSFollowedByMetaCharacter(int c, char *w);
int getword(char *w) {
int c;
int index = 0;
/*This while loop removes all leading blanks and whitespace characters
* The if statement then tests if the first character is a new line or
* semicolon metacharacter*/
while ((c = getchar()) == ' ' || c == '\t' || c == '\n' || c == ';') {
if (c == '\n' || c == ';') {
w[index] = '\0';
return 0;
}
}
/*This if statement calls ungetc() to push whatever character was taken
* from the input stream in the previous while loop back to the input
* stream. If EOF was taken from the input stream, ungetc() will return EOF,
* which will then cause getword() to return -1, signalling that it reached
* the End Of File. */
if (ungetc(c, stdin) == EOF)
return -1;
/*This if statement deals with some of the "non-special" metacharacters.
* If one of these metacharacters is pulled from the input stream by getchar(),
* it is stored in w and null-terminated. getword() then returns the length of
* the current string stored in w. If getchar() pulls anything besides one of the
* specified metacharacters from the input stream, it is then returned using ungetc() after
* the if statement.*/
if ((c = getchar()) == '<' || c == '>' || c == '|' || c == '&') {
w[index++] = c;
int d = getchar();
if (c == '>' && d == '>')
w[index++] = d;
else {
ungetc(d, stdin);
}
w[index] = '\0';
return index;
}
ungetc(c, stdin);
/*This while statement handles plain text from the input stream, as well as a few 'special'
* metacharacters. It also ensures that the word scanned is shorter than STORAGE-1 bytes.*/
while ((c = getchar()) != ' ' && c != '<' && c != '>' && c != '|'
&& c != ';' && c != '&' && c != '\t' && c != '\n' && c != '\0'
&& index <= STORAGE - 1) {
if (c == '~') {
int *ip = &index;
index = tilde(&w[index], *ip);
continue;
}/*END IF*/
else if (c == '\\') {
int d = c;
c = getchar();
if (BSFollowedByMetaCharacter(c, w)) {
w[index++] = c;
continue;
} else {
w[index++] = d;
}
}/*END ELSE IF*/
w[index] = c;
index++;
}/*END WHILE*/
ungetc(c, stdin);/*This final ungetc() call is used to push any meta characters*/
w[index] = '\0'; /*used as delimiters back to the input stream, to be retrieved*/
return index; /*at the next call of getword(). */
}/*END getword()*/
int tilde(char *cp, int i) {
int *ip;
ip = &i;
char *p = cp;
char *o;
o = (strcpy(p, getenv("HOME")));
int offset = strlen(o);
*ip = *ip + offset;
return i;
}
int BSFollowedByMetaCharacter(int c, char *w) {
if (c == '~' || c == '<' || c == '>' || c == '|' || c == ';' || c == '&'
|| c == ' ' || c == '\t' || c == '\\') {
return 1;
} else {
return 0;
}
}
The functions in getword.c seems correct. Your problem is in function parse.
To use execvp, contents of argv should be following (input:"hello world"):
argv[0] -> "hello"
argv[1] -> "world"
argv[2] -> NULL
Here, argv is an array of character pointers. But, in parse function, you are treating argv like simple character pointers in here:
*argv = commandPointer;
and here:
*argv = '\0';
Change your parse function into something like this:
int parse(char *commandLine, char *argv[]) {
int argc = 0;
char *commandPointer;
argv[argc++] = commandLine;
do{
commandPointer = (char*)malloc(sizeof(char) * STORAGE);
argv[argc++] = commandPointer;
getword(commandPointer);
}while(*commandPointer != '\0');
argv[argc] = NULL;
return argc;
}
Now, you should free allocated memory after if-else tree like:
for(int i = 0; i < argc; i++) free(argv[i]);
When valgrind runs this program (implementing a simple type of data compression), it reports "Conditional jump depends on uninitialized value." It also occasionally segfaults. Problem is, I can't seem to pinpoint which variable is not initialized. My CS professor mentioned that "your code doesn't make sure that the strings are properly null-terminated" but I can't see where.
https://gist.github.com/anonymous/9f6c87fb33985606a297
(edit - added the actual code here:)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define WORDLIM 128
#define REPEAT for(;;)
struct word {
char *cont;
char *wsp;
int ctr;
};
char peekchar(void)
{
char c;
c = getchar();
if(c != EOF)
ungetc(c, stdin);
/* puts it back */
return c;
}
struct word *getword()
{
char cont[WORDLIM];
char wsp[WORDLIM];
cont[0] = '\0';
wsp[0] = '\0';
if (peekchar() == EOF)
{
return NULL;
}
REPEAT{
char c = getchar();
char buf[2];
buf[0]=c;
buf[1]='\0';
if (c == '\n' || c == ' ' || c == EOF)
{
if (c != EOF)
strcat(wsp, buf);
if (peekchar() != '\n' && peekchar() != ' ')
{
struct word *toret;
toret = malloc(sizeof(struct word));
toret->cont = malloc(strlen(cont) + 1);
strcpy(toret->cont, cont);
toret->wsp = malloc(strlen(wsp) + 1);
strcpy(toret->wsp, wsp);
toret->ctr = -1;
return toret;
}
continue;
}
else {
strcat(cont, buf);
continue;
}
}
printf("PANIC PANIC PANIC THIS IS GOING WROOOOONG!!!!!\n");
}
void numbrify(struct word **wordlist)
{
int oc = 0;
int roc = oc;
struct word *w;
while ((w = wordlist[oc]) != NULL){
int ic;
if (w->ctr == -1){
for (ic = oc + 1; wordlist[ic] != NULL; ic++){
if (!strcmp(wordlist[ic]->cont, w->cont)){
//printf("**found match between %s and %s**\n", wordlist[ic]->cont, w->cont);
wordlist[ic]->ctr = roc;
}
}
if (w->cont[0]!='\0')
roc++;
}
oc++;
}
}
int main(void){
struct word *wlist[4096];
int i = 0;
struct word *w;
for (i = 0; (w = getword()) != NULL; i++){
wlist[i]=w;
}
wlist[i+1] = NULL;
numbrify(wlist);
i = 0;
for (i = 0; wlist[i]!=NULL; i++){
if (wlist[i]->ctr == -1)
printf("%s%s", wlist[i]->cont, wlist[i]->wsp);
else
printf("%d%s", wlist[i]->ctr, wlist[i]->wsp);
//printf("'%s'\t'%s'\t%d\n", wlist[i]->cont, wlist[i]->wsp, wlist[i]->ctr);
}
return 0;
}
At line 85 of your program:
wlist[i+1] = NULL;
i already points to an unused entry in the array, so assigning NULL to wlist[i+1] leaves an undefined value before the end.
I determined this by running the Clang static analyzer*, which identified this issue in the first two diagnostics (as well as an unrelated, harmless error as the third one):
14968829.c:62:12: warning: Assigned value is garbage or undefined
while ((w = wordlist[oc]) != NULL){
^ ~~~~~~~~~~~~
14968829.c:65:35: warning: The left operand of '!=' is a garbage value
for (ic = oc + 1; wordlist[ic] != NULL; ic++){
~~~~~~~~~~~~ ^
14968829.c:87:2: warning: Value stored to 'i' is never read
i = 0;
^ ~
Correcting the issue (by changing wlist[i+1] to wlist[i]) caused the two Clang diagnostics to disappear, as well as the Valgrind errors.
*: Command line: clang --analyze -Wall 14968829.c -o 14968829
Just a quick one: in C I have a buffer full of data like below:
char buffer[255]="CODE=12345-MODE-12453-CODE1-12355"
My question is how to search through this. For example for the CODE=12345, section bear in mind that the numbers change, so I would like to search like this CODE=***** using wildcard or preset amount of spaces after the CODE= part.
This method wont compile last one left to try
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
char buf[255]="CODE=12345-MODE-12453-CODE1-12355";
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input)
{
char *p = (char*) input, *buf, *pbuf;
if((buf = malloc(256)) == NULL)
return NULL;
pbuf = buf;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim white-space after 'code'
if(*p != '=')
return NULL;
STRIP(p); // remove '='
TRIMSPACES(p); //trim white-spaces after '='
/* copy the value until found a '-'
note: you must be control the size of it,
for avoid overflow. we allocated size, that's 256
or do subsequent calls to realloc()
*/
while(*p != '\0' && *p != '-')
*pbuf ++ = *p++;
// break;
}
p ++;
}
//put 0-terminator.
*pbuf ++ = '\0';
return buf;
}
//
}
You could use the sscanf() function:
int number;
sscanf(buffer, "CODE = %i", &number);
for that to work well your buffer has to be null terminated.
Another way to do it instead of sscanf():
char *input, *code;
input = strstr(buf, "CODE");
if(input == NULL) {
printf("Not found CODE=\n");
return -1;
}
code = strtok(strdup(input), "=");
if(code != NULL) {
code = strtok(NULL, "-");
printf("%s\n", code); // code = atoi(code);
} else {
//not found '='
}
Or more robust way.. a bit more complex:
#define TRIMSPACES(p) while(*p != '\0' && isspace((unsigned char)*p) != 0) ++p
#define NSTRIP(p, n) p += n
#define STRIP(p) ++p
char* getcode(const char *input, size_t limit)
{
char *p = (char*) input, *buf, *pbuf;
size_t i = 0;
while(*p != '\0') {
if(strncmp(p, "CODE", 3) == 0) {
NSTRIP(p, 4); //remove 'code'
TRIMSPACES(p);//trim all white-spaces after 'code'
/* check we have a '=' after CODE (without spaces).
if there is not, returns NULL
*/
if(*p != '=')
return NULL;
/* ok. We have.. now we don't need of it
just remove it from we output string.
*/
STRIP(p);
/* remove again all white-spaces after '=' */
TRIMSPACES(p);
/* the rest of string is not valid,
because are white-spaces values.
*/
if(*p == '\0')
return NULL;
/* allocate space for store the value
between code= and -.
this limit is set into second parameter.
*/
if((buf = malloc(limit)) == NULL)
return NULL;
/* copy the value until found a '-'
note: you must be control the size of it,
for don't overflow. we allocated 256 bytes.
if the string is greater it, do implementation with
subjecents call to realloc()
*/
pbuf = buf;
while(*p != '\0' && *p != '-' && i < limit) {
*pbuf ++ = *p++;
i ++;
}
*pbuf ++ = '\0';
return buf;
}
p ++;
}
return NULL;
}
And then:
char buf[255] = "foo baa CODE = 12345-MODE-12453-CODE-12355";
char *code = getcode(buf,256);
if(code != NULL) {
printf("code = %s\n", code);
free(code);
} else {
printf("Not found code.\n");
}
output:
code = 12345
Check out this online.
if you want to don't differentiate case, you can use the strncasecmp() that's POSIX function.
Assuming the CODE= part always comes at the beginning of the string, it's pretty easy:
sscanf(buffer, "CODE = %d", &number);
...but you want buffer to be char[255], not unsigned long.
Edit: If the CODE= part isn't necessarily at the beginning of the string, you can use strstr to find CODE in the buffer, do your sscanf starting from that point, then look immediately following that:
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
Edit2:
For example, you'd use this something like this:
#include <stdio.h>
#include <string.h>
#include <windows.h>
int main ()
{
// This is full of other junk as well
char buffer[255]="CODE=12345 MODE-12453 CODE=12355" ;
int i;
int codes[256];
char *pos = buffer;
size_t current = 0;
while ((pos=strstr(pos, "CODE")) != NULL) {
if (sscanf(pos, "CODE = %d", codes+current))
++current;
pos += 4;
}
for (i=0; i<current; i++)
printf("%d\n", codes[i]);
return 0;
}
For me, this produces the following output:
12345
12355
...correctly reading the two "CODE=xxx" sections, but skipings over the "MODE=yyy" section.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *getcode(const char *str, const char *pattern){
//pattern: char is match, space is skip, * is collect
static const char *p=NULL;
char *retbuf, *pat;
int i, match, skip, patlen;
if(str != NULL) p=str;
if(p==NULL || *p=='\0') return NULL;
if(NULL==(retbuf=(char*)malloc((strlen(p)+1)*sizeof(char))))
return NULL;
pat = (char*)pattern;
patlen = strlen(pat);
i = match = skip = 0;
while(*p){
if(isspace(*p)){
++p;
++skip;
continue;
}
if(*pat){
if(*p == *pat){
++match;
++p;
++pat;
} else if(*pat == '*'){
++match;
retbuf[i++]=*p++;
++pat;
} else {
if(match){//reset
pat=(char*)pattern;
p -= match + skip -1;
i = match = skip = 0;
} else //next
++p;
}
} else {
break;
}
}
if(i){//has match
retbuf[i++]='\0';
retbuf=realloc(retbuf, i);
return retbuf;
} else {
free(retbuf);
return NULL;
}
}
int main (){
char *code;
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(" CODE = 12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode("CODE-12345-MODE-12453-CODE1-12355", "CODE=*****");
if(code==NULL)printf("not match\n");//not match
code=getcode("CODE=12345-MODE-12453-CODE=12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE=*****");
printf("\"%s\"\n",code);//"12355"
free(code);
code=getcode("CODE=12345-MODE-12453-CODE1-12355", "CODE=*****");
printf("\"%s\"\n",code);//"12345"
free(code);
code=getcode(NULL, "CODE1-*****");
printf("\"%s\"\n",code);//"12355"
free(code);
return 0;
}