Use strtok like the following... arrayOfString will have list of strings.
#include <string.h>
#include <stdio.h>
int main()
{
char str[80] = "apples, pears, oranges,";
char* arrayOfString[3];
const char s[2] = ", ";
char *token;
int i=0;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL )
{
arrayOfString[i] = token;
token = strtok(NULL, s);
i++;
}
for(i=0;i<3;i++)
printf("%s\n", arrayOfString[i]);
return(0);
}
Answer from sabbir on Stack OverflowYour data field only holds one char now. It needs to have room for at least the typical value, like 02/19/18.
Use char[10] for example (if you know for sure that it can never be longer than 9 characters).
I think the compiler ought to have warned against your fscanf call.
Your fscanf() calls are off: When you make this call
fscanf(csv, "%s[^,]", v[i].data);
fscanf() will first parse a string of non-whitespace characters until it finds a whitespace character (the %s conversion), so "02/20/18,11403.7" gets written to your array, and your buffer will overflow. After that, you are in undefined behavior territory, and anything could happen. The [^,] conversion won't even be reached before you get UB.
Of course, you can simply fix this by dropping the %s from your format string, but I think, what you really want to do, is to just parse all the numbers as numbers:
int month, day, year;
double value;
int conversionCount = fscanf(csv, "%d/%d/%d,%lf\n", &month, &day, &year, &value);
if(conversionCount != 4) {
handleError();
}
Do not forget to check the result of fscanf() as it's the only way to know whether parsing completed successfully. I have added \n at the end of the format string, which will gobble up any whitespace following the float value, including the newline character. This allows you to perform your conversions one line at a time with a single fscanf() in a simple loop, without any need to call fseek(). Just keep parsing lines until an fscanf() call returns something other than the number of conversions you expect.
The function you are looking for is strtok. That means String Tokenizer.
I think this will work for you:
char str[] = get_order_type(optarg);
const char s[2] = ",";
char *token;
/* get the first token */
token = strtok(str, s);
/* walk through other tokens */
while( token != NULL )
{
printf( " %s\n", token );
token = strtok(NULL, s);
}
Anyway, here you have the documentation for the method.
Hope it helps!!
#define max_strln 30
#define max_str_no 20
char input[] = get_order_type(optarg);
char *str;
int i_ctr;
char arr[max_str_no ][max_strln];
for(i_ctr = 0,str = strtok(input,","); str!= NULL; i_ctr++, str= strtok(NULL,","))
{
strcpy( arr[i_ctr], str);
}
Explanation:
we take comma separator string in "input" variable and tokenize that variable by delimiter ( here comma). strtok return string which is separate by delimiter (here comma is delimiter). finally we copy that string into array using copy function.
I'm trying to do some advent of code challenges with C but I can't figure out the proper way to convert my input from a text file to an array. (Of course I could just copy the input directly into my C-file to use as an array but I want to understand how I can get it from a text file to an array). Also I want to get the length of that array.
My input looks like this: 3,5,1,2,5,4,1,5,1,2,5, ...
Here's what I already have
int main() {
FILE *fp = fopen("../input.txt", "r");
assert(NULL != fp);
int length = 0;
char charArray[] = {};
while (!feof(fp)) {
char ch = fgetc(fp);
if (isdigit(ch)) {
length++;
// push to charArray?
}
};
fclose(fp);
for (int i = 0; i < length; ++i) {
printf("%d,",charArray[i]);
}
printf("%d\n", length);
return 0;
}Try this small User Defined Function:
Public Function PeopleKounter(s As String) As Long
Dim DQ As String, c As Collection
Set c = New Collection
DQ = Chr(34)
ary = Split(Replace(s, DQ, ""), ",")
On Error Resume Next
For Each a In ary
c.Add a, CStr(a)
Next a
On Error GoTo 0
PeopleKounter = c.Count
End Function

This formula will iterate the "words" and only count the Unique.
=SUMPRODUCT(--(ISERROR(FIND(TRIM(MID(SUBSTITUTE(A1,",",REPT(" ",99)),(ROW($1:$17)-1)*99+1,99)),TRIM(MID(SUBSTITUTE(A1,",",REPT(" ",99)),1,(ROW($1:$17)-1)*99+1))))))
As it iterates it compares it to the current with all that came before with FIND(). And error is returned if not found and thus it is counted.

string s = "1,5,7";
int[] nums = Array.ConvertAll(s.Split(','), int.Parse);
or, a LINQ-y version:
int[] nums = s.Split(',').Select(int.Parse).ToArray();
But the first one should be a teeny bit faster.
string numbers = "1,5,7";
string[] pieces = numbers.Split(new string[] { "," },
StringSplitOptions.None);
int[] array2 = new int[pieces.length];
for(int i=0; i<pieces.length; i++)
array2[i] = Convert.ToInt32(pieces[i]);
const array = str.split(',');
MDN reference, mostly helpful for the possibly unexpected behavior of the limit parameter. (Hint: "a,b,c".split(",", 2) comes out to ["a", "b"], not ["a", "b,c"].)
Watch out if you are aiming at integers, like 1,2,3,4,5. If you intend to use the elements of your array as integers and not as strings after splitting the string, consider converting them into such.
var str = "1,2,3,4,5,6";
var temp = new Array();
// This will return an array with strings "1", "2", etc.
temp = str.split(",");
Adding a loop like this,
for (a in temp ) {
temp[a] = parseInt(temp[a], 10); // Explicitly include base as per Álvaro's comment
}
will return an array containing integers, and not strings.
You have several issues to work through to convert your function from simply printing the separated strings to stdout to saving the separated strings in ArrayOfString. Before getting to the changes, let's avoid using magic numbers in your code.
char ArrayOfString[10][5];
In ArrayOfString above, 10 and 5 are magic numbers. They are hardcoded values that will govern everything from the declaration size to required validation checks to protect your array bounds. Instead of hardcoding values, if you need a constant, define one (or more), e.g.
#include <stdio.h>
#include <string.h>
#define ROW 10
#define COL 5
char ArrayOfString[ROW][COL];
Now on to separating your string into tokens. The C-library provides a function specifically tailored to separating delimited strings into tokens. Conveniently named strtok. The only caveat to know about strtok is that it modifies the string, so if you need to preserve the original, make a copy first.
To use strtok (string, delims) to separate string into tokens at delims, your first call to strtok takes string as the 1st parameter. All subsequent calls use NULL in its place. You can either make an initial call to strtok and then use a while loop to complete the process, or a for loop is tailor made for handling the initial call, as well as all subsequent calls with NULL.
For example your function utilizing strtok to separate string into tokens and providing a size_t return of the number of tokens copied to ArrayOfString could be similar to:
char ArrayOfString[ROW][COL];
size_t vSeparateSringByComma (char* string)
{
const char *delims = ",\n";
char *s = string;
size_t n = 0, len;
for (s = strtok (s, delims); s && n < ROW; s = strtok (NULL, delims))
if ((len = strlen (s)) < COL)
strcpy (ArrayOfString[n++], s);
else
fprintf (stderr, "error: '%s' exceeds COL - 1 chars.\n", s);
return n;
}
(note: how your array bounds are protected both by the check with n < ROW and each row array bound is protected with (len = strlen (s)) < COL before the copy to ArrayOfString[n++] is made)
(also note: how by not using magic numbers, if you change the ROW or COL size in the future, only the constants need changing and the change is automatically incorporated throughout your code by virtue of using constants)
Your example program would then be:
int main(void) {
char string[] = "$,0,3,307,183,18,5,119,1,#";
size_t n = vSeparateSringByComma (string);
for (size_t i = 0; i < n; i++)
printf ("ArrayOfString[%zu] : '%s'\n", i, ArrayOfString[i]);
}
Example Use/Output
$ ./bin/arrayofstrings
ArrayOfString[0] : '$'
ArrayOfString[1] : '0'
ArrayOfString[2] : '3'
ArrayOfString[3] : '307'
ArrayOfString[4] : '183'
ArrayOfString[5] : '18'
ArrayOfString[6] : '5'
ArrayOfString[7] : '119'
ArrayOfString[8] : '1'
ArrayOfString[9] : '#'
Using strcspn and strspn Instead of strtok
As discussed in the comments, using strcspn to report the number of sequential characters not containing a delimiter allowing you to determined the length of each field. You then need to skip over the delimiters (which in many cases can be made up of more than one delimiter (e.g. $, 0, 3, ...).
While strtok considers multiple sequential delimiters a single delimiter, you would need a similar way to skip over the intervening delimiters to position your self to read the next field. strspn will work nicely using the same delims, but this time reporting the number of characters made up of only characters within delims (allowing you to add that to your len and then len to s to position yourself for the next read)
A short variation using strcspn and strspn could be:
size_t vSeperateSringByComma (char* string)
{
const char *delims = ",\n";
char *s = string;
size_t n = 0, len;
while ((len = strcspn (s, delims))) { /* number of non-delim chars */
if (len < COL) { /* validate it will fit */
memcpy (ArrayOfString[n], s, len); /* copy len chars */
ArrayOfString[n++][len] = 0; /* nul terminate at len */
}
else
fprintf (stderr, "error: '%s' exceeds COL - 1 chars.\n", s);
len += strspn (s + len, delims); /* scan past delimiter(s) */
s += len; /* update s to beginning of next field */
}
return n;
}
(the output is the same)
Look things over and let me know if you have further questions.
replace
printf("%.*s\n", (int)field_len, s);
with
sprintf(ArrayOfString[i],"%.*s\n", (int)field_len, s);
then you can print the 4 first elements with
for( i=0 ; i<4 ; i++)
printf("%s" , ArrayOfString[i] );
sizeof(char)by definition is 1.tmp += l + 1;would be as good.I don't see a need to special case
l == 0.You don't have to initialize
lin a loop header: it is immediately reassigned.gcccomplains about precision specifier inprintf("\"%.*s\"\n", l, tmp)beingsize_t; unfortunately, cast is unavoidable.I don't see a need for 2 separate loops. A single
char * tmp = (char *)str; do { int l = strcspn (tmp, tok); printf("\"%.*s\"\n", l, tmp); tmp += l + 1; } while (tmp[-1]); return 0;works equally well.
Solution
As @vnp noted, the "correct" solution is much simpler. I would make a few changes and write it as:
#include <stdio.h>
#include <string.h>
int main() {
const char string[] = "comma separated,input,,,some fields,,empty";
const char delims[] = ",";
const char *s = string;
do {
size_t field_len = strcspn(s, delims);
printf("\"%.*s\"\n", (int)field_len, s);
s += field_len;
} while (*s++);
}
Notable changes include:
- Friendlier variable names
- Don't cast away the
const - Ensure that
printf()gets anintfor the field width specifier - Smarter loop termination test (check for the NUL terminator then increment the pointer)
Nasty loop
Your original solution contains a loop that is particularly convoluted:
char * tmp = (char *)str; size_t count; for (count=0; tmp[count]; tmp[count] == tok[0] ? count++ : * tmp++) { //Empty loop body. } tmp = (char *)str;
As discussed previously,
- This loop, whose goal is to set
countto the number of commas, turns out to be completely unnecessary. - Casting away
constis bad.
In addition,
The loop manipulates both
countandtmp, which makes it very confusing. When the loop terminates,tmppoints tocountbytes before the end of the string. That's just weird!The non-weird version would be:
int count = 0; for (const char *tmp = str; *tmp; tmp++) { if (*tmp == tok[0]) count++; }Note the very conventional loop header: start at the beginning of
str, walk one byte at a time until NUL is reached. Also,tmpis truly temporary, and falls out of scope after the loop, so you don't have to worry about resetting it. The loop body is straightforward as well: incrementcountfor each comma.* tmp++is a superfluous pointer dereference that just adds confusion and noise.