I have tried using a function that would work in "regular" c:
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE* stream = fopen("v1.csv", "r");
char line[1024];
while (fgets(line, 1024, stdin))
{
char* tmp = strdup(line);
printf("Field 3 would be %s\n", getfield(tmp, 3));
// NOTE strtok clobbers tmp
free(tmp);
}
}
I am trying to read a file names "v1.csv" located in my pebble app resources folder.
You can not read/write to files, use file descriptor or any of the f* functions in the Pebble SDK.
If you want to store data on the watch, you should look into the Persistent Storage API.
Related
I am doing a project which involves using .csv files handling in c. I have been bothered with this question and can't find a solution, I want to know how to edit/ update my csv file.
My csv file is something like:
Username, Pin, Balance
Right now I am able to get the contents of the csv file, but I am struggling on how to update the contents.
I want to make it so that a username can change its pin, so basically changing the value at pin to be something else.
After reading the comments I have tried the replacing method, it goes like this.
void change_pin(char *C){
char line[200];
char user[50];
char date[50];
char action[50];
char user_n[50];
char date_n[50];
char action_n[50];
FILE *str = fopen("Example.csv", "r+");
FILE *new = fopen("new.csv", "w");
if (str == NULL) {
printf("Error opening file");
fclose(str);}
if (new == NULL) {
printf("Error opening file");
fclose(new);}
while(fgets(line, 200, str)){
char *token;
token = strtok(line, ",");
while (token != NULL){
if (strcmp(token, C) == 0){
strcpy(user, token);
token = strtok(NULL, ",");
strcpy(date, token);
token = strtok(NULL, ",");
strcpy(action, token);
token = strtok(NULL, ",");
strcpy(date, C);
fprintf(new, "%s,%s,%s\n", user, date, action);
}
else{
strcpy(user_n, token);
token = strtok(NULL, ",");
strcpy(date_n, token);
token = strtok(NULL, ",");
strcpy(action_n, token);
token = strtok(NULL, ",");
fprintf(new, "%s,%s,%s\n", user_n, date_n, action_n);
}
}
}
remove("Example.csv");
rename("new.csv", "Example.csv");
fclose(str);
fclose(new);
}
The strcpy (date, C) is just for testing
This works!, but the problem is it doesn't work the second time, I don't know why, when I want to do it the second time it gives a error.
I got it to work now just by removing the '\n' in fprintf. Thank you everyone for helping me out
I am trying to read a CSV file of the following format:
5,455,78,5
12245,4,78
1,455,4557,1,8,9
I have managed to open the file but I have no idea how to interpret the data. All the data is written in the first column, but I do not know how many rows there are or how many entries there is in each row.
This is my code for opening the file.
printf("File chosen is: %s",file);
int p=0;
FILE *myFile = NULL;
myFile = fopen(file,"r");
if (myFile == NULL)
{
exit(1);
}
if (myFile != NULL)
{
printf("\n\nFile read succesfully");
}
This should parse your csv. After opening you file, read each line using fgets. Loop through until fgets returns NULL which indicates no line could be read and you reached the end of your file. Use strtok to parse your line from fgets using the comma as your delimiter.
#include <stdio.h> // file handling functions
#include <stdlib.h> // atoi
#include <string.h> // strtok
...
char buffer[80];
while (fgets(buffer, 80, myFile)) {
// If you only need the first column of each row
char *token = strtok(buffer, ",");
if (token) {
int n = atoi(token);
printf("%d\n", n);
}
// If you need all the values in a row
char *token = strtok(buffer, ",");
while (token) {
// Just printing each integer here but handle as needed
int n = atoi(token);
printf("%d\n", n);
token = strtok(NULL, ",");
}
}
...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main()
{
FILE *stream = fopen("yourfile.csv", "r");
int i = 0;
int j = 0;
printf("Choose a line to be given its elements: ");
scanf("%d", &j);
char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp = _strdup(line);
i++;
printf("Element %d would be %s\n", i, getfield(tmp, j));
free(tmp);
}
}
Thank you for posting some code, but you don't mention what you wish to do with your data once you read it in.
I'll give you some pointers:
Use an array of known size to read your data into from the file and buffer it for processing. Run this in a loop. e.g.
char buffer[1000];
while (fgets(buffer, sizeof (buffer), myFile))
{
char *data = strtok(buffer, ",");
printf("Data %s\n", data);
/* Further processing of data */
data = strtok(NULL, ",");
}
fclose(myFile);
Process that buffer using strtok to separate out your strings. The token is the data delimiter which should be ',' but I'm not clear on whether you also have a newline character in there, but it needs to be consistent.
Handle your strings returned above.
I have the following to parse a csv file, and it works fine until i changed
(getfield(tmp, 12));
to
(getfield(tmp, ver));
Is the problem in function declaration ?
here is the code :
const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ";");
tok && *tok;
tok = strtok(NULL, ";\n"))
{
if (!--num)
return tok;
}
return NULL;
}
int main() {
double frame_index[40][300];
int horz;
FILE* fp = fopen("output.txt", "r");
char line[1024];
for (int ver; ver<20;ver++) {
while (fgets(line, 1024, fp)) {
char* tmp = strdup(line);
frame_index[ver][horz] = atof(getfield(tmp, ver));
// works if "ver" was explicitly defined
printf("AA %f\n", frame_index[ver][horz]);
free(tmp);
horz++;
}
rewind(fp);
}
}
You never initialize the variable ver. For example you might want to change
for (int ver; ver<20;ver++)
to
for (int ver=0; ver<20;ver++)
Update The same with horz..
What I am trying to do is to read input from file which is in the format of Data1;Data2;Data3;Data4;Data5 I want to tokenize this string, and store each of these separate pieces of information in a structure such as;
struct example {
char data1[10];
char data2[10];
char data3[10];
char data4[10];
char data5[10];
};
Here's what I have for my input function so far:
void userInput() { // I will need to change return type
FILE *file;
char buffer[BUFFER_SIZE];
struct example data[5];
file = fopen(DATA, "r");
if(file == NULL) {
printf("Error opening data file.\n");
}
while(fgets(buffer, BUFFER_SIZE, file) != null) {
//tokenize strings, and add to struct here
}
}
I realize that in my while function I will need something like:
....
char *token = NULL;
token = strtok(string, ";");
while(token != NULL) {
// add to struct here
token = strtok(NULL, ";");
}
Could someone explain how I would loop through my struct to add this? Or if I'm even going about this the proper way?
You have two things you want to iterate over. I assume each line of input corresponds to a different struct example. Then, you want to iterate over each field in your structure. You need a counter to iterate over your data array, and then you need a mechanism to iterate over the fields. I would use a temporary array to accomplish that:
int i = 0;
while(fgets(buffer, BUFFER_SIZE, file) != null && i < 5) {
char *fields[] = {
data[i].data1, data[i].data2, data[i].data3,
data[i].data4, data[i].data5
};
size_t lengths[] = {
sizeof(data[i].data1), sizeof(data[i].data2), sizeof(data[i].data3),
sizeof(data[i].data4), sizeof(data[i].data5)
};
char *token = NULL;
int j = 0;
token = strtok(string, ";");
while(token != NULL && j < 5) {
snprintf(fields[j], lengths[j], "%s", token);
token = strtok(NULL, ";");
++j;
}
++i;
}
If you want to use a struct, you need some sort of counter to differentiate between your structure elements. Something like:
int x = 0;
while(token != NULL) {
token = strtok(NULL, ";");
// add to struct here
if (x == 0){
data1 = token;
}else if (x == 1){
data2 = token;
}else if (...)
// ... keep going
x++;
}
I want to split a html page into pieces by a tag delimiter: like <img or <div>.
I tried the following code but it doesn't work:
char source[MAXBUFLEN + 1];
FILE *fp = fopen("source.html", "r");
if (fp != NULL)
{
size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp);
if (newLen == 0) {
fputs("Error reading file", stderr);
} else {
source[++newLen] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
//not working
char* strArray[10];
int i = 0;
char *token = strtok(source, "<img");
while(token != NULL)
{
strcpy(strArray[i++], token);
token = strtok(NULL, "<img");
}
printf("%s\n", strArray[3]);
What am I doing wrong? Is there any other method I can use except strtok?
As Daren has already posted, strtok() doesn't do what you want. You can use
char *ptr = strstr( source, "<img" );
instead to find the first tag, and then
ptr = strstr(ptr+4, "<img" ); // search starts direcly behind the previous "<img"
// maybe you can find a better offset
for the next occurances.
Besides, your line
strcpy(strArray[i++], token);
would crash because you have no memory allocated to the pointer.
char *strtokByWord_r(char *str, const char *word, char **store){
char *p, *ret;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
p = strstr(ret=*store, word);
if(p){
*p='\0';
*store = p + strlen(word);
} else {
*store = NULL;
}
return ret;
}
char *strtokByWord(char *str, const char *word){
static char *store = NULL;
return strtokByWord_r(str, word, &store);
}
replace
char *token = strtok(source, "<img");
...
token = strtok(NULL, "<img");
to
char *token = strtokByWord(source, "<img");
...
token = strtokByWord(NULL, "<img");
The second argument to strtok is a list of delimiter characters. Each of these will be used to split the string into tokens. I don't think it does what you think it does...
If you want to go and parse an html file into tokens, you could look into lex...
What is your desired output? Do you have a test case for your input?
Your code should produce the following:
input:
<html><img src="test.png"/></html>
output:
""
"ht"
"l>"
" src=\"test.pn"
"\"/>"
"/ht"
"l>"
I somehow don't think that is what you want...