I tried really hard to search for a solution to this but I can't think of good enough keywords.
Currently I'm having troubles grasping the concept behind makeargv and it's usage with triple pointers (I have no idea what ***foo means, it doesn't seem to be as easy of a concept as **foo or *foo). So I made my own:
const char **makeargv(char *string, int *numargs) {
string = string + strspn(string, delims);
char *copy = malloc(strlen(string) + 1);
int i;
strcpy(copy, string);
int numtokens;
if (strtok(copy, delims) != NULL) {
for (numtokens = 1; strtok(NULL, delims) != NULL; numtokens++) {}
}
strcpy(copy, string);
const char *results[numtokens+1];
results[0] = strtok(copy, delims);
for (i = 1; i < numtokens; i++) {
results[i] = strtok(NULL, delims);
}
results[numtokens+1] = NULL;
*numargs = numtokens;
return results;
}
Here's the part at where it breaks:
void parse_file(char* filename) {
char* line = malloc(160*sizeof(char));
FILE* fp = file_open(filename);
int i = 0;
int numargs = 0;
int *pointer = &numargs;
while((line = file_getline(line, fp)) != NULL) {
if (strlen(line) == 1){
continue;
}
const char **args = makeargv(line, pointer);
printf("%s\n", args[0]);
printf("%s\n", args[1]);
/* This prints out args[0], but then args[1] causes a seg fault. Even if I replace
the args[1] with another args[0] it still causes a seg fault */
}
fclose(fp);
free(line);
}
I have a working array of strings. However when I try to print out the strings in the array, I can only print 1 of my choice and then it seg faults for any subsequent calls. lets pretend my array of strings is argv[3] = {"Yes", "no", "maybe"}, if i call argv[0], it will let me call "Yes", but any other calls (even if i call argv[0] again) do not work and cause a segfault. I can call any of the elements in the array, but once i call one the rest cease to work causing segfaults.
Help please? D: This is in C.
const char *results[numtokens+1];
This array "results" is a local variable, it is only available inside of "makeargv".
You'd better use malloc:
results = malloc(numtokens+1)
And I believe there is memory leak in your code.
You will not be able to free the memory for "char *copy"
char *copy = malloc(strlen(string) + 1);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **makeargv(char *string, int *numargs) {
static const char *delims = " \t\n";
string = string + strspn(string, delims);
char *copy = malloc(strlen(string) + 1), *p = copy;
strcpy(copy, string);
int numtokens;
for (numtokens = 0; strtok(p, delims); ++numtokens, p = NULL);
char **results = malloc(sizeof(char*)*(numtokens+1));
strcpy(copy, string);
int i;
p = copy;
for (i = 0; i < numtokens; ++i, p = NULL)
results[i] = strtok(p, delims);
results[i] = NULL;
*numargs = numtokens;
return results;
}
FILE *file_open(char *filename){
FILE *fp = fopen(filename, "r");
if(!fp){
perror("file_open");
exit(1);
}
return fp;
}
void parse_file(char* filename) {
char* line = malloc(160*sizeof(char));
FILE* fp = file_open(filename);
int i = 0, numargs = 0;
while(fgets(line, 160, fp)){
if (*line == '\n')
continue;
char **args = makeargv(line, &numargs);
for(i = 0;i<numargs;++i)
printf("%s\n", args[i]);
printf("\n");
if(args[0])
free(args[0]);
free(args);
}
fclose(fp);
free(line);
}
int main(int argc, char *argv[]){
parse_file(argv[1]);
return 0;
}
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 trying to extract words from a string like this:
(octopus kitten) (game cake) (soccer football)
I attempted doing this with the help of strtok (I do strcpy just for not modifying the original token/string, also used memcpy, but it does the same in my case).
Main function:
int main(int argc, char * argv[]) {
char row[] = "(octopus kitten) (game cake) (soccer football)";
char * pch;
pch = strtok(row, "(");
while (pch != NULL) {
pch[strcspn(pch, ")")] = '\0';
print_word(pch);
pch = strtok(NULL, "(");
}
return 0;
}
Function for getting and printing each word:
void get_and_print_word(char str[]) {
char r[4000];
// for not modifying the original string
strcpy(r, str);
char * c = strtok(r, " ");
for (int i = 0; i < 2; i++) {
printf("%s\n", c);
c = strtok(NULL, " ");
}
}
It works absolutely fine with a first iteration, but after pch starts to point to another adress of memory (but it should point to the adress of letter "g").
It works absolutely fine (it's just printing string within the brackets) if we remove get_and_print_word(pch):
int main(int argc, char * argv[]) {
char row[] = "(octopus kitten) (game cake) (soccer football)";
char * pch;
pch = strtok(row, "(");
while (pch != NULL) {
pch[strcspn(pch, ")")] = '\0';
printf("%s\n", pch);
pch = strtok(NULL, "(");
}
return 0;
}
But that's not what I want to do, I need to get each word, not just a string of two words and space between them.
Using pch = strtok(NULL, " )(") is also not appropriate in my case, cause I need to store each pair of words (each word, of couse, should be a separate string) in some individual
struct, so I definitely need this function.
How to solve this issue and why it works like this?
Why not use regular expression :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
int main (int argc, char *argv[])
{
int err;
regex_t preg;
const char *str_request = argv[1];
const char *str_regex = argv[2];
err = regcomp (&preg, str_regex, REG_EXTENDED);
if (err == 0) {
int match;
size_t nmatch = 0;
regmatch_t *pmatch = NULL;
nmatch = preg.re_nsub;
pmatch = malloc (sizeof (*pmatch) * nmatch);
char *buffer;
if (pmatch) {
buffer = (char *) str_request;
match = regexec (&preg, buffer, nmatch, pmatch, 0);
while (match == 0) {
char *found = NULL;
size_t size ;
int start, end;
start = pmatch[0].rm_so;
end = pmatch[0].rm_eo;
size = end - start;
found = malloc (sizeof (*found) * (size + 1));
if (found) {
strncpy (found, &buffer[start], size);
found[size] = '\0';
printf ("found : %s\n", found);
free (found);
}
//searching next occurence
match = regexec (&preg, (buffer += end), nmatch, pmatch, 0);
}
regfree (&preg);
free (pmatch);
}
}
return 0;
}
[puppet#damageinc regex]$ ./regex "(octopus kitten) (game cake) (soccer football)" "([a-z]+)"
found : octopus
found : kitten
found : game
found : cake
found : soccer
found : football
This code reads file and split it lines into array in order to compare lines elements to each other.
The problem that it gives me as the first line
)�H� 2382 2382
I think that the function char **linecontent(char *line) is the problem but I am new in C and I tried every possible solution and I have nothing.
I am very sorry for asking.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** split(char string[],const char seps[])
{
char ** res = NULL;
char * p = strtok(string, seps);
int n_spaces = 0, i;
while (p) {
res = realloc(res, sizeof (char*) * ++n_spaces);
if (res == NULL) {
exit(-1); /* memory allocation failed */
}
res[n_spaces-1] = p;
p = strtok(NULL, seps);
}
res = realloc(res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = '\0';
return res;
free(res);
}
char** readfile(char *name, int *lsize)
{
FILE *fp;
char *result;
char line[500];
char *pline = NULL;
char **lines = NULL;
int i = 0;
int l = 0;
fp = fopen(name, "r");
while (fgets(line,500, fp)) {
i++;
pline = strdup(line);
lines = (char**)realloc(lines, sizeof (char**) * (++l));
/* Add to lines */
lines[l-1] = pline;
*lsize += 1;
pline = NULL;
}
fclose(fp);
return lines;
}
char** linecontent(char *line)
{
char **linecont;
char hit[300];
strncpy(hit, line, sizeof(hit) - 1);
hit[sizeof(hit) - 1] = '\0';
linecont = split(hit, "\t");
return linecont;
}
int main()
{
char **lines = NULL;
int lsize = 0;
lines = readfile("TEMP", &lsize);
int i = 0;
while (i != lsize) {
char **linecont1;
char *thisline=lines[i];
linecont1=linecontent(thisline);
char *pname1 = linecont1[0];
char *acc1 = linecont1[1];
int start1 = atoi(linecont1[3]);
int miss1 = atoi(linecont1[4]);
printf("%s\t%s\t%d\t%d\n", pname1, acc1, start1, start1);
i++;
}
}
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 have to dynamically allocate a pointer inside a while.
char * allocationg_memory(char [] path p) {
char message[4000];
char c;
unsigned int i = 0;
unsigned int count;
FILE *f;
//open the file
f = fopen(p, "rt");
count = 0;
//copy the contain of the file in message
if (f) {
while ((c = getc(f)) != EOF) {
count++;
message[i] = c;
i++;
}
fclose(f);
}
//allocating the memory
char *str = (char *) malloc(sizeof (char) * (count));
if (str == NULL) {
printf("error allocating memory for string\n");
exit(1);
}
//copy the message
strncpy (str, message, count);
return str;
}
void main {
char * ptr;
do {
//my path dynamically changing
path = path_of_file;
ptr = allocating_memory(path);
printf("%s", ptr);
free(ptr);
} while (1);
}
If I set ptr = NULL it gives me segmentation fault, if I don't, if the next print is bigger than the previus, the 2nd is printed over the 1st. What's wrong with my code?
For starters:
Your initial allocation is for 0 bytes.
You are trying to print what you have allocated as if it were a string.
Your loop never ends.
This works for me. Hopefully it helps
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
char * allocating_memory(int c) {
char *str = malloc ( c + 1); // allow an extra for the null
strncpy ( str, "abcdefghijklmnopqustuvwxyx", c);
str[c] = '\0'; // make sure the string is null terminated
return str;
}
int main () {
char * ptr;
int counter = 2;
do {
ptr = NULL;
ptr = allocating_memory(counter);
printf("%s\n", ptr);
free(ptr);
counter++;
} while (counter < 27);
return 0;
}