How to normalize the path(delete all repeated '/') in C - c

I am coding a program, that deletes all redundant / in the path of the file. In other words ///a/////b should become /a/b.
I can delete all repeated /, but can't fully wrap my head about how to leave only one slash WITHOUT any standard function or indexation operation.
Can someone fix my code, please?
#include <stdio.h>
// ///a/////b
// a/b/a
// aa///b/a
void normalize_path(char *buf) {
int k = 0, counter = 0;
for (int i = 0; buf[i]; i++) {
buf[i] = buf[i + k];
if (buf[i] == '/') {
++counter;
if (counter > 1) {
--i;
++k;
} else {
++k;
}
} else {
counter = 0;
}
}
}
int main() {
char path[100];
scanf("%s", path);
printf("String before the function: %s\n", path);
normalize_path(path);
printf("String after the function is used: %s\n", path);
return 0;
}

You can keep track if the previous character is slash, and add characters to the result if and only if at least either one of previous and current characters is not shash.
#include <stdio.h>
// ///a/////b
// a/b/a
// aa///b/a
void normalize_path(char *buf) {
char *in = buf, *out = buf;
int prev_is_slash = 0;
for (; *in != '\0'; in++) {
if (!prev_is_slash || *in != '/') *(out++) = *in;
prev_is_slash = *in == '/';
}
*out = '\0';
}
int main() {
char path[100];
scanf("%s", path);
printf("String before the function: %s\n", path);
normalize_path(path);
printf("String after the function is used: %s\n", path);
return 0;
}

The logic is broken. In particular, index i should never decrease, as it corresponds to the read character.
Simpler and correct is to use two indices, one for reading i and one for writing k.
#include <stdio.h>
// ///a/////b
// a/b/a
// aa///b/a
void normalize_path(char *buf) {
int k = 0, counter = 0;
if (buf[0] == '\0') return;
for (int i = 0; buf[i]; i++) {
if (buf[i] == '/') {
++counter;
if (counter > 1) {
continue;
}
} else {
counter = 0;
}
buf[k] = buf[i];
k++;
}
buf[k] = '\0';
}
int main() {
char path[100];
scanf("%s", path);
printf("String before the function: %s\n", path);
normalize_path(path);
printf("String after the function is used: %s\n", path);
return 0;
}

No standard functions and no indexing, use pointers:
char* normalize(char *s)
{
char *src = s;
char *dest = s;
while ((*dest = *src)) {
if (*dest == '/') {
// skip repeated slashes
while (*src=='/') {
src++;
}
dest++;
}
else {
src++;
dest++;
}
}
return s;
}

Use regular expressions (Regular expressions in C: examples?), a regex to remove double slashes is in remove duplicate forward slashes from the URL
In How to do regex string replacements in pure C? is a function like PHP str_replace

Related

Make login in database and change suffix if login already exists

I'm supposed to write a function that takes a login as argument and store this login at the end of the file named logins.db. If the login already exists in the database, you will add the suffix 1. If the login exists with that suffix, you will try with 2, the 3... until you find a valid login.
And with this 2nd part, I get confused and my code isn't working. I'm a beginner so if you have any tips or know what code I need to add, that would be awesome. Thanks.
#include <stdio.h>
typedef struct user
{
char name[100];
} user;
// ************ FUNCTION SPLIT ************ //
int ft_is_separator(char c, char *charset)
{
int i;
i = 0;
while (charset[i] != '\0')
{
if (c == charset[i])
return (1);
i++;
}
if (c == '\0')
return (1);
return (0);
}
int ft_wordlen(char *str, char *charset)
{
int i;
i = 0;
while (str[i] && !ft_is_separator(str[i], charset))
i++;
return (i);
}
int ft_wordcount(char *str, char *charset)
{
int i;
int count;
if (!str[0])
return (0);
i = 1;
count = !ft_is_separator(str[0], charset);
while (str[i] != '\0')
{
if (ft_is_separator(str[i - 1], charset)
&& !ft_is_separator(str[i], charset))
count ++;
i++;
}
return (count);
}
char *ft_strndup(char *src, int n)
{
char *dest;
int i;
i = 0;
dest = malloc(sizeof(char) * (n + 1));
if (dest == NULL)
return (NULL);
while (i < n && src[i])
{
dest[i] = src[i];
i++;
}
dest[i] = '\0';
return (dest);
}
char **ft_split(char *str, char *charset)
{
char **table;
int i;
int k;
k = 0;
table = malloc(sizeof(char *) * (ft_wordcount(str, charset) + 1));
if (table == NULL)
return (NULL);
i = 0;
while (str[i])
{
if (!ft_is_separator(str[i], charset))
{
table[k] = ft_strndup(&str[i], ft_wordlen(&str[i], charset));
if (table[k] == NULL)
return (NULL);
i = i + ft_wordlen(&str[i], charset);
k++;
}
else
i++;
}
table[k] = NULL;
return (table);
}
// ************ FUNCTION STRCMP ************ //
int ft_strcmp(char *s1, char *s2)
{
int i;
i = 0;
while (s1[i] || s2[i])
{
if (s1[i] != s2[i])
return (s1[i] - s2[i]);
i++;
}
return (0);
}
// ************ FUNCTION MAIN ************ //
int main(void)
{
FILE *fichier = NULL;
user det;
int recsize;
int i = 0;
fichier = fopen("logins.db" , "r+");
if (fichier != NULL)
{
recsize = sizeof(det);
fseek(fichier , 0 ,SEEK_END);
printf("Enter Login : ");
scanf("%s" , det.name);
fprintf(fichier, "user_generator %s \n", det.name);
char **table = ft_split("logins.db" , "/n");
printf("%s \n", table[0]);
while (table[i])
{
if (ft_strcmp(table[i], det.name) == 0)
{
fprintf(fichier, "user_generator %s + %d \n", det.name, i);
}
i++;
}
fclose(fichier);
}
return (0);
}
In attempting to construct the table within main,
char **table = ft_split("logins.db" , "/n");
you are sending in the database name, and not the contents of the file itself. To fix this, you need to read from the file. It would not be practical to put the entire file into a single char array, because you would need to make a massive buffer to estimate just how big the database is. Instead, use the fgets function to read from the file line by line.
char* nextLine = fgets(buffer, maxLength, fichier);
You will need to change some implementation to account for this change but it will separate the file by lines, giving you the next one each time you call the function. However, before you read you need to set the FILE* location back to the start of the file (your fseek() moved the pointer to the end of the file).
Finally, you are likely to run into a problem when modifying the name of the user, as you are incrementing the suffix for every line defined in the table, and not when a username in the table matches with det.name. Also, if det.name is already in the table, you now have to check for det.name + 1 to make sure it does not exist, and so on. This may take more than one loop as well, because the names may not necessarily be sorted.

Remove a word from a sentence (string)

I am in the stage of preparing myself for exams, and the thing that I m least proud of are my skills with strings. What I need to do is remove a word from a sentence, without using <string.h> library at all.
This is what I've got so far. It keeps showing me that certain variables are not declared, such as start and end.
#include <stdio.h>
/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
int counter = 0;
while (*s++) {
counter++;
s--;
return counter;
}
/* Function to remove a word from a sentence */
char *remove_word(const char *s1, const char *s2) {
int counter2 = 0;
/* We must remember where the string started */
const char *toReturn = s1;
/* Trigger for removing the word */
int found = 1;
/* First we need to find the word we wish to remove [Don't want to
use string.h library for anything associated with the task */
while (*s1 != '\0') {
const char *p = s1;
const char *q = s2;
if (*p == *q)
const char *start = p;
while (*p++ == *q++) {
counter2++;
if (*q != '\0' && counter2 < count(s2))
found = 0;
else {
const char *end = q;
}
}
/* Rewriting the end of a sentence to the beginning of the found word */
if (found) {
while (*start++ = *end++)
;
}
s1++;
}
return toReturn;
}
void insert(char niz[], int size) {
char character = getchar();
if (character == '\n')
character = getchar();
int i = 0;
while (i < size - 1 && character != '\n') {
array[i] = character;
i++;
character = getchar();
}
array[i] = '\0';
}
int main() {
char stringFirst[100];
char stringSecond[20];
printf("Type your text here: [NOT MORE THAN 100 CHARACTERS]\n");
insert(stringFirst, 100);
printf("\nInsert the word you wish to remove from your text.");
insert(stringSecond, 20);
printf("\nAfter removing the word, the text looks like this now: %s", stringFirst);
return 0;
}
your code is badly formed, i strongly suggest compiling with:
gcc -ansi -Wall -pedantic -Werror -D_DEBUG -g (or similar)
start with declaring your variables at the beginning of the function block, they are known only inside the block they are declared in.
your count function is buggy, missing a closing '}' (it doesn't compile)
should be something like
size_t Strlen(const char *s)
{
size_t size = 0;
for (; *s != '\n'; ++s, ++size)
{}
return size;
}
implementing memmove is much more efficient then copy char by char
I reformatted you code for small indentation problems and indeed indentation problems indicate real issues:
There is a missing } in count. It should read:
/* Side function to count the number of letters of the word we wish to remove */
int count(char *s) {
int counter = 0;
while (*s++) {
counter++;
}
return counter;
}
or better:
/* Side function to count the number of letters of the word we wish to remove */
int count(const char *s) {
const char *s0 = s;
while (*s++) {
continue;
}
return s - s0;
}
This function counts the number of bytes in the string, an almost exact clone of strlen except for the return type int instead of size_t. Note also that you do not actually use nor need this function.
Your function insert does not handle EOF gracefully and refuses an empty line. Why not read a line with fgets() and strip the newline manually:
char *input(char buf[], size_t size) {
size_t i;
if (!fgets(buf, size, stdin))
return NULL;
for (i = 0; buf[i]; i++) {
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
return buf;
}
In function remove_word, you should define start and end with a larger scope, typically the outer while loop's body. Furthermore s1 should have type char *, not const char *, as the phrase will be modified in place.
You should only increment p and q if the test succeeds and you should check that p and q are not both at the end of their strings.
last but not least: you do not call remove_word in the main function.
The complete code can be simplified into this:
#include <stdio.h>
/* Function to remove a word from a sentence */
char *remove_word(char *s1, const char *s2) {
if (*s2 != '\0') {
char *dst, *src, *p;
const char *q;
dst = src = s1;
while (*src != '\0') {
for (p = src, q = s2; *q != '\0' && *p == *q; p++, q++)
continue;
if (*q == '\0') {
src = p; /* the word was found, skip it */
} else {
*dst++ = *src++; /* otherwise, copy this character */
}
}
*dst = '\0'; /* put the null terminator if the string was shortened */
}
return s1;
}
char *input(char buf[], size_t size) {
size_t i;
if (!fgets(buf, size, stdin))
return NULL;
for (i = 0; buf[i]; i++) {
if (buf[i] == '\n') {
buf[i] = '\0';
break;
}
}
return buf;
}
int main() {
char stringFirst[102];
char stringSecond[22];
printf("Type your text here, up to 100 characters:\n");
if (!input(stringFirst, sizeof stringFirst))
return 1;
printf("\nInsert the word you wish to remove from your text: ");
if (!input(stringSecond, sizeof stringSecond))
return 1;
printf("\nAfter removing the word, the text looks like this now: %s\n",
remove_word(stringFirst, stringSecond));
return 0;
}
Your start and end pointers are defined within a block which makes their scope limited within that block. So, they are not visible to other parts of your code, and if you attempt to reference them outside their scope, the compiler will complain and throw an error. You should declare them at the beginning of the function block.
That said, consider the following approach to delete a word from a string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int delete_word(char *buf,
const char *word);
int main(void)
{
const char word_to_delete[] = "boy";
fputs("Enter string: ", stdout);
char buf[256];
fgets(buf, sizeof(buf), stdin);
if (delete_word(buf, word_to_delete))
{
printf("Word %s deleted from buf: ", word_to_delete);
puts(buf);
}
else
{
printf("Word %s not found in buf: ", word_to_delete);
puts(buf);
}
system("PAUSE");
return 0;
}
int chDelimit(int ch)
{
return
(ch == '\n' || ch == '\t') ||
(ch >= ' ' && ch <= '/') ||
(ch >= ':' && ch <= '#') ||
(ch >= '[' && ch <= '`') ||
(ch >= '{' && ch <= '~') ||
(ch == '\0');
}
char *find_pattern(char *buf,
const char *pattern)
{
size_t n = 0;
while (*buf)
{
while (buf[n] && pattern[n])
{
if (buf[n] != pattern[n])
{
break;
}
n++;
}
if (!pattern[n])
{
return buf;
}
else if (!*buf)
{
return NULL;
}
n = 0;
buf++;
}
return NULL;
}
char *find_word(char *buf,
const char *word)
{
char *ptr;
size_t wlen;
wlen = strlen(word);
ptr = find_pattern(buf, word);
if (!ptr)
{
return NULL;
}
else if (ptr == buf)
{
if (chDelimit(buf[wlen]))
{
return ptr;
}
}
else
{
if (chDelimit(ptr[-1]) &&
chDelimit(ptr[wlen]))
{
return ptr;
}
}
ptr += wlen;
ptr = find_pattern(ptr, word);
while (ptr)
{
if (chDelimit(ptr[-1]) &&
chDelimit(ptr[wlen]))
{
return ptr;
}
ptr += wlen;
ptr = find_pattern(ptr, word);
}
return NULL;
}
int delete_word(char *buf,
const char *word)
{
size_t n;
size_t wlen;
char *tmp;
char *ptr;
wlen = strlen(word);
ptr = find_word(buf, word);
if (!ptr)
{
return 0;
}
else
{
n = ptr - buf;
tmp = ptr + wlen;
}
ptr = find_word(tmp, word);
while (ptr)
{
while (tmp < ptr)
{
buf[n++] = *tmp++;
}
tmp = ptr + wlen;
ptr = find_word(tmp, word);
}
strcpy(buf + n, tmp);
return 1;
}
If you have to do it manually, just loop over the indicies of your string to find the first one that matches and than you’ll have a second loop that loops for all the others that matches and resets all and jumps to the next index of the first loop if not matched something in order to continue the searching. If I recall accuretaly, all strings in C are accesible just like arrays, you’ll have to figure it out how. Don’t afraid, those principles are easy! C is an easy langugae, thiught very long to write.
In order to remove: store the first part in an array, store the second part in an array, alloc a new space for both of them and concatinate them there.
Thanks, hit the upvote button.
Vitali
EDIT: use \0 to terminate your newly created string.

Get substrings from string in C

I have such string (it's a string that represents a system path actually):
./home/user/dir1/dir2/
And now, I would like to be able to create presented directory tree, so I need to create home, user, dir1, dir2.
I know how to create dirs in C in Linux, but have troubles with chopping off the string. Basically, what I need now is to have an array of strings:
tmp[0] = "./home/";
tmp[1] = "./home/user/";
tmp[2] = "./home/user/dir1/";
tmp[3] = "./home/user/dir1/dir2/";
and if I will hav such array it would be pretty easy to make presented dir tree but how to split the string in that way?
This is a bit naive but it should get you started. It will handle paths that may or may not have a trailing / and also escaped paths, such as ./home/some\/user/dir1/dir2
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char path[] = "./home/user/dir1/dir2";
char *start = path;
char *end = start + strlen(path);
while (start < end) {
char *slash = strchr(start, '/');
if (slash) {
if (slash > path && *(slash - 1) == '\\') {
start = slash + 1;
continue;
}
*slash = 0;
}
if (strcmp(start, ".") != 0) {
/* Use 'path' for mkdir here */
/* mkdir(path, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) or whatever */
printf("going to make %s\n", path);
}
if (!slash) {
break;
}
*slash = '/';
start = slash + 1;
}
return 0;
}
I'd go for Sean's advice as "You should just exec() mkdir -p ... and save yourself the headache."
However if C is necessary, there you go:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define BUF_SIZE 100
int main(){
char s[] = "./home/user/dir1/dir2/";
char** tmp;
int i, j;
int size = 0;
char* token;
/* count the '/' characters */
char c = s[0];
int count = 0;
i = 0;
while (c != '\0'){
if (s[i] == '/')
count++;
i++;
c = s[i];
}
size = i;
/* ready the tmp array */
tmp = (char**)malloc(count);
for (i = 0; i < count; i++){
tmp[i] = (char*)malloc(BUF_SIZE);
for (j = 0; j < BUF_SIZE; ++j)
tmp[i][j] = '\0';
}
/* special treatment for our first tmp[] */
tmp[0][0] = '.';
tmp[0][1] = '/';
i = 0;
/* tokenize the main string */
token = strtok(s, "./");
while (token != NULL){
if (i > 0)
strcat(tmp[i], tmp[i - 1]);
strcat(tmp[i], token);
strcat(tmp[i], "/");
printf("%s\n", tmp[i]);
token = strtok(NULL, "/");
i++;
}
/* clean up */
for (i = 0; i < count; i++)
free(tmp[i]);
getchar();
return 0;
}
The output is:
./home/
./home/user/
./home/user/dir1/
./home/user/dir1/dir2/
I would use strtok to parse the directory names from the string using "/" as the delimiter.
see: http://www.cplusplus.com/reference/cstring/strtok/
Heres how I did it:
#include <stdio.h>
#include <string.h>
// Count the number of times the character appears in the string
size_t countInstances(char* str, char token) {
size_t count = 0;
while(*str) {
if(*str == token) {
count++;
}
str++;
}
return count;
}
int main() {
char path[] = "./home/user/dir1/dir2/"; // strtok might segfault if this is a pointer (rather than an array)
size_t count = countInstances(path, '/');
char** dirs = malloc(sizeof(*dirs) * count);
char* dir;
size_t i = 0;
dir = strtok(path, "/");
while(dir && i < count) {
dirs[i] = dir; // store reference
printf("%s\n",dir);
dir = strtok (NULL, "/");
i++;
}
free(dirs);
return 0;
}
output is:
.
home
user
dir1
dir2

Remove a character from a string

I am trying to create a function that removes a specified character from a string.
I am only halfway done with the code because I got stuck when I am trying to replace the character to delete with nothing. I just realized I can't put "nothing" in an element of an array so my plan just got ruined.
I figure that I have to loop through the whole string, and when I find the character I want to remove I have to remove it by moving all of the elements that are in front of the "bad" character one step back. Is that correct?
#include <stdio.h>
#include <string.h>
void del(char string[], char charToDel)
{
int index = 0;
while(string[index] != '\0')
{
if(string[index] == charToDel){
string[index] = string[index+1];
}
index++;
}
printf("%s", string);
}
int main(void)
{
char string[] = "Hello world";
del(string, 'l');
return 0;
}
I want to make this program without pointers. Just plain simple code.
I added another while loop that moves every character in the loop to the left but it doesn't seem to work since the output is just plain blank.
int index = 0;
while(string[index] != '\0')
{
if(string[index] == charToDel)
{
while(string[index] != '\0')
{
string[index] = string[index+1];
}
}
index++;
}
printf("%s", string);
}
Johathan Leffler's Method?
char newString[100];
int index = 0;
int i = 0;
while(string[index] != '\0')
{
if(string[index] != charToDel)
{
newString[i] = string[index];
index++;
i++;
}
i++;
index++;
}
printf("%s", newString);
}
This gives me a lot of weird characters...
char const *in = string;
char *out = string;
while (*in) {
if (*in != charToDel)
*out++ = *in;
++in;
}
*out = '\0';
or without pointers
size_t in = 0;
size_t out = 0;
while (string[in]) {
if (string[in] != charToDel)
string[out++] = string[in];
++in;
}
string[out] = '\0';
The problem is that, when you are assigning string[index+1] to string[index], the next l from the string took place of previous one and index incremented to its next value by 1and this l is not deleted by your function. You should have to fixed that.
As suggested by Jonathan Leffler and Gabson; you can do it by coping the string to itself as;
void del(char string[], char charToDel)
{
int index = 0, i = 0;
while(string[index] != '\0')
{
if(string[index] != charToDel){
string[i++] = string[index];
}
index++;
}
string[i] = '\0';
printf("%s", string);
}

String Search and format in C

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;
}

Resources