I'm trying to load a CSV file into a single dimentional array. I can output the contents of the CSV file, but in trying to copy it into an array I'm having a bit of trouble.
Here is my existing code, which I realise is probably pretty bad but I'm teaching myself:
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LENGTH 1024
#define MAX_CSV_ELEMENTS 1000000
int main(int argc, char *argv[])
{
char line[MAX_LINE_LENGTH] = {0};
int varCount = 0;
char CSVArray[MAX_CSV_ELEMENTS] = {0};
FILE *csvFile = fopen("data.csv", "r");
if (csvFile)
{
char *token = 0;
while (fgets(line, MAX_LINE_LENGTH, csvFile))
{
token = strtok(&line[0], ",");
while (token)
{
varCount++;
CSVArray[varCount] = *token; //This is where it all goes wrong
token = strtok(NULL, ",");
}
}
fclose(csvFile);
}
return 0;
}
Is there a better way I should be doing this? Thanks in advance!
*token means dereferencing the pointer token which is the address of the first character in a string that strtok found. That's why your code fills CSVArray with just the first characters of each token.
You should rather have an array of char pointers to point at the tokens, like:
char *CSVArray[MAX_CSV_ELEMENTS] = {NULL};
And then assign a pointer to its elements:
CSVArray[varCount] = token;
Alternatively, you can copy the whole token each time:
CVSArray[varCount] = malloc(strlen(token)+1);
strcpy(CVSArray[varCount], token);
You are right about the problem line. It is because you are assigning a pointer, not copying the text.
Try here http://boredzo.org/pointers/ for a tutorial on pointers.
It looks like you're trying to put the char * that comes back from strtok into the char array.
I think you want to declare CSVArray as:
char * CSVArray[MAX_CSV_ELEMENTS] = {0};
Related
I'm having a lot of problems doing this task. I have a txt with only one line of words separated by commas. I have to read this and put it in an array.
So far i tried using strtok() but it just gives me errors. Here's my code:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<omp.h>
int main(){
char string[5000],list[200],*token,s=", ";
int i;
FILE *lista;
lista=fopen("lista.txt","r");
i=0;
token=strtok(string,s);
strcpy(list[i],token);
while(fscanf(lista,"%s",string)!=EOF){
token=strtok(NULL,s);
strcpy(list[i],token);
i=i+1;
}
fclose(lista);
}
It gives me the" expectig char *restrict" error
I'm seriously out of ideas.
BTW: I'm in Linux
There are many strange things in your code, but i guess, you want something like this:
char string[5000], *list[200], *token;
char * s = ",";
int i;
FILE *lista;
lista = fopen("C:\\File.txt", "r");
int MAX_FILE_SIZE = 1000;
char * buffer = (char*)malloc(sizeof(char)*MAX_FILE_SIZE);
fread(buffer, sizeof(char), MAX_FILE_SIZE, lista);
list[0] = strtok(buffer, s);
for (int i = 1;; i++)
{
list[i] = strtok(NULL, s);
if (list[i] == NULL)
{
break;
}
}
fclose(lista);
What is strange/wrong in your code:
You are passing char* string into strtok function, but this variable is uninitialised when passing
You have file pointer lista, but you never read from this file
You have variable list which is array of 200 chars, but i guess you want to have variable list as a list of strings
strtok eats two parameters, const char* inputString and const char* delimiter. So your variable s should be const char *
So I'm trying getting my input as file.txt,r and I have to split the string on the comma and save both file.txt and r into separate strings... but I'm really confused how to do that. I looked up strtok
and this is what I have so far:
char buffer[256];
char filename[2][40];
char operation[20];
n = read(sock,buffer,255); //read the message from the client into buffer
char cinput[300];
strcpy(cinput,buffer);//now cinput has the whole thing
char *token;
token = strtok(cinput,",");
while(token)
{
printf("%s\n",token);
token = strtok(NULL,",");
}
But I'm confused... how would I store file.txt and r as separate strings once parsed?
edit: something like this?
char *token;
char *pt;
pt = strtok(cinput,","); //this will hold the value of the first one
strcpy(filename,pt);
token = strtok(cinput,",");
while(token)
{
//printf("%s\n",token);
token = strtok(NULL,",");
}
printf("%s\n",token); //this will hold the value of the second one
strcpy(operation,token);
printf("%s\n",operation);
All you should need is separate pointers. You don't need to allocate all these buffers or use strcpy().
Just assign the return values from strtok() in multiple char * pointers.
Something like:
char *p1 = strtok("file.txt,r", ",");
char *p2 = strtok(NULL, ",");
may be a compact approach
//your data pattern
typedef
struct file_inputs {
char *fname;
char *fmode;
} finput_t;
and some where in your code
finput_t fi;
fi.fname = strtok(cinput,",");
fi.fmode = strtok(NULL,",");
I have to check if strings given by the user are correct expressions. The strings should look like this:
int1+int2+int3+int4+...
for example:
1+5+21
Is a correct expression, while 1+a is not.
How can I do that?
The problem I encountered is that I define strings like:
char *str;
str = (char*)malloc(1024*sizeof(char));
char **output = strtok(str, "+"); // error
So I get segmentation fault when using strtok function.
Example of using strtok, in your case:
#include <string.h>
#include <stdio.h>
int function()
{
char* str = malloc(80);
strcpy(str,"1+5+21");
const char s[2] = "+";
char *token;
token = strtok(str, s); /* get the first token (1) */
while( token != NULL ) /* walk through other tokens */
{
// characters manipulation for verification
}
free(str);
return(0);
}
I need help with breaking a string into an array.
I got it to work without storing the info and just printing the tokens.
But for this prog, I need to store the tokens strtok made and use a binary search to do a strncmp with 2 elements each being from a different array.
./file "Example input: 'Cause I'm Batman"
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char delims[] = " ";
char *result = NULL;
int i = 1;
int j = 0;
char sent[1000];
result = strtok(argv[1], delims);
sent[0] = *result;
while(result != NULL)
{
result = strtok(NULL, delims);
sent[i] = *result;
i++;
}
while(j < i)
{
printf(" %p\n", &sent[j]);
j++; //Forgot to add it in first time around
}
return 0;
}
Problem is I'm getting a segmentation fault and I can't seem to get it to store the tokens into an array and I don't understand why. Is it a pointer issue? Passing incompatible data types? Something else?
Edit: Wanted output: "Example" "input:" "'Cause" "I'm" "Batman"
Any help would be great.
In your case it's very easy to figure out what's causing the crash: You dereference the NULL pointer.
Think for a minute what will happen with the expression *result when result is NULL.
Also, this error would have taken you less than a minute to find if you used a debugger. When a program crashes, a programmers first instinct should always be to run the program in a debugger.
fix like this
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]){
char delims[] = " ";
char *result = NULL;
int i = 0, j;
char sent[1000];
char *parray[32];//32 word
strcpy(sent, argv[1]);//strtok destory string, argv[n] is read only.
result = strtok(sent, delims);
parray[i++] = result;
while(NULL!= (result=strtok(NULL, delims))){
parray[i++] = result;
}
for(j=0; j < i;++j)
printf("%s\n", parray[j]);
return 0;
}
When strtok reaches '\0' NUL character in the string, it will return NULL pointer.
In your code 'result' is de-referenceed after making strtok(NULL, delims) call. As a result you will be de-referencing result without making a sanity check for its validity and will end up accessing NULL pointer.
I learnt C in uni but haven't used it for quite a few years. Recently I started working on a tool which uses C as the programming language. Now I'm stuck with some really basic functions. Among them are how to split and join strings using a delimiter? (I miss Python so much, even Java or C#!)
Below is the function I created to split a string, but it does not seem to work properly. Also, even this function works, the delimiter can only be a single character. How can I use a string as a delimiter?
Can someone please provide some help?
Ideally, I would like to have 2 functions:
// Split a string into a string array
char** fSplitStr(char *str, const char *delimiter);
// Join the elements of a string array to a single string
char* fJoinStr(char **str, const char *delimiter);
Thank you,
Allen
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char** fSplitStr(char *str, const char *delimiters)
{
char * token;
char **tokenArray;
int count=0;
token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));
if (!token) {
return tokenArray;
}
while (token != NULL ) { // While valid tokens are returned
tokenArray[count] = (char*)malloc(sizeof(token));
tokenArray[count] = token;
printf ("%s", tokenArray[count]);
count++;
tokenArray = (char **)realloc(tokenArray, sizeof(char *) * count);
token = (char *)strtok(NULL, delimiters); // Get the next token
}
return tokenArray;
}
int main (void)
{
char str[] = "Split_The_String";
char ** splitArray = fSplitStr(str,"_");
printf ("%s", splitArray[0]);
printf ("%s", splitArray[1]);
printf ("%s", splitArray[2]);
return 0;
}
Answers: (Thanks to Moshbear, Joachim and sarnold):
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char** fStrSplit(char *str, const char *delimiters)
{
char * token;
char **tokenArray;
int count=0;
token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));
tokenArray[0] = NULL;
if (!token) {
return tokenArray;
}
while (token != NULL) { // While valid tokens are returned
tokenArray[count] = (char*)strdup(token);
//printf ("%s", tokenArray[count]);
count++;
tokenArray = (char **)realloc(tokenArray, sizeof(char *) * (count + 1));
token = (char *)strtok(NULL, delimiters); // Get the next token
}
tokenArray[count] = NULL; /* Terminate the array */
return tokenArray;
}
char* fStrJoin(char **str, const char *delimiters)
{
char *joinedStr;
int i = 1;
joinedStr = realloc(NULL, strlen(str[0])+1);
strcpy(joinedStr, str[0]);
if (str[0] == NULL){
return joinedStr;
}
while (str[i] !=NULL){
joinedStr = (char*)realloc(joinedStr, strlen(joinedStr) + strlen(str[i]) + strlen(delimiters) + 1);
strcat(joinedStr, delimiters);
strcat(joinedStr, str[i]);
i++;
}
return joinedStr;
}
int main (void)
{
char str[] = "Split_The_String";
char ** splitArray = (char **)fStrSplit(str,"_");
char * joinedStr;
int i=0;
while (splitArray[i]!=NULL) {
printf ("%s", splitArray[i]);
i++;
}
joinedStr = fStrJoin(splitArray, "-");
printf ("%s", joinedStr);
return 0;
}
Use strpbrk instead of strtok, because strtok suffers from two weaknesses:
it's not re-entrant (i.e. thread-safe)
it modifies the string
For joining, use strncat for joining, and realloc for resizing.
The order of operations is very important.
Before doing the realloc;strncat loop, set the 0th element of the target string to '\0' so that strncat won't cause undefined behavior.
For starters, don't use sizeof to get the length of a string. strlen is the function to use. In this case strdup is better.
And you don't actually copy the string returned by strtok, you copy the pointer. Change you loop to this:
while (token != NULL) { // While valid tokens are returned
tokenArray[count] = strdup(token);
printf ("%s", tokenArray[count]);
count++;
tokenArray = (char **)realloc(tokenArray, sizeof(char *) * count);
token = (char *)strtok(NULL, delimiters); // Get the next token
}
tokenArray[count] = NULL; /* Terminate the array */
Also, don't forget to free the entries in the array, and the array itself when you're done with it.
Edit At the beginning of fSplitStr, wait with allocating the tokenArray until after you check that token is not NULL, and if token is NULL why not return NULL?
I'm not sure the best solution for you, but I do have a few notes:
token = (char *)strtok(str, delimiters); // Get the first token
tokenArray = (char**)malloc(1 * sizeof(char*));
if (!token) {
return tokenArray;
}
At this point, if you weren't able to find any tokens in the string, you return a pointer to an "array" that is large enough to hold a single character pointer. It is un-initialized, so it would not be a good idea to use the contents of this array in any way. C almost never initializes memory to 0x00 for you. (calloc(3) would do that for you, but since you need to overwrite every element anyway, it doesn't seem worth switching to calloc(3).)
Also, the (char **) case before the malloc(3) call indicates to me that you've probably forgotten the #include <stdlib.h> that would properly prototype malloc(3). (The cast was necessary before about 1989.)
Do note that your while() { } loop is setting pointers to the parts of the original input string to your tokenArray elements. (This is one of the cons that moshbear mentioned in his answer -- though it isn't always a weakness.) If you change tokenArray[1][1]='H', then your original input string also changes. (In addition to having each of the delimiter characters replaced with an ASCII NUL character.)