I am trying to split a given char array into separate strings. I am doing this by putting the address of each word into an array, and then getting the string from the address to print.
So I have updated my code but now the program freezes after printing the numArgs but before "test2." I don't understand why.
----------------old code-----------------------
char* parseArgs(char* comPtr){
char *args[100] = {0};
char *token;
int i = 0;
token = strtok(comPtr, " ");
while(token != NULL){
args[i] = malloc(100);
args[i] = &token;
token = strtok(NULL, " ");
}
return *args;
}
char* args = parseArgs(comPtr);
int i = 0;
while(i < numArgs){
printf("arg%d: %s\n",i,&args[i]);
i++;
}
-----------------------end old code--------------------
------------------new code------------------------
int countArgs(char* comPtr){
char *token;
int i = 0;
token = strtok(comPtr, " ");
while(token != NULL){
i++;
token = strtok(NULL, " ");
}
return i;
}
char** parseArgs(char* comPtr){
printf("test1");
char** args = calloc(100, sizeof(char*));
char* token;
int i = 0;
while(token = strtok(comPtr, " ")){
args[i] = token;
}
printf("test2");
return args;
}
printf("ComPtr: %s\n",comPtr);
char* path = "/bin/";
//int pid = fork(); //pid always 0 so using pid = 1 to test
//printf("PID:%d",pid);
int pid = 1;
printf("PID:%d",pid);
if(pid != 0){
int numArgs = countArgs(comPtr);
printf("test1");
printf("NumArgs: %d\n",numArgs);
printf("test2");
char** args = parseArgs(comPtr);
int i = 0;
printf("test3");
while(i < numArgs){
printf("arg%d: %s\n",i,args[i]);
printf("test4");
i++;
}
}
else{
//waitpid();
}
You've lost track of where your memory is, your pointers are pointing etc.. If you want to return the list of pointers to tokens, you need something like this:
char** parseArgs(char* comPtr){
char** p_args = calloc(100, sizeof(char*);
int i = 0;
char* token;
while (token = strtok(comPtr, " "))
p_args[i] = token;
return p_args;
}
char** p_args = parseArgs(comPtr);
int i = 0;
while(i < numArgs)
{
printf("arg%d: %s\n",i,p_args[i]);
i++;
}
free(p_args);
I haven't tested it, but it should point you in the right direction. Have a careful think about how it differs from your program, and use a debugger and/or printf() statements in the code to print out addresses and see how it works (or debug it if necessary).
Declare the pointer array 'char *args[100]' as global variable. In your program your are allocating memory to the local pointer and its life is within the function. so at the end of the function your pointer variable scope ends. Here there is memory leak too.
The freeze is due to
int i = 0;
while(token = strtok(comPtr, " ")){
args[i] = token;
}
where you repeatedly - in an infinite loop - find the first token in comPtr, token becomes &comPtr[0] in each iteration (unless the string starts with spaces), and that is assigned to args[i].
After the first call, all calls to strtok that shall find further tokens in the same string - if any - should have a NULL first argument.
Also, you should probably increment i in the loop, since presumably you don't want to overwrite args[0] with each new token.
Related
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.
I am learning about how to use token to analyze file and put it in struct array. My code compiles fine, but it crashes while running it. Can someone please help?
Here is my code:
struct state_info {
char code[3];
unsigned long num_records;
unsigned long total_income;
unsigned long total_vehicles;
unsigned long total_population;
unsigned long total_rent;
unsigned long total_renter;
};
int main(int argc, char *argv[]) {
const int num_states = 100;
struct state_info *states[num_states];
FILE *file = fopen(argv[i], "r");
analyze_file(file, states, num_states);
}
void analyze_file(FILE *file, struct state_info *states[], int num_states) {
const int line_sz = 100;
char line[line_sz];
while (fgets(line, line_sz, file) != NULL) {
char* token = strtok(line, " \n");
while(token != NULL) {
//allocate memory
int size = atoi(token);
if(states[size] == NULL) {
states[size] = malloc(sizeof(struct state_info));
states[size]->num_records = 0;
states[size]->total_income = 0;
states[size]->total_vehicles = 0;
states[size]->total_population = 0;
states[size]->total_rent = 0;
states[size]->total_renter = 0;
}
//add value to the states
token = strtok(NULL, " \n");
strcpy(states[size]->code, token);
token = strtok(NULL, " \n");
states[size]->total_population += atoi(token);
token = strtok(NULL, " \n");
states[size]->total_income += atoi(token);
token = strtok(NULL, " \n");
states[size]->total_vehicles += atoi(token);
token = strtok(NULL, " \n");
//calculate total rent and total renter
if(atoi(token) != 0) {
states[size]->total_rent += atoi(token);
states[size]->total_renter++;
}
}
states[size]->num_records++;
token = strtok(NULL, " \n");
}
}
I think there should be something wrong with my pointer but I am not sure about it.
Statement struct state_info *states[num_states] does not initialize the pointer array with NULL-values, such that it may contain "garbage" (i.e. pointers != NULL pointing to something not being a valid object).
Hence, a comparison like if(states[size] == NULL) will probably never evaluate to true and will consequently never allocate a proper object. Subsequent access to states[size] will lead to undefined behaviour (actually the access states[size]==... already is undefined behaviour, yet I bet that the "crash" is due to the subsequent access)
Maybe there are other issues as well; yet I think that this is the most obvious thing in your code.
Fix it by initialising states, e.g. struct state_info *states[num_states] = { NULL }
I am trying to make dynamic double array, but I have a problem with BAD_ACCSESS.
int execute(person* person_array)
{
char** parsed_command;
if(!(parsed_command = malloc(sizeof(char*)))){
error_notification(12);
return 2;
}
parsed_command[0] = malloc(SIZE_ARG*sizeof(char));
char command[MAX_BUFFER_SIZE];
string quit = "quit\n";
do{
printf("esp> ");
if(fgets(command, MAX_BUFFER_SIZE, stdin)==NULL){ // save input in "command"
return 2;
}
parse_command_input(command, person_array, &parsed_command);
}while(strcmp(command,quit));
printf("Bye.\n");
free(&parsed_command[0]);
free(parsed_command);
return 0;
}
void parse_command_input(const char* command, person* person_array, char*** parsed_command){
char* delim = strtok(command, " ");
int counter = 0;
while (delim != NULL){
if(counter > 0) {
char **tmp = realloc(*parsed_command, (counter+1)*sizeof(char*));
if(tmp!=NULL)
*parsed_command = tmp;
else{
error_notification(12);
}
*parsed_command[counter] = malloc(SIZE_ARG*sizeof(char)); //ERROR
}
strcpy(*parsed_command[counter], delim);
counter++;
delim = strtok (NULL, " \n");
}
which_command(parsed_command, counter, person_array);
}
So, I initialise parsed_command in execute(), and then reallocate it in parsed_command_input() when i have more then one word in input.
By reallocating parsed_command at the first time everything is ok, but on the second reallocating round the address of parsed_command changes, and i have BAD_ACCSESS by malloc (add memory for line).
How can I fix it?
Thanks in advance
*parsed_command[counter] means the same as *(parsed_command[counter]) but you meant it to be (*parsed_command)[counter] so write that.
I've only found a few threads like this, and none with information that I am able to make any sense of. I'm programming a shell in C and I feel like it should be easy but my C programming is not so fresh. I'm having issues with passing a double pointer and the contents disappearing
I feel I am on the right track, and it sounds like it has something to do with initialization, but I've tried a few things, setting pointers to NULL just to be sure. Thanks.
void runProgram (char **cLine);
char **parse(char *str);
/*
*
*/
int main(int argc, char** argv)
{
char *cin = NULL;
ssize_t buffer = 0;
char **tempArgs = NULL;
printf(">");
while(1)
{
getline(&cin, &buffer, stdin);
tempArgs = parse(cin); //malloc, parse, and return
printf("passing %s", tempArgs[0]); //works just fine here, can see the string
runProgram(tempArgs); //enter this function and array is lost
}
return (EXIT_SUCCESS);
}
char** parse( char* str )
{
char *token = NULL;
char tokens[256];
char** args = malloc( 256 );
int i = 0;
strcpy( tokens, str );
args[i] = strtok( tokens, " " );
while( args[i] )
{
i++;
args[i] = strtok(NULL, " ");
}
args[i] = NULL;
return args;
}
Visible in main up until this function call
void runProgram (char **cLine)
{
//function that calls fork and execvp
}
The simplest fix is not to use tokens at all in the parse() function:
int main(void)
{
char *buffer = NULL;
size_t buflen = 0;
char **tempArgs = NULL;
printf("> ");
while (getline(&buffer, &buflen, stdin) != -1)
{
tempArgs = parse(buffer);
printf("passing %s", tempArgs[0]);
runProgram(tempArgs);
printf("> ");
free(tempArgs); // Free the space allocated by parse()
}
free(buffer); // Free the space allocated by getline()
return (EXIT_SUCCESS);
}
char **parse(char *str)
{
char **args = malloc(256);
if (args == 0)
…handle error appropriately…
int i = 0;
args[i] = strtok(str, " ");
// Bounds checking omitted
while (args[i])
args[++i] = strtok(NULL, " ");
return args;
}
Note that when the loop terminates, the array is already null terminated, so the extra assignment wasn't necessary (but it is better to be safe than sorry).
I am having trouble with the strtok function. I keep getting a 'bus error.' I wrote a function to return all the words within a line. Could somebody please point out my error?
NOTE: I am used to higher level languages
void extract_words(char tokens[WORD_MAX][WORD_LEN], char* line, int* sizePtr)
{
printf("in extract words"); //for debugging
char* chPtr = NULL;
chPtr = strtok(line, " ");
int size = 1; //words has one element
while(chPtr != NULL)
{
strcpy(tokens[size++], chPtr);
chPtr = strtok(NULL, " "); //continue to tokenize the string
}
*sizePtr = size;
}
Thanks in advance!
strtok modifies the string you pass to it, so it can't be a string literal. You should be able to do something like this:
void extract_words(char tokens[WORD_MAX][WORD_LEN], const char* line_arg, int* sizePtr)
{
char line[(WORD_LEN+1)*WORD_MAX];
char* chPtr = NULL;
int size = 0;
strcpy(line,line_arg);
printf("in extract words"); //for debugging
chPtr = strtok(line, " ");
while(chPtr != NULL)
{
strcpy(tokens[size++], chPtr);
chPtr = strtok(NULL, " "); //continue to tokenize the string
}
*sizePtr = size;
}
Note that I also initialized size to zero, since array indices start at zero.
Well...
Should you try to use a separator?
That case, I have source code.
int split(char *src, char *div, char **result,int *size)
{
int i, j, slen, dlen, key=0, start=0;
slen=strlen(src);
dlen=strlen(div);
for(i=0;i<slen;i++)
{
for(j=0;j<dlen;j++)
{
if(src[i]==div[j])
{
src[i]=0x00;
result[key] = src+start;
key++;
start=i+1;
}
}
}
result[key]=src+start;
*size=key+1;
return 0;
}
using
split(chatData, " ", cmpData, &tok);
" " : token
&tok : count split word
chatData : original data
by korean Dalsam.