I am trying to take user input: (1 345 44 23) and make it into a tokenized char string then into ints. Surprisingly I could not find much help for what I would think would be a common task.
Any ideas how to convert the char string into an in string using tokens?
My program crashes when it gets to the conversion (after the tokenization [I realize this is not a word]).
Thanks!
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define StrSZE 81
void strInput (char str[], int maxChars);
void custatoi(char * tokenArray[], int * data, int numOfTok);
int main(int argc, char *argv[])
{
char str[StrSZE];
char* tokenArray;
int maxChars=StrSZE-1, cont=1, numOfToken=0, i=0;
int* data;
strInput(str, maxChars);
tokenArray = strtok(str, " \t");
while (tokenArray)
{
printf("token: %s\n", tokenArray);
tokenArray = strtok(NULL, " \t");
numOfToken++;
}
data = (int *) malloc(numOfToken * sizeof(int));
custatoi(tokenArray, data, numOfToken);
system("PAUSE");
return 0;
}
void strInput (char str[], int maxChars)
{
char garbage;
int k=0;
str[0]='\0';
printf("Please type a string of whole numbers (intigers).\n\n");
while ((k<80) && ((str[k] = getchar()) != '\n'))
k++;
/* Clears the keyboard buffer. */
if (k==80)
while((garbage = getchar()) != '\n')
;
/* Place null at the end of the line read in from user */
str[k]='\0';
printf("str after input is: %s\n\n", str);
}
void custatoi(char * tokenArray[], int * data, int numOfTok)
{
int i;
for (i=0; i < numOfTok; i++)
data[i] = atoi(tokenArray[i]);
}
I corrected the errors in yours code: There was some mistakes in main(), tokenArray data type was not correct.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define StrSZE 81
void strInput (char str[], int maxChars);
void custatoi(char* tokenArray[], int * data, int numOfTok);
int main(int argc, char *argv[])
{
char str[StrSZE];
int maxChars=StrSZE-1, cont=1, numOfToken=0, i=0;
int* data;
char* tokenArray[50]; // Declared correctly
strInput(str, maxChars);
tokenArray[i] = strtok(str, " \t"); // Also made a change here!
while (tokenArray[i])
{
printf("token: %s\n", tokenArray[i]);
i++;
tokenArray[i] = strtok(NULL, " \t");
numOfToken++;
}
data = (int *) malloc(numOfToken * sizeof(int));
custatoi(tokenArray, data, numOfToken);
printf("data\n");
for(i=0;i<numOfToken;i++){
printf(" %d\n",data[i]);
}
system("PAUSE");
return 0;
}
void strInput (char str[], int maxChars)
{
char garbage;
int k=0;
str[0]='\0';
printf("Please type a string of whole numbers (intigers).\n\n");
while ((k<80) && ((str[k] = getchar()) != '\n'))
k++;
/* Clears the keyboard buffer. */
if (k==80)
while((garbage = getchar()) != '\n')
;
/* Place null at the end of the line read in from user */
str[k]='\0';
printf("str after input is: %s\n\n", str);
}
void custatoi(char* tokenArray[], int * data, int numOfTok)
{
int i;
for (i=0; i < numOfTok; i++)
data[i] = atoi(tokenArray[i]);
}
At the end of the strtok loop, tokenArray will be set to NULL. You then pass it to custatoi, which presumably crashes when it tries to dereference it.
Note that tokenArray is not an array of strings; it's just a single string pointer (or a pointer to an array of characters). If you want to accumulate the tokens into an array, you'll have to create a separate array for that purpose.
The main problem is that custatoi() expects to work with an array of pointers to char, while tokenArray in main() is a mere pointer to char. The original code never collects all pointers to tokens in the input string into an array that custatoi() expects, there isn't such an array in the original code.
Please study the fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#define StrSZE 81
void custatoi(char* tokenArray[], int* data, int numOfTok);
int main(void)
{
char str[StrSZE];
char** tokenArray;
int numOfToken = 0, i;
int* data;
//strInput(str, maxChars);
strcpy(str, "1 345 44 23");
tokenArray = malloc(sizeof(char*));
tokenArray[numOfToken] = strtok(str, " \t");
while (tokenArray[numOfToken] != NULL)
{
printf("token: %s\n", tokenArray[numOfToken]);
numOfToken++;
tokenArray = realloc(tokenArray, sizeof(char*) * (numOfToken + 1));
tokenArray[numOfToken] = strtok(NULL, " \t");
}
data = malloc(numOfToken * sizeof(int));
custatoi(tokenArray, data, numOfToken);
for (i = 0; i < numOfToken; i++)
printf("data[%d]=%d\n", i, data[i]);
return 0;
}
void custatoi(char* tokenArray[], int* data, int numOfTok)
{
int i;
for (i=0; i < numOfTok; i++)
data[i] = atoi(tokenArray[i]);
}
Output (idone):
token: 1
token: 345
token: 44
token: 23
data[0]=1
data[1]=345
data[2]=44
data[3]=23
Related
I'm doing an exercice where I need to split a string into an array of strings. The number of delimiters is checked before (the code snippet posted is a stripped down version however it doesn't work too), then the string is transformed into lowercase and it gets split into 4 parts separated by the delimiter "-". Here's the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_USERNAME_LENGHT 256
#define NUMBER_OF_ELEMENTS 4
void StringToArrayOfStrings(char *string, char **string_array, char *delimiter);
void LowerString(char * string, int string_lenght);
int main() {
char string[MAX_USERNAME_LENGHT] = "Joseph-Lucy-Mike-Nick"; //Test string
char *string_array[NUMBER_OF_ELEMENTS]; //We need four elements
char delimiter[] = "-";
int counter = 0;
//LowerString(string, strlen(string));
//printf("%s", string);
StringToArrayOfStrings(string, string_array, delimiter);
//Print each element of the string array
for (counter = 0; counter < NUMBER_OF_ELEMENTS; counter++) {
printf("\n%s\n", string_array[counter]);
}
return 0;
}
void LowerString(char * string, int string_lenght) {
unsigned short int counter;
for (counter = 0; counter < string_lenght; counter++) {
string[counter] = tolower(string[counter]);
}
}
void StringToArrayOfStrings(char *string, char **string_array, char *delimiter) {
unsigned short int counter;
char *token;
token = strtok(string, delimiter);
while(token != NULL) {
string_array[counter++] = token;
token = strtok(NULL, delimiter);
}
}
I've been scratching my head for the past 2 hours and I wasn't able to fix it. This programs works only if the string is not printed or/and transformed in lowercase. The program crashes when entering the loop in StringToArrayOfStrings. Where's the problem?
Thanks.
I have a char array in C with numbers separated by comma, and need to convert it to an int array. However when I try to use strtok, it crashes with EXC_BAD_ACCESS.
Can you help me please?
The method
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ARRAY_LEN (0x100)
#define OUTPUT_LEN (0x400)
unsigned int StaticAnalyze_load( char* data, char delimiter, int* array, unsigned int length ){
char *token;
int i=0;
// CRASHES HERE (BAD ACCESS)
token = strtok(data, &delimiter);
while( token != NULL ) {
array[i] = atoi(token);
token = strtok(NULL, &delimiter);
i++;
}
for(i=0;i<3;i++) {
printf("%d\n", array[i]);
}
return length;
}
Main
int main(int argc, const char * argv[]) {
char *data = "13,654,24,48,1,79,14456,-13,654,13,46,465,0,65,16,54,1,67,4,6,74,165,"
"4,-654,616,51,654,1,654,654,-61,654647,67,13,45,1,54,2,15,15,47,1,54";
int array[ARRAY_LEN]; // array, I need to fill-in with integers from the string above
unsigned int loaded = StaticAnalyze_load(data, ',', array, ARRAY_LEN);
return 0;
}
data in main is a pointer to a literal string that strtok cannot modify.
strchr could be used to identify the tokens.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ARRAY_LEN (0x100)
#define OUTPUT_LEN (0x400)
unsigned int StaticAnalyze_load( char* data, char delimiter, int* array, unsigned int length ){
char *token = data;
int i=0;
while( i < ARRAY_LEN && token != NULL ) {
array[i] = atoi(token);
token = strchr(token, delimiter);
if ( token) {
++token;
}
i++;
}
for(i=0;i<3;i++) {
printf("%d\n", array[i]);
}
return length;
}
int main(int argc, const char * argv[]) {
char *data = "13,654,24,48,1,79,14456,-13,654,13,46,465,0,65,16,54,1,67,4,6,74,165,"
"4,-654,616,51,654,1,654,654,-61,654647,67,13,45,1,54,2,15,15,47,1,54";
int array[ARRAY_LEN]; // array, I need to fill-in with integers from the string above
unsigned int loaded = StaticAnalyze_load(data, ',', array, ARRAY_LEN);
return 0;
}
Here's my code:
#include <stdio.h>
#include <string.h>
char input_buffer[1000];
void get_substring(){
int i;
int length;
printf("Please enter a string:\n");
scanf("%[^\n]s", input_buffer);
printf("Index of first character of substring:\n");
scanf("%d", &i);
printf("Length of substring:\n");
scanf("%d", &length);
printf("Substring is %.*s ", length, input_buffer + i);
}
int main(void) {
// your code goes here
//get_substring(0,4);
get_substring();
return 0;
}
That's my current code, I want to return a pointer of the input, instead of just displaying the substring. Sorry for the confusion everyone.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getSubstring(char* str,size_t start, size_t length)
{
// determine that we are not out of bounds
if(start + length > strlen(str))
return NULL;
// reserve enough space for the substring
char *subString = malloc(sizeof(char) * length);
// copy data from source string to the destination by incremting the
// position as much as start is giving us
strncpy(subString, str + start, length);
// return the string
return subString;
}
int main(int argc, char* argv[])
{
char *str = "Hallo Welt!";
char *subStr = getSubstring(str,0,20);
if(subStr != NULL)
{
printf("%s\n",subStr);
free(subStr);
}
}
This solution should give you a hint how you would start with such a problem.
I'm trying to pass information from a char string that's been
tokenized using " ." as the set.
Turn those characters into integers using atoi()
Then send the values into dynamically allocated memory
I know the theory, I know how it's supposed to work, but I can't get the right syntax to make it work!
The second part, after I declare *Malloc_Array_ptr* is where I run into trouble.
So far, I've used the Malloc Pointer exactly how I'd use a regular array pointer, and I'm not getting any results on my printf test.
Can't find info that makes sense to me over google, I'm going crazy over this. I think I'm real close to figuring it out, I just need a nudge in the right direction >.<
Thank you! :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
#define MIN_SIZE 2
void StrInput(char str[], int maxChars);
int main(int argc, char *argv[])
{
char Array[SIZE], *Array_ptr = strtok(Array, " .");
StrInput(Array, SIZE);
int i=1, *temp = Array_ptr;
//Strok initialized in order to use NULL next sequence.
//Temp stores the pointer in it's original form, before it gets butchered by strtok
while (Array_ptr != NULL)
{
Array_ptr = strtok(NULL, " .");
i++;
}
//Above code finds the number of tokens strtok worked on, and stores it as i.
//Dynamically Creates the array which can hold exactly the amount of tokens (i)
int *Malloc_Array_ptr = (int*)malloc(i* sizeof(int)), hold;
i=0;
while (Array_ptr != NULL)
{
temp = strtok(NULL, " .");
hold = atoi(temp);
Malloc_Array_ptr[i] = hold;
i++;
}
printf("Show me the money: %s \n", Malloc_Array_ptr);
system("PAUSE");
return 0;
}
/*----------------------------------------------------------------------*/
void StrInput(char str[], int maxChars)
{
int i=0, str_lenght;
while ((str[i] = getchar()) != '\n')
i++;
str[i+1]='\0';
if (i>maxChars || i<MIN_SIZE)
{
printf("Your sumbition dosn't fit the size criteria.\n");
printf("Please reenter:\n\n");
StrInput(str, maxChars);
}
}
This is problematic:
char Array[SIZE], *Array_ptr = strtok(Array, " .");
You are declaring the array, then trying to use strtok on the uninitialized array. You probably meant to do this:
char Array[SIZE], *Array_ptr = 0;
StrInput(Array, SIZE);
Array_ptr = strtok(Array, " .");
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 10
#define MIN_SIZE 2
void StrInput(char str[], int maxChars);
int main(int argc, char *argv[]){
char Array[SIZE], *Array_ptr, *strwk;
StrInput(Array, SIZE);
int i=0;
strwk=strdup(Array);//strtok would change the string. so make a copy.
Array_ptr=strtok(strwk, " .");
while (Array_ptr != NULL){
++i;//countup element
Array_ptr = strtok(NULL, " .");
}
int *Malloc_Array_ptr = (int*)malloc(i* sizeof(int));
i=0;
strcpy(strwk, Array);
Array_ptr = strtok(strwk, " .");
while (Array_ptr != NULL){
Malloc_Array_ptr[i] = atoi(Array_ptr);
++i;
Array_ptr = strtok(NULL, " .");
}
free(strwk);
int j;
//check print
for(j=0;j<i;++j)
printf("%d ", Malloc_Array_ptr[j]);
printf("\n");
// printf("Show me the money: %s \n", Malloc_Array_ptr);//Malloc_Array_ptr isn't (char*).
system("PAUSE");
return 0;
}
/*----------------------------------------------------------------------*/
void StrInput(char str[], int maxChars){
int i=0, ch;//str_lenght: unused
int InputOver = 0;
printf("input numbers :");
for(i=0;(ch = getchar()) != '\n';++i){
if(i > maxChars -1){//-1: for EOS(\0)
i = maxChars - 1;
InputOver = !InputOver;//true
break;
}
str[i]=(char)ch;
}
str[i]='\0';
if (InputOver || i<MIN_SIZE){
printf("Your sumbition dosn't fit the size criteria.\n");
printf("Please reenter:\n\n");
while('\n'!= ch){//clear input
ch = getchar();
}
StrInput(str, maxChars);
}
}
I need to use strtok to read in a first and last name and seperate it. How can I store the names where I can use them idependently in two seperate char arrays?
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="test string.";
char * test;
test = strtok (str," ");
while (test != NULL)
{
printf ("%s\n",test);
test= strtok (NULL, " ");
}
return 0;
}
Here is my take at a reasonably simple tokenize helper that
stores results in a dynamically growing array
null-terminating the array
keeps the input string safe (strtok modifies the input string, which is undefined behaviour on a literal char[], at least I think in C99)
To make the code re-entrant, use the non-standard strtok_r
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** tokenize(const char* input)
{
char* str = strdup(input);
int count = 0;
int capacity = 10;
char** result = malloc(capacity*sizeof(*result));
char* tok=strtok(str," ");
while(1)
{
if (count >= capacity)
result = realloc(result, (capacity*=2)*sizeof(*result));
result[count++] = tok? strdup(tok) : tok;
if (!tok) break;
tok=strtok(NULL," ");
}
free(str);
return result;
}
int main ()
{
char** tokens = tokenize("test string.");
char** it;
for(it=tokens; it && *it; ++it)
{
printf("%s\n", *it);
free(*it);
}
free(tokens);
return 0;
}
Here is a strtok-free reimplementation of that (uses strpbrk instead):
char** tokenize(const char* str)
{
int count = 0;
int capacity = 10;
char** result = malloc(capacity*sizeof(*result));
const char* e=str;
if (e) do
{
const char* s=e;
e=strpbrk(s," ");
if (count >= capacity)
result = realloc(result, (capacity*=2)*sizeof(*result));
result[count++] = e? strndup(s, e-s) : strdup(s);
} while (e && *(++e));
if (count >= capacity)
result = realloc(result, (capacity+=1)*sizeof(*result));
result[count++] = 0;
return result;
}
Do you need to store them separately? Two pointers into a modified char array will yield two separate perfectly usable strings.
That is we transform this:
char str[] ="test string.";
Into this:
char str[] ="test\0string.";
^ ^
| |
char *s1 ----- |
char *s2 -----------
.
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="test string.";
char *firstname = strtok(str, " ");
char *lastname = strtok(NULL, " ");
if (!lastname)
lastname = "";
printf("%s, %s\n", lastname, firstname);
return 0;
}
What about using strcpy:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_NAMES 2
int main ()
{
char str[] ="test string.";
char *names[MAX_NAMES] = { 0 };
char *test;
int i = 0;
test = strtok (str," ");
while (test != NULL && i < MAX_NAMES)
{
names[i] = malloc(strlen(test)+1);
strcpy(names[i++], test);
test = strtok (NULL, " ");
}
for(i=0; i<MAX_NAMES; ++i)
{
if(names[i])
{
puts(names[i]);
free(names[i]);
names[i] = 0;
}
}
return 0;
}
It contains much clutter to maintain a complete program and clean its resources, but the main point is to use strcpy to copy each token into its own string.
#include <stdio.h>
#include <string.h>
#include <stdlib.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++=p;
}
*array=NULL;
*len=c;
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
free(array[0]);//for text
free(sa); //for array
}
}
int main(void){
char str[] ="test string.";
char **words;
size_t len=0;
int i;
words = split(str, " \t\r\n,.", &len);
/*
for(char **wk = words; *wk ;wk++){
printf("%s\n", *wk);
}
*/
for(i = 0;i<len;++i){
printf("%s\n", words[i]);
}
free4split(words);
return 0;
}
/* result:
test
string
*/
Copy the results from strtok to a new buffer using a function such as
/*
* Returns a copy of s in freshly allocated memory.
* Exits the process if memory allocation fails.
*/
char *xstrdup(char const *s)
{
char *p = malloc(strlen(s) + 1);
if (p == NULL) {
perror("memory allocation failed");
exit(1);
}
strcpy(p, s);
return p;
}
Don't forget to free the return values when you're done with them.
IMO, you don't need (and probably don't want) to use strtok at all (as in, "for this, or much of anything else"). I think I'd use code something like this:
#include <string.h>
#include <stdlib.h>
static char *make_str(char const *begin, char const *end) {
size_t len = end-begin;
char *ret = malloc(len+1);
if (ret != NULL) {
memcpy(ret, begin, len);
ret[len]='\0';
}
return ret;
}
size_t tokenize(char *tokens[], size_t max, char const *input, char const *delims) {
int i;
char const *start=input, *end=start;
for (i=0; *start && i<max; i++) {
for ( ;NULL!=strchr(delims, *start); ++start)
;
for (end=start; *end && NULL==strchr(delims, *end); ++end)
;
tokens[i] = make_str(start, end);
start = end+1;
}
return i;
}
#ifdef TEST
#define MAX_TOKENS 10
int main() {
char *tokens[MAX_TOKENS];
int i;
size_t num = tokenize(tokens, MAX_TOKENS, "This is a longer input string ", " ");
for (i=0; i<num; i++) {
printf("|%s|\n", tokens[i]);
free(tokens[i]);
}
return 0;
}
#endif
U can do something like this too.
int main ()
{
char str[] ="test string.";
char * temp1;
char * temp2;
temp1 = strtok (str," ");
temp2 = strchr(str, ' ');
if (temp2 != NULL)
temp2++;
printf ("Splitted string :%s, %s\n" , temp1 , temp2);
return
}