Seg fault using strtok to parse stdin to an array - c

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.

Related

Strtok() problems when I call a function within the loop

The program prints all the outputs from the file I expect it to if I comment out the second line however if I re-add it the tokens reach null earlier and only 2 words from the file are printed any problems I'm missing?
printf("%s\n",texttoken);
fprintf(resultptr,"%s ",filterer(redwords,lowercase(texttoken)));
The rest of the code is below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void main(){
char *filterer(char* redwords, char* word);
char *lowercase(char *word);
FILE *redptr;
FILE *textptr;
FILE *resultptr;
char *redwords = malloc(20);
char *text = malloc(255);
char *texttoken;
char *temp;
redptr = fopen("redfile.txt", "r");
textptr = fopen("textfile.txt", "r");
resultptr = fopen("result.txt", "w");
fgets(redwords,20,redptr);
redwords = lowercase(redwords);
fgets(text,255,textptr);
texttoken = strtok(text, " ");
while(texttoken != NULL){
printf("%s\n",texttoken);
fprintf(resultptr,"%s ",filterer(redwords,lowercase(texttoken)));
texttoken = strtok(NULL, " ");
}
}
char *filterer(char *redwords, char *word){
int match = 0;
char *token;
token = strtok(redwords, ",");
while(token != NULL) {
if(strcmp(word,token)==0){
match = 1;
}
token = strtok(NULL, ",");
}
if(match == 1){
int i;
int len = strlen(word);
char modified[len+1];
modified[len] = NULL;
for(i=0; i<len; i++){
modified[i] = '*';
}
return modified;
}
return word;
}
char *lowercase(char *word){
int i;
for(i=0; i<=strlen(word); i++){
if(word[i]>=65&&word[i]<=90)
word[i]=word[i]+32;
}
return word;
}
At least these problems:
Return of invalid pointer
return modified; returns a pointer to a local array. Local arrays become invalid when the function closes.
char modified[len+1];
modified[len] = NULL;
for(i=0; i<len; i++){
modified[i] = '*';
}
return modified; // Bad
Save time: Enable all warnings
Example: warning: function returns address of local variable [-Wreturn-local-addr]
Nested use of strtok()
Both this loop and filterer() call strtok(). That nested use is no good. Only one strtok() should be active at a time.
while(texttoken != NULL){
printf("%s\n",texttoken);
fprintf(resultptr,"%s ",filterer(redwords,lowercase(texttoken)));
texttoken = strtok(NULL, " ");
}
Since filterer() is only looking for a ',', look to strchr() as a replacement.

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.

Sorting string lexicographically in c

I want to sort words of a string in lexicographical order.
For Example:
I have a string: I am Apple
Output should be: am Apple I
Problem (output):
enter the string
hello shamsh
the sorted array:
hello
It's not sorting the string and whole string is not being shown in the output, can anyone help me out here. Thanks!
Program code:
#include<stdio.h>
#include<string.h>
void main()
{
char a[25][25],t[25];
char s[200];
char * pch;
int count = 0;
int i,j ,n;
printf("enter the string\n");
gets(s);
pch = strtok (s," ,.-");
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
count=count+1;
i=0;
while(pch != NULL)
{
strcpy(a[i],pch);
pch = strtok (NULL, " ,.-");
i++;
}
for(i=0;i<count-1;i++)
{
for(j=i+1;j<count;j++)
{
if(strcmp(a[i],a[j])>0)
{
strcpy(t,a[i]);
strcpy(a[i],a[j]);
strcpy(a[j],t);
}
}
}
printf("the sorted array:\n");
for(i=0;i<count;i++)
printf("%s\n",a[i]);
}
If you try to print your string after you pch = strtok (s," ,.-"), you'll notice that your string is broken up. That's because strtok() is destructive and breaks up the string into tokens so you need to count the number of white spaces before calling strtok():
printf("enter the string\n");
gets(s);
for (i = 0;s[i] != '\0';i++)
{
if (s[i] == ' ')
count++;
}
count=count+1;
i=0;
pch = strtok (s," ,.-");
Also like Weather Vane said, don't use gets(), use fgets() instead oand remove the '\n' from end of the string afterwards. Also you can use realloc() to assign more memory to a dynamic array instead of using a static array since you wouldn't know the number of words in a string beforehand.
#include <stdlib.h>
#include<stdio.h>
#include<string.h>
void main()
{
char** a = NULL;
char t[25];
char s[512];
char * pch;
int count = 0;
int i,j ,n;
printf("enter the string\n");
if(fgets(s,512, stdin)==NULL)
{
printf("failed to read string\n");
exit(-1);
}
/*remove '\n' from end of the string*/
char *pos;
if ((pos=strchr(s, '\n')) != NULL)
*pos = '\0';
pch = strtok(s, " ,.-");
while(pch)
{
a = realloc(a, sizeof(char*)*++count);
if(a==NULL)
{
perror("failed to allocate memory\n");
exit(-1);
}
a[count-1] = pch;
pch = strtok(NULL, " ,.-");
}
for(i=0;i<count;i++)
printf("%d: %s\n", i, a[i]);
///...compare array
Use qsort() for this sort of thing.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 0x100
int strcmp_wrapper(const void *a, const void *b) {
return strcmp(*(const char **)a, *(const char **)b);
}
int main () {
char buffer[BUF_SIZE], *tokens[BUF_SIZE / 2 + 1];
int i = 0, j = 0;
printf("Enter a string: ");
fgets(buffer, BUF_SIZE, stdin);
tokens[0] = strtok(buffer, " ,.-\n");
while ((tokens[++i] = strtok(NULL, " ,.-\n")));
qsort(tokens, i, sizeof(tokens[0]), strcmp_wrapper);
while (j < i)
printf("%s\n", tokens[j++]);
return 0;
}
below is a compact working way of doing what you want. It prints the words of each line, sorted and separated by one space, without repeating words being repeated (if you want them repeated for sure you will be able to touch the program to make it work)
$ cat pru799.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define DELIMITERS " \t\n,.-()&%$\"\'[]{}+-*/;:##|!\\<>=?"
#define LINE_SIZE 1024
#define MAX_WORDS 256
int compare(const char **p, const char **q)
{
return strcmp(*p, *q);
}
int main()
{
char line[LINE_SIZE];
char *words[MAX_WORDS];
int n_words;
while (fgets(line, sizeof line, stdin)) { /* while not eof */
char *p;
int i;
/* first get the words */
n_words = 0;
for (p = strtok(line, DELIMITERS); p; p = strtok(NULL, DELIMITERS)) {
if (strlen(p) == 0) continue; /* word is zero length */
if (n_words >= MAX_WORDS) {
fprintf(stderr, "MAX_WORDS(%d) exceeded\n", MAX_WORDS);
exit(EXIT_FAILURE);
}
words[n_words++] = p;
} /* for */
/* now we have all the words in the array of strings words, sort it */
qsort(words, n_words, sizeof words[0], (int(*)(const void *, const void *))&compare);
/* now print the words */
for (i = 0; i < n_words; i++) {
if (i) { /* all but the first one */
/* don't repeat words */
if (!strcmp(words[i], words[i-1]))
continue;
printf(" "); /* print a space between words */
}
printf("%s", words[i]);
}
printf("\n");
} /* while */
} /* main */

Segmentation Fault with strlen

I am getting a segmentation fault error. When I comment out "wordlength = strlen(token);" it runs fine. I don't know why it the seg fault happens when I assign a strlen(token) just fine to an int a few lines before this one. I would appreciate any help possible.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define char_max 60
int main(int argc, char *argv[])
{
FILE *fp = fopen(argv[2],"r");
char **wordlist;
int row = 1;
int i;
char temp[100];
char *token;
int wordlength;
int lengthcounter;
wordlist = (char**)malloc(row*sizeof(char*));
for(i = 0; i < row; i++)
{
wordlist[i] = (char*)malloc(char_max*sizeof(char*));
}
while(fgets(temp, sizeof(temp), fp) != NULL)
{
lengthcounter = 0;
wordlength = 0;
token = strtok(temp, " ");
strcat(wordlist[row-1], token);
printf("%s\n", wordlist[row-1]);
lengthcounter = strlen(token);
while(token != NULL)
{
token = strtok(NULL, " ");
wordlength = strlen(token);
/*lengthcounter += wordlength;*/
}
printf("The lengthcounter is %d\n", lengthcounter);
}
free(wordlist);
fclose(fp);
return 0;
}
while(token != NULL)
{
token = strtok(NULL, " ");
wordlength = strlen(token);
/*lengthcounter += wordlength;*/
}
What happens in the last iteration of the loop when token is NULL? You pass it to strlen anyway.
Also, this is almost certainly wrong:
wordlist[i] = (char*)malloc(char_max*sizeof(char*));
You're allocating space for pointers, not characters. So why sizeof(char*)? Also, don't cast the return value of malloc. This is C, not C++.

Putting information from a char array into a Dynamically created array

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);
}
}

Resources