Segmentation fault (core dumped)...BMH Algorithm - c

I am trying to implement a Boyer Moore Horsepoole algorithm. This code was written in Turbo C++, Windows. It worked. I have to port this in ubuntu.
typedef struct skip_table
{
char index;
int value;
}skip_table;
void create_table(char*,int);
int discrete_char(char*,int);
int bm(char*, char*);
int lookup(char);
int check_EOF(char*,int);
skip_table *t1;
int tab_len;
FILE *fptr;
int main()
{
time_t first, second;
double time_spent;
long int cnt=0;
char *key_string,*buf,c; // String to be matched and text
int i,key_len,text_len,def_shift_len,flag_match=0;
gets(key_string);
key_len=strlen(key_string);
fptr=fopen("test_file.txt","r");
first = clock();
fseek(fptr,SEEK_SET,0);
create_table(key_string,key_len);
while(flag_match!=1)
{
fseek(fptr,100*cnt,0);
fread(buf,100-key_len-1, 1, fptr);
flag_match = bm(buf, key_string);
cnt++;
printf("\n%d",cnt);
}
second =clock();
time_spent=(double)(second-first)/CLOCKS_PER_SEC;
if(flag_match==1)
printf("\n\nMatch Found in %lf seconds",time_spent);
else
printf("\n\nMatch NOT Found in %lf seconds",time_spent);
fclose(fptr);
return 0;
}
int discrete_char(char* key_string,char* temp,int key_len)
{
int i,j,count=1,flag=0;
for(i=1;i<key_len;i++)
{
for(j=0; j<count; j++)
{
flag=0;
if(temp[j] == key_string[i])
{
flag=1;
break;
}
}
if(flag!=1)
{
temp[count++]=key_string[i];
flag=0;
}
}
temp[count]='\0';
return count;
}
void create_table(char* key_string,int key_len)
{
int i,j,k,max_index;
char *temp;
temp[0] = key_string[0];
tab_len=discrete_char(key_string,temp,key_len);
t1=(skip_table*)malloc((tab_len-1)*sizeof(skip_table));
for(i=0;i<tab_len;i++)
{
for(j=0;j<key_len;j++)
{
if(temp[i]==key_string[j])
max_index=j;
}
t1[i].index=temp[i];
t1[i].value=key_len-max_index-1;
printf("\n\n %c %d",t1[i].index,t1[i].value);
}
}
int bm(char* text, char* key_string)
{
int i_t, i_k, j,k, text_len, key_len, shift, count=0, flag_match=0;
int loop_count;
text_len = strlen(text);
key_len = strlen(key_string);
i_t=key_len;
i_k=key_len;
loop_count=0;
while(i_t<=text_len)
{
if(count != key_len)
{
if(text[i_t-1]==key_string[i_k-1])
{
count++;
i_t--; i_k--;
loop_count++;
}
else
{
if(loop_count>key_len)
{
i_t=i_t+lookup(text[i_t-1])+1;
i_k=key_len;
loop_count=0;
continue;
}
shift = lookup(text[i_t-1]);
if(shift<=0)
shift=key_len;
i_t = i_t+shift;
i_k = key_len;
count=0;
}
}
else
{
flag_match = 1;
break;
}
}
return flag_match;
}
"int lookup(char index)" returns the respective value field of the index if present in "temp" else returns -1.
There's my whole code.

Not that I see exactly what went wrong but here are some defensive programming tips:
int main()
{
// initialize all variables before use
time_t first = 0, second = 0;
double time_spent = 0.0;
long int cnt=0;
char *key_string = NULL;
char *buf = NULL;
char c = '\0';
char temp[50] = {0};
int i = 0,key_len=0,text_len=0,def_shift_len=0,flag_match=0;
// use fgets instead of gets, fgets allows you specify max length
fgets(temp,sizeof(temp),stdin);
key_len=strlen(temp);
key_string = (char*) malloc(key_len+1);
// use strncpy or strcpy_s to specify max size
strncpy(key_string, temp, sizeof(key_string));
fptr = fopen("test_file.txt","r");
first = clock();
// here arguments have wrong order, fseek takes origin as last arg:
fseek(fptr,0,SEEK_SET);
// could be something in create_table, but you have not supplied it
create_table(key_string,key_len);
When you have so many variables in a function you may consider moving out parts of the function to other functions

Try using --track-origins=yes on your valgrind options as well, as the output suggests, this can help track down where uninitialised varables have come from.
As others have suggested, the issue valgrind is reporting is inside create_table, so please post the code for that as well.

Related

Overlapping and too long integer values in dynamic c structs

I have the following problem.
I need to create a list of savestates with dynamical length. That's why I decided to create a list by defining some structs and connecting dynamically created structs together to build a list of structs which can dynamically be extended and so on.
However, some things seem to not work at all. Here's the relevant code first:
saves.h:
#ifndef SAVES_H
#include<time.h>
#define SAVES_H
#define SVS_STRLEN 500
#define SVS_FILE "savefile.dat"
#define True 1
#define False 0
typedef struct SVS_STATE SVS_STATE;
typedef struct SVS_STATES SVS_STATES;
struct SVS_STATE {
int i_playfield[6][7];
int i_turn;
time_t i_time;
void *next;
};
struct SVS_STATES {
SVS_STATE *states;
int count;
int loaded;
};
void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time);
void SVS_Debug_State(SVS_STATE *state);
void SVS_Format_State(SVS_STATE *state, char text[]);
SVS_STATE *SVS_Get_State(int number);
#endif
saves.c:
#include "saves.h"
#include<string.h>
#include<time.h>
SVS_STATE *SVS_Get_State(int number)
{
int i = 1;
SVS_STATE *state;
if (svs_current_state.loaded == False) return NULL;
if (number > svs_current_state.count) return NULL;
state = svs_current_state.states;
printf("printing state 1:");
SVS_Debug_State(state);
while( i < number)
{
i++;
state = (SVS_STATE*)(state->next);
printf("printing state %i:", i);
SVS_Debug_State(state);
}
return state;
}
void SVS_Format_State(SVS_STATE *state, char text[])
{
int i, j;
if (svs_current_state.loaded == False) return;
text[0] = '\0';
strcat(text, "{\0");
for (i = 0; i < X_SIZE; i++)
{
strcat(text, "{\0");
for(j = 0; j < Y_SIZE; j++)
{
strcat(text, "%i,\0");
sprintf(text, text, state->i_playfield[i][j]);
}
strcat(text, "}\0");
}
strcat(text, "};%i;%i\n\0");
sprintf(text, text, state->i_turn, state->i_time);
printf("\nFormatted state:%s\n", text);
}
void SVS_Debug_State(SVS_STATE *state)
{
char text[SVS_STRLEN];
SVS_Format_State(state, text);
printf("%s\n", text);
}
void SVS_Add_State(int i_playfield[][7], int i_turn, time_t i_time)
{
int i, j;
SVS_STATE *laststate, *newstate;
newstate = (SVS_STATE*)malloc(sizeof(SVS_STATE));
printf("adding state with time:%i\n", i_time);
if (svs_current_state.loaded == False) return;
for (i = 0; i < 6; i++)
for (j = 0; j < 7; j++)
newstate->i_playfield[i][j] = i_playfield[i][j];
newstate->i_turn = i_turn;
newstate->i_time = i_time;
newstate->next = NULL;
printf("initialized state:");
SVS_Debug_State(newstate);
if (svs_current_state.coun > 0)
{
laststate = SVS_Get_State(svs_current_state.count);
laststate->next = (void*)newstate;
} else
svs_current_state.states=newstate;
svs_current_state.count++;
}
int main()
{
int i_playfield[6][7] = {0};
// mark saves library as loaded here, but removed function, since it
// just sets svs_current_state.loaded (which is the global struct of
// type SVS_STATES) to 1
SVS_Add_State(i_playfield, 1, time(NULL));
i_playfield[0][0] = 2;
SVS_Add_State(i_playfield, 2, time(NULL));
return 0;
}
The actual problems I encountered while using the printf's and Debug_State calls in these functions:
- the i_time I give is printed out once in Add_State(), correctly. Means it is a legal time and stuff, but when printed out after creating the full state by using Format_State() the string is 50 percent to long and the last part is displayed twice, for example:
if the time is 12345678, it is displayed correctly while debugging in Add_State, but Format_State() displays 123456785678.
- second problem: the first state added works, more or less, fine. But after adding a second one, printing the first state (retrieved by using Get_State and formatted with Format_State) prints a mixture of two states, for example something like this:
state 1: {{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}{0,0,0,0,0,0,0}...
{0,0,0,0,0,0}};1;123456785678
state 2: {{0,0,0,0,0,0}{0,0,0,0,0,0}...
{0,0,0,0,0,0}};2;1234567856785678,0}{0,0,0,0,0,0}...
Thanks for reading.
These calls
sprintf(text, text, ...
invoke undefined behaviour, as the target buffer and one of the other arguments overlap.
From the POSIX specs to sprintf():
If copying takes place between objects that overlap as a result of a call to sprintf() [...], the results are undefined.

How to manipulate string properly in C

I'm still new in C. I'm doing an enviroment variable task and I'm having a problem in processing my string. I would like to pass a variable that represent the environment variable, and replace a value that has ${...} with environment value if that string are same as the enviroment key. Here are the codes:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
void replace_env(char *string, char *env)
{
int y = 0;
int x = 0;
int j = 0;
int i = 0;
int n = 0;
int val_length;
int location2[100];
char *tmp3[BUFSIZ];
char env_key[BUFSIZ];
char env_val[BUFSIZ];
char env_var[sizeof(env)][BUFSIZ];
char user_input[BUFSIZ];
char final_string[BUFSIZ];
char tmp_key[100][BUFSIZ];
tmp3[x]=env;
strncpy(env_var[x],tmp3[x],sizeof(tmp3));
for(x=0;env_var[y][x] != '=';x++) //this is to get the environment key
{
env_key[x] = env_var[y][x];
}
x++;
for(j=0;env_var[y][j] != '\0';j++) //this is to get the environment value
{
env_val[j]=env_var[y][x];
x++;
}
val_length = strlen(env_val);
j=0;
y=0;
strncpy(user_input,string,sizeof(user_input));
for(x = 0;user_input[x] !='\0';x++)
{
if (user_input[x] =='$')
{
x++;
if(user_input[x] == '{')
{
x++;
y=0;
while(user_input[x]!='}')
{
tmp_key[i][y] = user_input[x];
x++;
y++;
}
i++;
}
}
}
tmp_key[i][y]='\0';
i=0;
for(x = 0;user_input[x] !='\0';x++) //I think my problem is starting from here.
{
if (user_input[x] !='$')
{
final_string[j]=user_input[x];
j++;
}
else
{
x++;
if((user_input[x]== '{')&&(strncmp(tmp_key[i],env_key,sizeof(tmp_key))==0))
{
while(user_input[x]!='}')
{
x++;
}
strcat(final_string,env_val);
j=j+val_length;
}
else
{
final_string[j]=user_input[x];
j++;
}
}
}
printf("output result = %s \n",final_string);
}
int main() {
char s[100];
sprintf(s, "jack${ABC}zack${DEF}");
replace_env(s, "ABC=/home/fikrie/Documents");
replace_env(s, "DEF=/tmp");
if (strcmp(s, "jack/home/fikrie/Documentszack/tmp")==0) {
printf("pass\n");
} else {
printf("fail\n");
}
printf("--------------------------------------------------------\n");
return 0;
}
To make it more clearer, here are the result:
env_var = ABC=/home/fikrie/Documents
env_key = ABC
env_val = /home/fikrie/Documents
input = jack${ABC}zack${DEF}
after strcat result is = jack/home/fikrie/Documents
j value is 26
after strcat result is = jack/home/fikrie/Documentszack/home/fikrie/Documents
j value is 52
output result = jack/home/fikrie/Documentszack/home/fikrie/Documents
env_var = DEF=/tmp
env_key = DEF
env_val = /tmp
input = jack${ABC}zack${DEF}
output result = jack{ABC}zack{DEF}ocumentszack/home/fikrie/Documents
fail
--------------------------------------------------------
As you can see, ABC are sent into the replace_env function. And it does replace the ${ABC} properly, followed with a string zack.Then the problem occures where ${DEF} are replaced with ABC key and not maintained as ${DEF}
When the DEF are sent during the second call of replace_env function, things got more wierd. Both ABC and DEF are not recognized. Even worse, the character at the back are still there.
My expectation is:
For the first call of replace_env:
jack/home/Fikrie/Documentszack${DEF}
For the second call of replace_env:
jack/home/Fikrie/Documentszacl/tmp
after the strcmp passed, the final_string will be cleared again.
All help are really appreciated. I dont expect an answer. I prefer a knowledge or guidance rather than just solving it blankly. Just need a clear explanation on my fault because I have been editing this code for almost a month and everything looks so blurry now. I know there are ways to solve it using memory functions, allocation etc. But this task is about string manipulation. I am running this on Ubuntu OS. Sorry for my bad english.
I know you didn't ask for this, but consider this. Learning the C string functions is worth your time.
#include <stdio.h>
#include <string.h>
void sub(char *s, char *env, char *value) {
char buf[BUFSIZ], *src = s, *dst = buf;
int n = strlen(env);
while(*src) {
if(strncmp(src, env, n) == 0) {
dst += strlen(strcpy(dst, value));
src += strlen(env);
} else {
*dst++ = *src++;
}
}
*dst = 0;
strcpy(s, buf);
}
void replace_env(char *s, char *env) {
char copy[BUFSIZ], tmp[BUFSIZ];
strcpy(copy, env);
char *eq = strchr(copy, '=');
if(eq == 0) {
printf("No '=' found in '%s'\n", env);
return;
}
*eq = 0;
sprintf(tmp, "${%s}", copy);
sub(s, tmp, eq+1);
}
int main() {
char s[100];
sprintf(s, "jack${ABC}zack${DEF}");
replace_env(s, "ABC=/home/fikrie/Documents");
replace_env(s, "DEF=/tmp");
if (strcmp(s, "jack/home/fikrie/Documentszack/tmp")==0) {
printf("pass\n");
} else {
printf("fail\n");
}
printf("--------------------------------------------------------\n");
return 0;
}

why does C code pauses after i give ./a.out?

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
//This program is a sorting application that reads a sequence of numbers
//from a file and prints them on the screen . The reading from the file here,
//is a call back function .
typedef int (*CompFunc)(const char* , const char* );
typedef int (*ReadCheck)(char nullcheck);
char array[100];
//Let this function be done in the library itself . It doesn't care as to
//where the compare function and how is it implemented . Meaning suppose
//the function wants to do sort in ascending order or in descending order
//then the changes have to be done by the client code in the "COMPARE" function
//who will be implementing the lib code .
void ReadFile(FILE *fp,ReadCheck rc)
{
char a;
char d[100];
int count = 0,count1=0;
a=fgetc(fp);
while(1 != (*rc)(a))
{ if(a=='\0')
{
//d[count1]='\0';
strcpy(&array[count],d);
count=count+1;
}
else
{
d[count1]=a;
count1=count1+1;
}
}
}
void Bubblesort(char* array , int size , int elem_size , CompFunc cf)
{ int i,j;
int *temp;
for( i=0;i < size ;i++)
{
for ( j=0;j < size -1 ; j++)
{
// make the callback to the comparision function
if(1 == (*cf)(array+j*elem_size,array+ (j+1)*elem_size))
{
//interchanging of elements
temp = malloc(sizeof(int *) * elem_size);
memcpy(temp , array+j*elem_size,elem_size);
memcpy(array+j*elem_size,array+(j+1)*elem_size,elem_size);
memcpy(array + (j+1)*elem_size , temp , elem_size);
free(temp);
}
}
}
}
//Let these functions be done at the client side
int Compare(const char* el1 , const char* el2)
{
int element1 = *(int*)el1;
int element2 = *(int*)el2;
if(element1 < element2 )
return -1;
if(element1 > element2)
return 1 ;
return 0;
}
int ReadChecked(char nullcheck)
{
if (nullcheck=='\n')
return 1;
else
return 0;
}
int main()
{
FILE *fp1;
int k;
fp1=fopen("readdata.txt","r");
ReadFile(fp1,&ReadChecked);
Bubblesort((char*)array,5,sizeof(array[0]),&Compare);
printf("after sorting \n");
for (k=0;k<5;k++)
printf("%d",array[k]);
return 0;
}
Just perhaps the program is taking a little while to run... just perhaps.
Here's a possible issue: What happens when fgetc returns EOF (-1) ?
while(1 != (*rc)(a))

C Memory Allocation: Why there is not enough memory(250K only)

I am having trouble figuring out the reason why my .c code is having trouble allocating ~250K of memory. Here is the allocation code:
struct IMAGE {
int width, height, maxval;
char **data;
};
void raiseError(char *msg)
{
printf("%s", msg);
getch();
exit(1);
}
//...
IMAGE readPGM()
{
IMAGE image;
image.data = (char **) malloc(sizeof(char)*image.height);
//..
for (i=0; i<image.height; i++) {
image.data[i] = (char *) malloc(sizeof(char)*image.width);
if (image.data[i]=='\0') {
printf("%d\n", i);
raiseError("Not enough memory!..");
}
}
//..
}
//..
The program exits when i=116. image.width and image.height equals to 500 here, so I want 500x500=250000 bytes to be allocated here. But 116x500 = 58000 bytes are being allocated at maximum. So, is there something that limits it? Is there something wrong with my code? I am posting the full source below, just in case if it is necesarry. The idea is to read a PGM file into the structure IMAGE, process it and rewrite it in another file. As you can tell, it is not complete yet because I couldn't figure out a way to allocate more memory.
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<alloc.h>
struct IMAGE {
int width, height, maxval;
char **data;
};
void raiseError(char *msg)
{
printf("%s", msg);
getch();
exit(1);
}
char *toString(int num)
{
char sign = 0;
if (num<0) {
sign = -1;
num*=-1;
}
int numLen = 1;
if (sign<0) {
numLen++;
}
int tmpNum = num;
while (tmpNum>9) {
tmpNum /= 10;
numLen++;
}
char *result = (char *)malloc(sizeof(char)*(numLen+1));
result[numLen] = '\0';
char ch;
while (num>9) {
ch = (num%10)+'0';
num /= 10;
result[numLen-1] = ch;
numLen--;
}
result[numLen-1] = num + '0';
if (sign<0)
result[0] = '-';
return result;
}
int toInteger(char *line)
{
int i=strlen(line)-1;
int factor = 1;
int result = 0;
while (i>=0) {
result += factor*(line[i]-'0');
factor *= 10;
i--;
}
return result;
}
char *getNewParam(FILE *fp)
{
char ch = 'X';
char *newParam;
newParam = (char*) malloc(1);
newParam[0] = '\0';
int paramSize = 0;
while (!isspace(ch)) {
ch = fgetc(fp);
if (!isspace(ch)) {
if (ch=='#') {
while (fgetc(fp)!='\n');
continue;
}
paramSize++;
newParam = (char *) realloc(newParam, paramSize+1);
newParam[paramSize-1] = ch;
}
}
newParam[paramSize] = '\0';
return newParam;
}
IMAGE readPGM()
{
FILE *fp;
IMAGE image;
//Open the file.
fp = fopen("seeds2.pgm","r+b");
if (fp=='\0')
raiseError("File could not be opened!..");
//Check if it is a raw PGM(P5)
char *line;
line = getNewParam(fp);
if (strcmp(line, "P5")!=0)
raiseError("File is not a valid raw PGM(P5)");
int paramCount = 0;
int *pgmParams;
pgmParams = (int *)malloc(sizeof(int)*3);
while (paramCount<3) {
line = getNewParam(fp);
pgmParams[paramCount++] = toInteger(line);
}
int pixelSize;
if (pgmParams[2]>255)
pixelSize = 2;
else
pixelSize = 1;
image.width =pgmParams[0];
image.height =pgmParams[1];
image.maxval =pgmParams[2];
free(pgmParams);
image.data = (char **) malloc(sizeof(char)*image.height);
int i,j;
long sum = 0;
for (i=0; i<image.height; i++) {
image.data[i] = (char *) malloc(sizeof(char)*image.width);
sum += sizeof(char)*image.width;
if (image.data[i]=='\0') {
printf("%d\n", i);
raiseError("Not enough memory!..");
}
}
for (i=0; i<image.height; i++) {
for (j=0; j<image.width; j++) {
fread(&image.data[i][j], sizeof(char), image.width, fp);
}
}
fclose(fp);
return image;
}
void savePGM(IMAGE image)
{
FILE *fp = fopen("yeni.pgm", "w+b");
fprintf(fp, "P5\n%s\n%s\n%s\n",
toString(image.width), toString(image.height), toString(image.maxval));
int i,j;
for (i=0; i<image.height; i++) {
for (j=0; j<image.width; j++) {
fwrite(&image.data[i][j], sizeof(char), 1, fp);
}
}
fclose(fp);
}
int main()
{
clrscr();
IMAGE image = readPGM();
//process
savePGM(image);
getch();
return 0;
}
The answer to your question is in the comment you added to it. You are using an (antique) 16 bit x86 real mode compiler. A 16 bit virtual machine can address only 1Mb of memory in total, only 640Kb of which is normally accessible to programs, and is shared with the OS.
[edit in response to paxdiablo's comment]
Further to those restrictions the segmented addressing architecture also gives rise to a number of memory models where as little as 64kb may be the limit for specific memory areas.
Also the argument to malloc() has type size_t, which may only be 16-bit in this case - you should check. I recall using a variant called halloc() for large allocations. But short of using a DOS extender, there is still a 640kb limit.
[end edit]
There are a number of far better and free modern 32-bit compilers available. Dump the antique. I suggest VC++ Express Edition
Apart from that strictly:
if(image.data[i]=='\0')
should be
if(image.data[i]==0)
or
if(image.data[i]==NULL)
As it happens it will work in either case, but technically you are testing for a null-pointer not a NUL character.
I'm not going to read all that code -- this is a prime example of where you should give a minimal example to reproduce the problem -- but this line:
image.data = (char **) malloc(sizeof(char)*image.height);
is incorrect. It should have sizeof(char*). The statement as written should return a char* but you are casting it to char**.
FWIW, on my system, sizeof(char) returns 1 and sizeof(char*) returns 4, because a char is a single byte, and a char* is a pointer (aka a single word of 32 bits). So you actually allocated 1/4 of what you probably intended to allocate.
If you print out the value that you are passing to malloc, you will find out how much memory you are really asking for.

splitting a full filename into parts

I am creating a function that will split a full unix filename(like /home/earlz/test.bin) into its individual parts. I have got a function, and it works for the first two parts perfect, but after that it produces erroneous output...
strlcpy_char will copy a string using term as the terminator, as well as 0.
If it is terminated with term, then term will be the last character of the string, then null.
returns trg string length...
int strlcpy_char(char *trg,const char *src,int max,char term){
int i;
if(max==0){return 0;}
for(i=0;i<max-1;i++){
if(*src==0){
*trg=0;
return i;
}
if(*src==term){
*trg=term;
trg++;
*trg=0; //null terminate
return i+1;
}
*trg=*src;
src++;
trg++;
}
*trg=0;
return max;
}
.
int get_path_part(char *file,int n,char *buf){
int i;
int current_i=0;
//file is assumed to start with '/'so it skips the first character.
for(i=0;i<=n;i++){
current_i++;
current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
if(current_i<=1){ //zero length string..
kputs("!"); //just a debug message. This never happens with the example
return -1; //not enough parts to the path
}
}
if(buf[current_i-1]=='/'){
return 1; //is not the last part
}else{
return 0; //is the last part(the file part)
}
}
I use this code to test it:
kputs("test path: ");
kgets(cmd);
kputs("\n");
char *tmp=malloc(256);
int i=0;
get_path_part(cmd,i,tmp);
kputs(tmp);
kputs("\n");
i=1;
get_path_part(cmd,i,tmp);
kputs(tmp);
kputs("\n");
i=2;
get_path_part(cmd,i,tmp);
kputs(tmp);
kputs("\n");
When I try something like "/home/test.bin" it works right outputting
/home
/test.bin
But when I try "/home/earlz/test.bin" I get
/home
/earlz
/arlz
Anyone see the problem in my code, as I've been looking but I just can't see any problem.
Also, before you say "but there is a library for that" I am doing this in an operating system kernel, so I barely have a standard library. I only have parts of string.h and really that's about it for standard.
You overwrite current_i instead of adding it up as you walk through the path.
So
current_i++;
current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
should really be
current_i += strlcpy_char(buf,&file[current_i+1],MAX_PATH_PART_SIZE,'/');
I think you need to track your current_i for i>1 since the max value returned from the strlcpy has no idea of where you are in the overall file string. does it make sense?
current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
Don't you need to do something like
tocurrent_i += strlcpy_char...
instead of
tocurrent_i = strlcpy_char...
Does your code have to be re-entrant?
If not use strtok, it is in strings.h
STRTOK(P)
NAME
strtok, strtok_r - split string into tokens
SYNOPSIS
#include <string.h>
char *strtok(char *restrict s1, const char *restrict s2);
char *strtok_r(char *restrict s, const char *restrict sep,
char **restrict lasts);
Sorry for not commenting on your code though :)
If you are using Glib, g_strsplit is very nice and easy to use.
This is how I'd do it
char ** split_into_parts(char *path) {
char ** parts = malloc(sizeof(char *) * 100);
int i = 0;
int j = 0;
if (*path == '/') {
path++;
}
parts[0] = 0;
while (*path) {
if (*path == '/') {
parts[i][j] = 0;
i++;
parts[i] = 0;
j = 0;
} else {
if (parts[i] == 0) {
parts[i] = malloc(sizeof(char) * 100);
}
parts[i][j] = *path;
j++;
}
path++;
}
parts[i+1] = 0;
return parts;
}
Try something like the code I have below.
If you need implementations of standard C functions (like strchr()) try koders.com or just google for strchr.c.
#include <stdio.h>
#include <string.h>
const char *NextToken(const char *pStart, char chSep, char *pToken, size_t nTokMax)
{
const char *pEnd;
size_t nLength;
/* set output to empty */
*pToken=0;
/* make sure input is OK */
if (!pStart || *pStart!=chSep)
return NULL;
/* find end of token */
pEnd = strchr(pStart+1, chSep);
if (pEnd)
nLength = pEnd - pStart;
else
nLength = strlen(pStart);
if (nLength >= nTokMax) /* too big */
return NULL;
strncpy(pToken, pStart, nLength);
pToken[nLength] = 0;
return pEnd;
}
int main()
{
#define BUFFSIZE 256
char cmd[BUFFSIZE];
char tmp[BUFFSIZE];
const char *pStart=cmd;
int i=0;
puts("test path: ");
fgets(cmd, BUFFSIZE, stdin);
puts("");
do {
pStart = NextToken(pStart, '/', tmp, BUFFSIZE);
if (tmp[0])
puts(tmp);
} while (pStart);
return 0;
}

Resources