I have been trying to convert a string in array of integers, floats and characters. While I could get it work for integers and floats, there is some problem for characters.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s1;
int k, no=5;
char* variable = "R1,R2,R3,R4,R5";
void* value;
s1 = calloc(no,sizeof(char)*81);
for (k=0; k<no; k ) s1[k] = strdup(mchar);
ListChar(variable, s1, no, ",");
memcpy(value, s1, no*sizeof(char)*81);
free(s1);
int i;
for (i = 0; i < no; i )
printf("%s", value[i]);
printf("\n");
return 0;
}
In the header file I have
#define mchar "A...(81times)"
Implementation:
int ListChar(char *buf, char *list, int maxloop, char* delim)
{
int n = 0;
char *s,*t;
s= strdup(buf);
t= strtok(s,delim);
while ( t && (n<maxloop))
{
if (list!=NULL) list[n] =strdup(t);
n ;
t=strtok(NULL,delim);
}
free(s);
return(n);
}
During the calloc memory assignment when I watch s1
its 0xsomeadress ""
After the for loop s1
becomes 0xsomeadress "Garbage value 81 times"
When s1
is assigned to list
its still reads the same garbage value.
And when list [n] = strdup(t)
list[0]
reads the first block of garbage value like -21 '\221 ṗ'
.
t
is getting delimited correctly. I even tried initializing char *s1[81] = {"something"}
and looping it on j
but it wont work, same problem, and I need to free s1
at the end because this function runs for number of times. I did it for integers and floats by list[n]=atoi(t)
it works fine. Can anyone suggest me something?
CodePudding user response:
There seems to be a fundamental misunderstanding about how strings work. Your s1
clearly needs to be a char **
and the usage of strdup
is incorrect. If s1
is of type char *
, then s1[k]
is of type char
. But strdup
returns a char *
, so s1[k] = strdup ...
is clearly an error which your compiler ought to warn you about. Perhaps you want something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void * xmalloc(size_t s);
void
ListChar(const char *buf, char **list, int maxloop, int delim)
{
char set[] = {delim, 0};
for( int n = 0; n < maxloop; n = 1 ){
size_t len = strcspn(buf, set);
list[n] = xmalloc(len 1);
memcpy(list[n], buf, len);
buf = len 1;
}
}
int
main(int argc, char **argv)
{
int delim = ',';
(void)argc; /* Suppress compiler warning */
while( * argv ){
char **s1;
int k, num = 1;
char *input = *argv;
for( const char *p = input; *p; p = 1 ){
if( *p == delim ){
num = 1;
}
}
s1 = xmalloc(num * sizeof *s1);
ListChar(input, s1, num, delim);
for( int i = 0; i < num; i = 1 ){
printf("%s\n", s1[i]);
}
free(s1);
}
return 0;
}
void *
xmalloc(size_t s)
{
void *rv = malloc(s);
if( rv == NULL ){
perror("malloc");
exit(EXIT_FAILURE);
}
return rv;
}
Note that the above code scans each string twice, which is not ideal. Rather than scanning the string to find the number of delimiters and then parsing the string, it would be better to do both in one pass. But for the purposes of demonstrating how to break up the string, that seems like unnecessary complexity. (Though it's actually simpler, IMO)