Splitting strings in C strtok() - c

I want to split strings received from the terminal input, if they are contained on a buffer. If they are I want to print them.
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* fich[5]={"ha","he","hi","ho","hu"};
int main(){
char passaarg[70];
const char space[2]= " ";
char *token;
int i;
while(1){
read(STDIN_FILENO, passaarg, 70);
for (i = 0; i < 5; i++){
if(strncmp(passaarg, fich[i], 2) == 0){
token = strtok(passaarg, space);
while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, space);
printf("%s\n", token);
}
break;
}
}
}
return 0;
}
My output is the following one:
ha he
ha
he
he
Segmentation fault (core dumped)

I suspect your problem is here:
token = strtok(passaarg, space);
while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, space);
printf("%s\n", token);
}
That second printf will cause undefined behavior (likely a crash) when strtok returns NULL, as it will when there are no more tokens in the string. Just remove that line.
Stylistically, I'd use a for loop here:
for(token = strtok(passaarg, space); token != NULL; token = strtok(NULL, space)) {
printf("%s\n", token);
}

while(token != NULL){
printf("%s\n", token);
token = strtok(NULL, space);
}
The while loop will fail when the token is NULL. At this time you are trying to print this pointer using your second printf() in the while loop which will lead to undefined behavior.
Get rid of your second printf()

Related

How can I add a string to an array of strings in C?

I have a string "token" and an empty array of strings "arr". I want to add token to the first index of arr. I've tried arr[0][0] = token, but this would only work for chars and I've also tried arr[0] = token but this throws the error "expression must be a modifiable lvalue". My full program is:
#include <stdio.h>
#include <string.h>
char arr[100][100] = {};
char *token = strtok(StringToBeSplit, " ");
int i = 0;
while(token != NULL) {
arr[0] = token;
printf("%s\n", token);
token = strtok(NULL, " ");
i++;
}
What should I do?
You need to avoid assigning string literal to strtok. Basically using strcpy to copy the token to array and increment array as advised by previous answer. Something like this:-
#include <stdio.h>
#include <string.h>
int main(){
char arr[100][100] = {};
char str[] = "Split this string";
char sep[] = " ";
char *token = strtok(str, sep);
int i = 0;
while(token != NULL){
strcpy(arr[i], token);
token = strtok(NULL, sep);
i++;
}
//Test If it can print the strings
for(int j = 0; j < i; j++)
printf("%s\n", arr[j]);
}

Error when reading strings from CSV (Core Dumped)

I keep getting the same error, I'm new to programming so I'm not so sure if the Syntax is correct.
Every time I run it, it returns Segmentation Fault(core dumped), I'm not even sure If I can open a file with a string (address) instead of the filename in extense.
Also the files I'm reading from are CSV but in txt format.
I'm using C99
#define BUFFER_SIZE 1024
#define TAM_PERGUNTAS 128
struct question{
char category[TAM_PERGUNTAS];
char question[TAM_PERGUNTAS];
char option1[TAM_PERGUNTAS];
char option2[TAM_PERGUNTAS];
char option3[TAM_PERGUNTAS];
char correct[TAM_PERGUNTAS];
};
struct question vec_question[BUFFER_SIZE];
void questions() {
FILE *perguntas;
int numaleat=0;
int num_questions, counter = 0, index, temp_randomizer=0;
char line[BUFFER_SIZE];
char answer[32];
char address[TAM_PERGUNTAS];
address[0] = '\0';
srand(time(NULL));
printf("Digite agora o numero de perguntas desejadas.(MAX 20) : "); //Insert Number of questions
scanf("%d", &num_questions);
printf("\n");
for (counter = 0; counter < num_questions; counter++) {
temp_randomizer = rand() % j; //j Represents the number o CATEGORIES at play and acts as a marker in the SELECTION string
sprintf(address, "%s.txt", SELECTION[temp_randomizer]);
perguntas = fopen(address, "r");
if (perguntas == NULL) {
printf("ERROR OPENING FILE!");
}
index = 0;
while (fgets(line, sizeof(line), perguntas) != NULL) {
strcpy(vec_question[index].category, strtok(line, ";"));
strcpy(vec_question[index].question, strtok(NULL, ";"));
strcpy(vec_question[index].option1, strtok(NULL, ";"));
strcpy(vec_question[index].option2, strtok(NULL, ";"));
strcpy(vec_question[index].option3, strtok(NULL, ";"));
strcpy(vec_question[index].correct, strtok(NULL, ";"));
vec_question[index].correct[strlen(vec_question[index].correct) - 1] = '\0';
index++;
}
fclose(perguntas);
index = 20;
numaleat = rand() % index;
printf("%s : %s\n%s\n%s\n%s",vec_question[numaleat].category,vec_question[numaleat].question,vec_question[numaleat].option1,vec_question[numaleat].option2,vec_question[numaleat].option3);
for (int i = 0; i < num_users; i++) {
printf("\n%s: ", &users[i][20]);
scanf("%s", &answer[32]);
if (answer == vec_question[numaleat].correct)
userspoints[i] += 1;
}
}
}
In general one should assume that functions like strtok can fail.
Sometimes it fails and returns a NULL value. A short record in your input is a likely cause.
Consider using it with a loop, and breaking out of the loop once strtok returns NULL.
I found a simple example here.
#include <string.h>
#include <stdio.h>
int main () {
char str[80] = "This is - www.tutorialspoint.com - website";
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);
}
return(0);
}
Note that it does one strtok to get the first token. That might return NULL in which case the loop doesn't run. If it doesn't return NULL then it prints that token, and asks strtok for the next token. It keeps doing that until strtok returns NULL.

strtok() tokenizes only once when nested

Suppose I have the following string: 0:1,2,3.
I want to separate first using : as the delimiter and when it gets to the second part (i.e 1,2,3) and try to use strtok on that (with ,) it does not work as expected.
#include <stdio.h>
#include <stdbool.h>
int main(void){
char s[10];
strcpy(s, "0:1,2,3");
char* token1 = strtok(s, ":");
//To let me know it is on the second part
bool isSecondToken = false;
while (token1) {
printf("token1: %s\n", token1);
if(isSecondToken == true){
char* token2 = strtok(token1, ",");
while (token2) {
printf("token2: %s\n", token2);
token2 = strtok(NULL, " ");
}
}
token1 = strtok(NULL, " ");
isSecondToken = true;
}
}
Output I get:
token1: 0
token1: 1,2,3
token2: 1
token2: 2,3
Expected output:
token1: 0
token1: 1,2,3
token2: 1
token2: 2
token2: 3
When updating the token1 and token2 pointers you need to use the same token splitter:
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int main(void){
char s[10];
strcpy(s, "0:1,2,3");
char* token1 = strtok(s, ":");
//To let me know it is on the second part
bool isSecondToken = false;
while (token1) {
printf("token1: %s\n", token1);
if(isSecondToken == true){
char* token2 = strtok(token1, ",");
while (token2) {
printf("token2: %s\n", token2);
token2 = strtok(NULL, ",");
}
}
token1 = strtok(NULL, ":");
isSecondToken = true;
}
}
Also strcpy requires the string.h library, so you were probably also getting some warnings of implicit declaration.

Getting Segmentation fault (core dumped)

So i am trying to read lines and then split them in two with strtok . So if i would read "nice dog" it will first print what i read and then will print using the strtok commands "nice" and "dog" on the next line . But after second input i got Segmentation fault .Also , what does free(buf) do ? I've seen that the error is at this line : "strcpy(name, strtok(NULL, " "));" This is the code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *buf;
char command[32];
char name[32];
while((buf = readline("\n"))!=NULL)
{
if (strcmp(buf,"exit")==0)
break;
printf("%s\n",buf);
strcpy(command, strtok(buf, " "));
printf("%s\n", command);
strcpy(name, strtok(NULL, " "));
printf("%s\n", name);
if(buf[0]!=NULL)
add_history(buf);
}
free(buf);
return 0;
}
You must check the result of strtok if it's NULL meaning that no tokens where found you will get segmentation fault
char *pointer;
pointer = strtok(buf, " ");
if (pointer != NULL)
strcpy(command, pointer);
also, readline allocates new memory on every call so you should free inside the while loop.
Fix it this way
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#include <readline/history.h>
int main()
{
char *buf;
char command[32];
char name[32];
while((buf = readline("\n"))!=NULL)
{
char *pointer;
if (strcmp(buf,"exit")==0)
break;
printf("%s\n",buf);
pointer = strtok(buf, " ");
if (pointer != NULL)
{
strcpy(command, pointer);
/* Don't print poitner otherwise since it is unintialized */
printf("%s\n", pointer);
}
/* subsequent calls to strtok must have first argument NULL */
pointer = strtok(NULL, " ");
if (pointer != NULL)
{
strcpy(name, pointer);
printf("%s\n", pointer);
}
if (buf != NULL) // this is never FALSE because of the while condition
add_history(buf);
free(buf);
}
return 0;
}
you also have to make sure that command and name will be big enough to fit the resulting stirng.

Seg fault using strtok to parse stdin to an array

I'm getting a seg fault every time the code reaches the first strtok
token = strtok(commandLine," ");
I'm just trying to parse stdin and store it, using a space as a delimiter. A lot of problems I saw were people using strtok on a string literal, which I assume also applies to my case as well, but how do I work around that?
Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
int main(int argc, char* argv[]){
//Used for parsing
char commandLine[255];
char* tokens[10];
char* token;
int counter;
int i;
printf("gets to pt 1\n");
//Parsing
while( fgets(commandLine, 255, stdin) ){
printf("\n%s\n", commandLine);
token = strtok(commandLine," ");
printf("gets here");
counter = 0;
for(counter = 0; token != NULL; counter++){
strcpy(tokens[counter], token);
token = strtok(NULL, " ");
}
}
printf("gets to point2");
for(i = 0; tokens[i] != NULL; i++){
printf("%s ", tokens[i]);
}
EDIT:
Here is the working code.
As User93353 pointed out, I had to allocate memory for my tokens so I changed
char* tokens[10]
to
char tokens[10][100]
and my for loop wasn't ending correctly, had to change
tokens[i] != NULL
to
i<counter
-
int main(int argc, char* argv[]){
//Used for parsing
char commandLine[255];
char tokens[10][100];
char* token;
int counter;
int i;
printf("gets to pt 1\n");
//Parsing
while( fgets(commandLine, 255, stdin) ){
printf("\n%s\n", commandLine);
token = strtok(commandLine," ");
printf("gets here");
for(counter = 0; token != NULL; counter++){
strcpy(tokens[counter], token);
token = strtok(NULL, " ");
}
printf("gets to printing");
for(i = 0; i<counter; i++){
printf("%s", tokens[i]);
}
}
}
Allocate memory for each element of the tokens array.
Easy way is to declare it as
#define SOME_SIZE 100
char tokens[10][SOME_SIZE];
Otherwise, tokens[0], tokens[1] etc point to some random location in memory. strcpying to that random location is causing your program to crash.

Resources