Can anyone advise on a simple way of converting a csv string to an array of floats in C?
e.g.
char my_string[] = "1.0,2.0,3.0";
to:
my_array = [1.0, 2.0, 3.0]
where my_array is of type float[]
I would use sscanf as a quick and easy solution but I don't know how many values are contained in the string in advance
Is there some existing library function that could do this without me having to resort to looping over every char looking for a ","?
You could use strtok():
float my_array[N]; // if you don't know how many there are, use the heap
int i = 0;
char *tok = strtok(my_string, ",");
while (tok != NULL) {
my_array[i++] = atof(tok);
tok = strtok(NULL, ",");
}
There's a library you could use - LibCSV
From their description:
libcsv is a small, simple and fast CSV library written in pure ANSI
C89 that can read and write CSV data. It provides a straight-forward
interface using callback functions to handle parsed fields and rows
and can parse improperly formatted CSV files
Use a while() loop that reads only one float at a time with sscanf(). As soon as sscanf() returns 0, you know you're at the end of the list.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** split(const char *str, const char *delimiter, size_t *len){
char *text, *p, *first, **array;
int c;
char** ret;
*len = 0;
text=strdup(str);
if(text==NULL) return NULL;
for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
if(c==0) first=p; //first token top
ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
if(ret==NULL){
free(text);
return NULL;
}
strcpy(text, str+(first-text));//skip until top token
array=ret;
for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
*array++=strdup(p);
}
*array=NULL;
*len=c;
free(text);
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
while(*sa)
free(*sa++);//for string
free(array); //for array
}
}
int main(){
char my_string[] = "1.0,2.0,3.0";
float *my_array;
char **strs;
size_t count;
strs=split(my_string, ", \t", &count);
my_array=(float*)malloc(sizeof(float)*count);
{ //convert
int i;
for(i=0;i<count;++i)
my_array[i]=(float)atof(strs[i]);
free4split(strs);
}
{ //test print
int i;
for(i=0;i<count;++i)
printf("%f\n", my_array[i]);
}
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getToken(char **p, const char delimiter){
char *word, *top=*p;
int len;
if(*p == NULL || **p == '\0') return NULL;
while(**p && **p != delimiter)
++(*p);
if(**p != delimiter) return strdup(top);
len = *p - top;
++(*p);
word=(char*)malloc(sizeof(char)*(len+1));
strncpy(word, top, len);
word[len]='\0';
return word;
}
int main(){
char my_string[] = "1.0,2.0,3.0";
float *my_array=NULL;
char *word, *p=my_string;
int count=0;
while(NULL!=(word=getToken(&p, ','))){
my_array=(float*)realloc(my_array, sizeof(float)*(++count));
my_array[count-1]=(float)atof(word);
free(word);
}
{ //test print
int i;
for(i=0;i<count;++i)
printf("%f\n", my_array[i]);
}
return 0;
}
You might want to look into using the strchr family of functions.
STRCHR(3) Linux Programmer's Manual STRCHR(3)
NAME
strchr, strrchr - locate character in string
SYNOPSIS
#include <string.h>
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
DESCRIPTION
The strchr() function returns a pointer to the first
occurrence of the character c in the string s.
The strrchr() function returns a pointer to the last
occurrence of the character c in the string s.
RETURN VALUE
The strchr() and strrchr() functions return a pointer to
the matched character or NULL if the character is not
found.
CONFORMING TO
SVID 3, POSIX, BSD 4.3, ISO 9899
SEE ALSO
index(3), memchr(3), rindex(3), strpbrk(3), strsep(3),
strspn(3), strstr(3), strtok(3)
Related
char* str =
"\
a-a-a-a\
differing the text, because that was the lecture thing\
the text has been changed\
I know!\
the text has been changed\
";
i deeply thinking about this for hours but can`t figure it out..
with using only stdio.h
string.h is not allowed, but using only basic things..
how can I get string length? someone please help me.
the goal is to find frequency of input pattern in a given string
ex) ha => 2, di => 1..
help me.
As for length of string, the implementation of strlen isn't very complicated.
All you should do is to loop over the string until you find a \0 (end of string) and count the number of times you looped.
unsigned int mystrlen(const char* str)
{
unsigned int length = 0;
while (*str != 0)
{
str++;
length++;
}
return length;
}
This could be shortened into
unsigned int len = 0;
for (; str[len]; len++);
A string in pure C is just a pointer to a memory.
IF the last element is 0, then you can use strlen or whatever checks for that.
But if that is not the case you need to memorize the length in a variable.
So if it is 0-terminated just loop to the first element that is 0 (not '0') and thats the end. If you counted the elements you have the string-length.
This works for some test input string, but i higly recommend to check it with more cases.
Suppose we have implemented strstr().
strstr()
Is a C library function from string.h Library
char *strstr(const char *haystack, const char *needle)
This function finds the first occurrence of the substring needle in the source string haystack.
The terminating \0 characters are not compared.
source: TutorialsPoint
(with some edition)
Code
#include <stdio.h>
#include <string.h>
unsigned int Neostrlen(const char* str)
{
unsigned int length = 0;
while (*str != 0)
{
str++;
length++;
}
return length;
}
int BluePIXYstrlen(char* str)
{
int len = 0;
sscanf(str, "%*[^0]%n", &len);
return len;
}
int Jeanfransvastrlen(char* str)
{
int i;
for (i=0;str[i];i++);
return i;
}
int main(int argc, char **argv){
//is it true, no need to malloc????
char* str =
"\
P-P-A-P\
I have a pen, I have a apple\
Uh! Apple-Pen!\
I have a pen, I have pineapple\
Uh! Pineapple-Pen!\
Apple-Pen, Pineapple-Pen\
Uh! Pen-Pineapple-Apple-Pen\
Pen-Pineapple-Apple-Pen\
";
printf("len: %d\n", Jeanfransvastrlen(str));
printf("len: %d\n", Neostrlen(str));
printf("len: %d\n", BluePIXYstrlen(str));
printf("sss:%s\n\n\n", str);
char * search = "have";//search for this substring
int lenSr= Neostrlen(search);
printf("lenSr: %d\n", lenSr);
char * ret;
ret = strstr(str, search);
int count = 0;
while (ret){
//printf("The substring is: %s\n\n\n\n", ret);
count++;
for (int i=0;i<lenSr;i++){
printf("%c", ret[i]);
}
printf("\nEnd sub\n");
for (int i=0;i<lenSr;i++){
ret++;
}
ret = strstr(ret, search);
}
printf("count: %d\n", count);
return 0;
}
Edited
For only using stdio.h you can substitute all strstr() with this version of mystrstr() adopted from leetcode
mystrstr()
char* mystrstr(char *str, const char *target) {
if (!*target) {
return str;
}
char *p1 = (char*)str;
while (*p1) {
char *p1Begin = p1, *p2 = (char*)target;
while (*p1 && *p2 && *p1 == *p2) {
p1++;
p2++;
}
if (!*p2){
return p1Begin;
}
p1 = p1Begin + 1;
}
return NULL;
}
Hint
I removed const from first first argument of mystrstr() because of I want to change it later, and this is the only changed i have made on original code.
This version is sensitive to Uppercase and lowercase letters in string,
for example Apple is differ from apple.
As chux said in comments my code return substrings of "ababa" from source
"aba" only {aba} not more. and this is because i change string pointer inside while in last for.
Suggestion
Try to implement your version of strstr(), and strlen()
I have the following string abcd1234 and I want to find a way to break this string into two different strings, abcd and 1234. I have tried the following code:
char buf[100],*str1,*str2;
int x;
fgets(buf,sizeof(buf),stdin);
str1=strtok(buf,"0123456789 \t\n");
str2=strtok(NULL," \n\t\0");
puts(str1);
puts(str2);
x=atoi(str2);
printf("x=%d", x);
but output is abcd 234. And if I try it with one letter and one number, e.g a2 I take only e on output and x is 0.
As per the man page of strtok()
Each call to strtok() returns a pointer to a null-terminated string containing the next token. This string does not include the delimiting byte. [...]
So, while using "0123456789 \t\n" as the delimiter for the first time, 1 will be treated as the actual delimiter and will not be considered in the subsequent parsing.
You may want to use strcspn() and/or strpbrk() to find out the index for the required sub-strings and parse accordingly.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
size_t extract(const char **sp, char *out, int (*test)(int ch));
int main(void){
char buf[100], str1[100], str2[100];
int x;
const char *p = buf;
//size_t len;
fgets(buf, sizeof(buf), stdin);
while(*p){
if(isalpha((unsigned char)*p)){
extract(&p, str1, isalpha);
puts(str1);
} else if(isdigit((unsigned char)*p)){
extract(&p, str2, isdigit);
x = atoi(str2);
printf("%s, x=%d\n", str2, x);
} else {
++p;//skip one char
}
}
return 0;
}
size_t extract(const char **sp, char *out, int (*test)(int ch)){
const char *p = *sp;
while(*p && test((unsigned char)*p)){
*out++ = *p++;
}
*out = '\0';
size_t len = p - *sp;
*sp = p;
return len;
}
Try below code.Hope this will help you.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char string[]="abcd1234";
char digitStr[10];
char charStr[10];
int i,j = 0,k = 0;
for(i=0;string[i];i++)
{
if(isdigit(string[i]))
{
charStr[j++]=string[i];
}
else
{
digitStr[k++]=string[i];
}
}
charStr[j] = '\0';
digitStr[k] = '\0';
printf("%s %s\n",digitStr,charStr);
}
I realize I'm very late on this one, but this is for if anyone has a similar case
Assuming all input strings are like your example, this method will work.
char buf[100];
fgets(buf, sizeof(buf), stdin);
if (buf[strlen(buf) - 1] == '\n')
buf[strlen(buf) - 1] = '\0';
int x = atoi(strpbrk(buf, "0123456789"));
char letters[number - buf + 1];
memcpy(letters, sizeof(letters) - 1, buf);
letters[sizeof(letters) - 1] = '\0';
//letters is the word
//x is the number as an int, not a string
• Note the if statement after the fgets. This checks that the newline character was read by fgets, and turns it into a NUL character. (essentially truncating the string).
• As for strpbrk(), that's just a function that returns a pointer to the first occurence of any character in the second string inside the first string. I use it here to find the start of the digit sequence.
• I would also drop the atoi() for strtol() for safety.
• The letters[] array size is the return of strpbrk() (the address of the first number), minus the start of the array (giving the length of the letter string in bytes), plus one for the NUL character I add later.
I'm new to programming,and I have a small problem.
I have a file named questions.txt containing a string of questions, I want to read the string from the file then split it into array with each question having an index, for example a[i] = "Question i" etc.
I did so many tries, but it always ends up reading the last line in the file, when write a loop the program stops working.
This is what i came up with, it's all probably wrong:
char str[200];
char *ptr;
FILE * fp = fopen("questions.txt", "r");
while(fgets(str, 200, fp)!= NULL)
printf("%s", str);
ptr = strtok(str, "\n");
while(ptr != NULL)
{
ptr = strtok(str, "\n");
printf("%s\n", ptr);
ptr = strtok(NULL, "\n");
}
fclose(fp);
The file is:
what is your course?
who is your instructor?
Output i get is:
what is your course?
who is your instructor?
who is your instructor?
I want to read the string from the file then split it into an array with each question having an index...
Let me say, that you don't have a string to split into array.
You should better have a file with a one string of questions like this:
what is your course?:who is your instructor? // `:` is some kind of delimiter
I can suppose that you want to make a vector (one dimensional array) of the file. And in that vector, each element will contain a question from the file. Right?
I can share with you a function from my library I've made at the university. I'll write here a simple program. But it uses delimiters - :, for example. You can modify this function for working without delimiters -- this only depends on you.
In two words, this little program does the following:
// BEFORE: you have a string that ends with a null terminating character.
Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa\n
^
here ^<< printing 'string' stops
// AFTER: an array of questions. Each of them ends with a null terminating character.
Question_1_abcbadsad\nQUestion_2asasdasd\nQuestion_3sldasdsa\n
^
^<< printing argz[0] will stop here
main.c
#include "argz.h"
int main()
{
error_t func;
char *argz; // pointer to a vector; to an array of questions
size_t argz_len;
// size of that vector (the size of the string you've got from the file)
// Consider `string` to be your `ptr`. You read a string from the file so
// `ptr` will point to the string.
char *string = "Question_1_abcbadsad:QUestion_2asasdasd:Question_3sldasdsa";
// Here `:` is a separate character.
func = argz_create_sep(string, ':', &argz, &argz_len);
if(func == OK)
argz_print(argz, argz_len);
else
printf("ERROR\n");
return 0;
}
argz.c
#include "argz.h"
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len)
{
int i;
char *ch;
int len = strlen(string);
if(len==0)
return ENOMEM;
*argz = (char*) malloc (sizeof(char)*(len + 1));
strcpy(*argz, string);
*argz_len = strlen(*argz);
ch = *argz;
for(i = 0; i < len; i++) {
if(*ch == sep) *ch='\0';
ch++;
}
return OK;
}
void argz_print(const char *argz, size_t argz_len)
{
const char *ch;
int i;
ch = argz;
for(i = 0; i < argz_len; i++) {
if(*ch == '\0')
printf("\n");
else
printf("%c",*ch);
ch++;
}
printf("\n\n\n");
}
argz.h
#include <stddef.h> // for size_t
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef enum {OK, ENOMEM} error_t;
/* function prototypes */
error_t argz_create_sep (const char *string, int sep, char **argz, size_t *argz_len);
void argz_print (const char *argz, size_t argz_len);
I think what you want is something like this:
#include <stdio.h>
int main(){
int i=0;
char str[200],s='1'; //s is give a random character
FILE * fp = fopen("questions.txt", "r");
while (s!=EOF){ //works until s= the end of file
s=getc(fp); //s starts to receive characters from text file
str[i]=s; //each character of text is placed into the string array
i++;
}
str[i]='\0'; //s reached EOF so lets indicate where we stopped in the string
fclose(fp);
printf("%s\n",str);
//EDIT: changing 1D str to 2D str2
char str2[10][200]; // 10 for max no. of questions, 200 - length of each question
int j=0,k=0;
i=0;
for(j=0;j<200;j++){
str2[i][k]=str[j];
k++;
if (str[j]=='\n'){
i++;
k=0;}
}
for(i=0;i<10;i++) //prints your 2D string array
printf("%s",str2[i]); //after the last question there will be junk
return 0;
}
The code reads a text file delimited by colons : and formatted as follows
1111:2222:3333
How would I store the values separated by colons : into separate variables ?
any help would be appreciated.
program code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
int read_file();
int main()
{
read_file(); // calls function to read file
return 0;
}
// read text file function
int read_file()
{
char line[100];
char file_location[40];
FILE *p_file;
printf("Enter file location: ");
scanf("%s",file_location);
p_file =fopen(file_location, "r");
if(!p_file)
{
printf("\n File missing:");
return 0;
}
while(fgets(line,100,p_file)!=NULL)
{
printf("%s \n",line);
}
fclose(p_file);
return 0;
}
This will give you a hint :
Use strtok as you would do for reading a csv file
while(fgets(line,100,p_file) != NULL)
{
char *p = strtok(line, ":");
while(p)
{
printf("%s\n", p); //Store into array or variables
p=strtok(NULL, ":");
}
}
POW already gave you everything you need to know.
So, FWIW:
One of the things C coders do is to keep a library of simple utitlies. Whacking a string up using delimiters is one of those utilities.
Here is a very simple (no error checking) example:
char **split(char **r, char *w, const char *src, char *delim)
{
int i=0;
char *p=NULL;
w=strdup(src); // use w as the sacrificial string
for(p=strtok(w, delim); p; p=strtok(NULL, delim) )
{
r[i++]=p;
r[i]=NULL;
}
return r;
}
int main()
{
char test[164]={0x0};
char *w=NULL; // keep test whole; strtok() destroys its argument string
char *r[10]={NULL};
int i=0;
strcpy(test,"1:2:3:4:hi there:5");
split(r, w, test, ":\n"); // no \n wanted in last array element
while(r[i]) printf("value='%s'\n", r[i++]);
printf("w='%s' test is ok='%s'\n",
(w==NULL)? "NULL" : w, test);// test is still usable
free(w); // w is no longer needed
return 0;
}
If I want to know the length of the string without using standard libraries and the array in the program. How am I supposed to find the length?
You should iterate a C string until reaching to \0
#include <stdio.h>
int my_str_len(char *s)
{
int len;
char *ptr = s;
for (len = 0; *ptr; ptr++, len++)
// nothing
;
return len;
}
int main()
{
char str[] = "Hello";
printf("%i\n", my_str_len(str));
return 0;
}
print that string using printf
int count = printf("%s", str);
printf returns the number of characters printed.