C String into array - c

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.

Related

Returning the rest of a string in c after the first white space

I'm writing a program to return a the rest of a string after the first white space.
"I had a bad day"
should return
"had a bad day"
This is what I have so far
char* next_word(char* str){
char s[100];
int index = 0;
int i = 0;
int counter = 0;
for(i = 0; i < strlen(str); i++){
if(str[i] == ' '){
index = i+1;
for(index; index < strlen(str); index++){
s[counter] = str[index];
counter = counter + 1;
}
s[index] = '\0';
return s;
}
}
return index;
}
I'm looping through the char* str and finding the index of the first empty space then from there I've made another loop to print out the rest of the string starting at index + 1. For some reason when I writes s[counter] = str[index], I don't believe that its copying the char from str to s.
When I try to return s after the loop I don't get anything. Is it possible to add char to the empty char s[100] then return the full string as s?
Thank You
Your next_word() function is returning a local (to the function) variable which results in a undefined behavior. You must take s (in your case) as input or malloc a character buffer in the function. Then you can do the copying. I prefer you go for the first alternative and do not forget to check the length of the input string, so that you do not cross the size while copying.
Also, the next_word() returns index when no space found? That is clearly a mistake and your code will fail to compile.
For the code, you can just break from the first loop whenever you find the first space and from there you can continue with copying.
You should not return s as it is a local variable on the stack. You could simply return a pointer into the str argument since str remains valid at the time of return.
#include <string.h>
const char* TheString = "I had a bad day";
const char* stringAfterBlank(const char* str)
{
const char* blank = strchr(str, ' ');
if (blank != NULL)
{
return ++blank;
}
return "";
}
void main(int argc, char** argv)
{
const char* restOfTheString = stringAfterBlank(TheString);
// restOfTheString is "had a bad day" pointing into TheString
}
If you need a copy of the string then you can use strdup. If you do then don't forget to free.
You shouldn't return your local variable. The easiest way to accomplish what you want is operating on pointers.
There is solution using only stdio.h, as you wanted:
#include <stdio.h>
char* next_word(char* str);
int main()
{
char* arg = "I had a bad day!";
//Print every "next_word"
char* words = arg;
do{
printf("%s\n", words);
} while(words = next_word(words));
}
char* next_word(char* str)
{
while(*str != '\0'){
if(*str++ == ' ')
return str;
}
return NULL;
}

freeing malloc'd memory causes other malloc'd memory to garbage

I'm trying to learn C, and one of the things I'm finding tricky is strings and manipulating them. I think I understand the basics of it, but I've taken for granted a lot of what might go into strings in JS or PHP (where I'm coming from).
I'm trying now to write a function that explodes a string into an array, based on a delimiter, using strtok. Similar to PHP's implementation of explode().
Here's the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char **explode(char *input, char delimiter) {
char **output;
char *token;
char *string = malloc(sizeof(char) * strlen(input));
char delimiter_str[2] = {delimiter, '\0'};
int i;
int delim_count = 0;
for (i = 0; i < strlen(input); i++) {
string[i] = input[i];
if (input[i] == delimiter) {
delim_count++;
}
}
string[strlen(input)] = '\0';
output = malloc(sizeof(char *) * (delim_count + 1));
token = strtok(string, delimiter_str);
i = 0;
while (token != NULL) {
output[i] = token;
token = strtok(NULL, delimiter_str);
i++;
}
// if i uncomment this line, output gets all messed up
// free(string);
return output;
}
int main() {
char **row = explode("id,username,password", ',');
int i;
for (i = 0; i < 3; i++) {
printf("%s\n", row[i]);
}
free(row);
return 0;
}
The question I have is why if I try to free(string) in the function, the output gets messed up, and if I'm doing this incorrectly in the first place. I believe I'm just not mapping out the memory properly in my head and that's why I'm not understanding the issue.
you misunderstand what strtok does, It does not make new strings, it is simply returning a pointer to different parts of the original string. If you then free that string all the pointers you stored become invalid. I think you need
while (token != NULL) {
output[i] = strdup(token);
token = strtok(NULL, delimiter_str);
i++;
}
strdup will allocated and copy a new string for you
In output you save pointers that points into string so when you free string, you free the memory that the output pointers are pointing to.
It's not enough to save the pointers. You'll have to copy the actual strings. To do that you need to allocate memory to output in another way.

Separating two values in a char and assigning them to varables

New to C and Arduino programming, my issue, how to split char c into two separate integer variables? char c's value looks like this 140,100, both numbers are integers. I need to create two integer variables, SpeedX and SpeedY from this data so that SpeedX = 140 and SpeedY = 100. Thanks for your help!
how to split char c into two separate integer variables?
First of all, what you have is a string, not a char.
You can use the strtok() function to split a string (and specify the delimiter to use), like this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char nums[] = "140,100";
char *str;
int num;
int SpeedX, SpeedY, i = 0;
str = strtok (nums, ",");
while (str != NULL)
{
num = atoi(str);
if (i == 0)
SpeedX = num;
else if (i == 1)
SpeedY = num;
str = strtok (NULL, ",");
i++;
}
return 0;
}
NOTE : If, generally speaking about such a problem to solve in c and not in arduino, you do not know for sure that you will have only two elements in nums, you should use dynamic memory allocation (read more about it here), and modify your code like this :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char nums[] = "140,100,500";
char *str;
int num;
int len, i = 0;
int *p;
str = strtok (nums, ",");
len = strlen(str);
p = malloc((len-1)*sizeof(int));
while (str != NULL)
{
num = atoi(str);
*(p+i) = num;
i++;
str = strtok (NULL, ",");
}
for (i = 0; i < len-1; i++)
printf("%d\n", *(p+i));
return 0;
}
The char you are talking about is most likely string or char array, which is really a pointer to a number of chars. A char can only store 1 character.
The function strtol defined in stdlib.h takes three arguments:
A char pointer to the beginning of your string (or the place you want to start looking
A pointer to a char pointer that will be updated to point to the first char after the end of the number
The base the number is represented in, most likely 10 in your case
Your data type is probably char* or char[50], because char can only represent one character, not a sequence of characters like "140,100".
Anyway, use sscanf, which scans a string and extracts values according to a given format:
char *myNums = "140,100";
int first,second;
int elementsRead = sscanf(myNums,"%d,%d", &first, &second);
// note: elementsRead is `2` if both format specifiers `%d` and `%d` have been scanned successfully

How to set index of char pointer array to a char pointer?

I'm tokenizing by commas, which gives me char * as an output in a while loop. How do I assign each of these char pointers in the while loop to the index of a char pointer []?
Pseudocode:
char * p;
char * args[30];
int i = 0;
while(p!=NULL){
p = strtok(NULL,",");
args[i] = p; //attempt 1
*(args + i) = p; //attempt 2
strcpy(p,args[i]); //attempt 3
i++;
}
Error:
I print out the value of p and after printing index 0, it fails. Here is my code for printing it out:
for(int j=0; j<i; j++){
printf("%s \n",args[j]);
}
Here is my error:
"0 g" when my input is "g m n" and it prints out
Segmentation fault: 11.
Your program is mostly correct, but I think your problem is that you're using strtok() incorrectly. Upon its first call, strtok() expects a string and delimiters. Subsequent calls expect NULL and delimiters.
I modified your C "pseudo-code" to a working program.
#include <stdio.h>
#include <string.h>
void main(int argc, char* argv[]) {
char* p;
char* args[30];
int i = 0;
int j;
char input[30];
puts("Please enter a string:");
scanf("%29s", &input); /* get a string to break up */
p = args[i++] = strtok(input, ","); /* first call to strtok() requires the input */
while(p!=NULL && i < 30) { /* added bounds check to avoid buffer overruns */
p = strtok(NULL,","); /* subsequent calls expect NULL */
args[i] = p; /* this is the best way to assign values to args, but it's equivalent to your attempt 2*/
i++;
}
for(j = 0; j < i; j++){
printf("%s \n",args[j]);
}
}
Edit: I just realized that my original code used an uninitialized pointer p. This is undefined behavior, and I have corrected the code.

C prints first character of the array only, does not print the rest?

Basically I have to tokenise a 4 column line and put those tokens into an array, and so I made this function below.
char** tokeniser(char* lineToToken)
{
int i = 0;
char** tokenList = malloc(4*sizeof(char*));
char* token;
while ((token = strtok(lineToToken, " ")) != NULL && i<4)
{
tokenList[i] = malloc(strlen(token) + 1);
strcpy(tokenList[i], token);
++i;
}
return tokenList;
}
and in the main I have this simple thing to test it, and only get first element printed 4 times..
for(int i = 0; i<3; i++)
{
printf("%s", tokenList[i]);
}
the text file that I put this through is
"asda asdasd 23 asd", but I only get asda 4 times :S
The issue is in your usage of strtok(). The documentation from cplusplus.com says it best:
On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning
In summary, you are passing the string to be tokenized over and over, rather than passing it the first time only (and NULL subsequent times)
So, the following program might give you the example that you need:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char** tokeniser(char* lineToToken)
{
int i = 0;
char** tokenList = (char**) malloc(4 * sizeof(char*));
char* token = strtok(lineToToken, " ");
while(token != NULL && i < 4)
{
tokenList[i] = (char*) malloc(strlen(token) + 1);
strcpy(tokenList[i], token);
token = strtok(NULL, " ");
++i;
}
return tokenList;
}
int main(int argc, char const* argv[])
{
char str[] = "asda asdasd 23 asd";
char** tokenList = tokeniser(str);
for(int i = 0; i < 4; ++i)
{
printf("%s\n", tokenList[i]);
}
return 0;
}
On my machine this prints:
asda
asdasd
23
asd
In the above function every time Strtok function you are passing the start address of the same string.
Generally strtok function should be called in the following manner.
#include<stdio.h>
#include<string.h>
void main() {
char Src[25]="Hare Krishna Hare Rama";
char C[2]=" ";
char *del=C;
char *temp[5];
int i=0;
temp[i] = strtok(Src,del);
while(temp[i] !=NULL) {
printf("The str is <%s\n>",temp[i]);
temp[++i] = strtok(NULL,del);
}
}
When you are calling first time you have to pass the start address of the string and delimiter.
Then strtok returns start pointer which point to the delimiter.So next time when you call you no need to pass the start address of the string, strtok will remembers the address which point to next character of the delimiter.So Subsequent calls should be called with NULL pointer.

Resources