Basically I have a struct which stores my general program settings. I read in a config with the callback function to get the corresponding value, but I can't write it to the struct. I've tried everything from memcpy over strcpy to dereferencing the char pointer, but every time the char in the struct stays empty. The passed string contains only one char, I checked that multiple times. Also if I strcpy a string to the other fields of the struct, it works fine.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct {
char *datafile;
char *logfile;
char mode;
} general_settings;
void setSettingsData(void){
log_trace("parsing config file for general settings initialisation");
config_error_t rc = config_parse("config.ini", handle_settings_ini_file);
if (rc != CONFIG_ERROR_NONE) {
log_error("Error parsing configuration: %s on line %lu", config_get_error_string(rc), config_get_line_number());
} else {
log_info("Settings parsed successfully!");
}
}
static config_error_t handle_settings_ini_file(char *section, char *key, char *value) {
if(section != NULL && !strcmp("Allgemein", section)) {
if (!strcmp("mode", key)) {
general_settings.mode = strdup(value); // ??????
log_info("Program Execution mode set to %s", value);
} else {
log_fatal("Unrecognized setting. Check for typos. Exiting...");
exit(0);
}
}
return CONFIG_ERROR_NONE;
}
Since value is a char *, you can get the char it points to with *value.
So you want general_settings.mode = *value;.
You could also use general_settings.mode = value[0];
Since a[b] is the same as *(a+b), *(value + 0) is the same as value[0] and also the same as *value.
Related
Situation: I'm currently working with chained lists and I am adding new elements through a function called inputRegistering(). I am positive that at the end of this function, an element have been added to the correct place.
Issue1: The added element modifies all the other to take its value.
Issue2: When exiting the function, and calling the inputReadingAll() function (which displays the list in its entirety), the elements are now all "empty", or replaced with gibberish (as can do the pointers).
Test1: I have tested to do a manual adding in the main() function and it seems everything worked fine. I can't understand what is the fundamental difference with my code though...
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLEN 256
typedef struct
{
struct elt *first;
struct elt *last;
} Tfile;
typedef struct elt
{
char *val;
struct elt *next;
} Telt;
int fileAdd(Tfile *, char *);
void fileInit(Tfile *);
void inputReadingAll(Tfile *);
void inputRegistering(Tfile *);
int main(int argc, char **argv){
Tfile file;
fileInit(&file);
inputRegistering(&file);
inputRegistering(&file);
inputReadingAll(&file);
}
int fileAdd(Tfile *F, char *newVal){
Telt *newElt;
newElt = (Telt*)malloc(sizeof(Telt));
if(newElt == NULL){
printf("Error\n");
return 0;
}
newElt->val = newVal;
newElt->next = NULL;
if(fileTaille(F) == 0)
F->first = newElt;
else
F->last->next= newElt;
F->last = newElt;
return 1;
}
void fileInit(Tfile *F){
F->first = NULL;
F->last = NULL;
}
void inputReadingAll(Tfile *file){
printf("> Reading all function\nBEGIN\n");
Telt *currElt = file->first;
while(currElt != NULL){
printf("%p, %s\n", currElt, currElt->val);
currElt = currElt->next;
}
printf("END\n");
}
void inputRegistering(Tfile *file){
printf("> Registering function\n> What to register : \n> ");
char temp[MAXLEN];
fgets(temp, MAXLEN, stdin);
temp[strcspn(temp, "\n")] = 0;
printf("Registering %s\n", temp);
fileAdd(file, temp);
}
The (pointer to) local array temp of the function inputRegistering() is passed to the function fileAdd() and the pointer is directly stored to the structure.
This is bad because the array is local and it is invalidated on returning from the function inputRegistering().
Instead of this, the function fileAdd() should copy the passed string and store the pointer to the copy in the structure.
This can be done like this:
newElt->val = malloc(strlen(newVal) + 1); /* +1 for terminating null-character */
if (newElt->val == NULL) {
printf("Error\n");
free(newElt);
return 0;
}
strcpy(newElt->val, newVal);
instead of this:
newElt->val = newVal;
typedef struct
{
char Path[100];
} DirectoryInformation;
void Getskelutofdirectorie(char * dir, int lvl)
{
DirectoryInformation DI[100];
char cwd[1024];
//Search recursive
// where I want to put the path on the struct to use on main
getcwd(cwd, sizeof(cwd));
strcpy(DI[0].Path, cwd);
}
int main(void)
{
DirecoryInformation DI[100];
printf("%s", DI[0].Path);
}
I can print the path but if i use on main function will work.
Can somebody help me out?
It executes without error but when I print out make segmentation fault
Your code invokes undefined behavior by using value of variable DI having automatic storage duration and not initialized, which is indeterminate.
Call the function with passing pointer to the struct to store the data, then store there.
typedef struct
{
char Path[100];
} DirectoryInformation;
void Getskelutofdirectorie(DirectoryInformation * DI, char * dir, int lvl)
{
char cwd[100]; // cwd was too long, so there was risk of buffer overrun when copying
//Search recursive
//where i want to put the path on the struct to use on main
getcwd(cwd, sizeof(cwd));
strcpy(DI[0].Path, cwd);
}
int main(void)
{
DirectoryInformation DI[100] = {{""}}; // initialize for in case the function fails to set values
Getskelutofdirectorie(DI, NULL, 0); // pass proper parameter
printf("%s", DI[0].Path);
}
There is a function that asks the user which text file to open, opens it and then passes the array of structures that was passed into the function along with the file pointer to another function that reads in data from file into the structure. The array structure for testing purposes only has the value char name[25];. I can assign one line at a time from the file to the same structure index all I want but when I try an increment it I get a segmentation fault no matter what approach I've taken.
The structure has been type defined as well.
The code is:
void oSesame(char usrTxt[], int len, FILE * pFile, Country * p)
{
pFile = fopen(usrTxt, "rw");
if(pFile != NULL)
{
readIn(pFile, &p);
}
else
{
printf("Error opening %s , check your spelling and try again.\n", usrTxt);
}
}
void readIn(FILE * pfile, Country ** p)
{
int count = 0;
int i = 0;
for(i = 0; i<3; i++)
{
fgets((*p[i]).cntName, MAX_COUNTRY_LENGTH, pfile);
}
fclose(pfile);
}
The header file:
//Header.h
#define COUNTRY_MAX 10
#define MAX_COUNTRY_LENGTH 25
#define MAX_CAPITAL_LENGTH 25
typedef struct country
{
char cntName[MAX_COUNTRY_LENGTH];
char capName[MAX_CAPITAL_LENGTH];
double population;
}Country;
int ask(char * usrTxt);
void oSesame(char usrTxt[], int len, FILE * pFile, Country * p);
void readIn(FILE * pFile, Country ** p);
The main code:
#include <stdio.h> //for testing within main
#include <string.h> //for testing within main
#include "headers.h"
int main()
{
int len;
FILE * fileP;
char UI[25];
Country c[10];
Country * ptr;
ptr = c;
len = ask(UI);
oSesame(UI, len, fileP, ptr);
return 0;
}
You are passing Country** for some reason and then handling it as *p[index]. This is wrong. You could use (*p)[index] but the correct way is not to take a reference to the Country* in the first place.
The way you're doing it means you have a pointer to pointer to Country. When you index that you are moving to next pointer to pointer, which is not the same as moving to the next pointer. Undefined behaviour happens.
I've encountered a problem trying to reduce the size of my code. What I was trying to do was passing either name or color to function writedata so that I wouldn't have to write it twice for each case.
typedef struct Pet{
char* name;
char* color;
} pet;
void writedata(pet *Pet, char string[], const char field[]){
gets(string);
Pet->field= (char*)malloc(strlen(string)+1);//I wanted it to be treated like Pet->name
strcpy(Pet->field, string);
}
The call of the function:
writedata(Pet, string, name);
I'm quite sure I got something wrong.
update: the whole code http://ideone.com/Y7L8Hu
update2: I tried to implement it using offset according to BLUEPIXY's advice but it seems I misunderstand manipulations with fields using their addresses... I believe the problem could be that the fields aren't initialized in the first place, but then again, my aim is to initialize them.
typedef struct Pet{
char* name;
int legs;
char* color;
} pet;
void writedata(pet *Pet, size_t FIELD){
char string[50];
gets(string);
(char*)Pet+offsetof(struct Pet, FIELD) = (char*)malloc(strlen(string)+1);//I wanted it to be treated like Pet->name
strcpy((char*)Pet+FIELD, string);
}
That's not how C works. However, I think using string comparison can achieve what you need:
if (strcmp(field, "name") == 0)
{
Pet->name = ...
}
else if (strcmp(field, "color") == 0)
{
Pet->color = ...
}
And call it with a string literal:
writedata(Pet, string, "name");
Using enum is also an option.
BTW, don't use gets, it's dangerous, use fgets instead.
use macro function sample.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define writedata(var, buffer, field) \
do {\
int len = strlen(buffer);\
var->field = (char*)malloc(len + 1);\
memcpy(var->field, buffer, len+1);\
}while(0)
typedef struct Pet{
char* name;
int legs;
char* color;
char* voice;
} pet;
void addpet(pet* Pet, int *TotalLegs){//Can not be used reference(&) in C
char buff[50];
int len;
puts("Input name");
scanf("%49[^\n]", buff);
writedata(Pet, buff, name);
puts("How many legs?");
scanf("%d%*c", &Pet->legs);
puts("What does it say?");
scanf("%49[^\n]%*c", buff);
writedata(Pet, buff, voice);
puts("_____\n");
*TotalLegs += Pet->legs;
}
int main(){
int TotalLegs = 0;
pet* Pet1 = (pet*)malloc(sizeof(pet));
addpet(Pet1, &TotalLegs);
pet* Pet2 = (pet*)malloc(sizeof(pet));
addpet(Pet2, &TotalLegs);
pet* Pet3 = (pet*)malloc(sizeof(pet));
addpet(Pet3, &TotalLegs);
//printf("%s\n", Pet1->name);
//printf("%s\n", Pet1->voice);
printf("The animals have %d legs\n", TotalLegs);
free(Pet1);free(Pet2);free(Pet3);
return 0;
}
A lot of things are wonky in your code.
What you wish to do can be achieved but it takes different type of code than you'd want to write.
What you really want to do is simply create a function that fills in a name and a color.
So here is the simplest way to do it:
typedef struct pet {
char *name;
char *color;
} pet_t;
pet_t * new_pet(const char *name, const char *color)
{
pet_t *p;
p = malloc(sizeof(pet_t));
if ( p == NULL )
return NULL;
p->name = strdup(name); /* allocate space and copy string */
p->color = strdup(color); /* allocate spance and copy string */
return p;
}
void delete_pet(pet_t *p)
{
if ( p-> name )
free(p);
if ( p->color)
free(color);
if ( p )
free(p);
}
int main() {
pet_t *p;
p = new_pet("Harry", "brown");
printf("%s is a %s pet\n", p->name, p->color);
delete_pet(p);
return 0;
}
I want to parse a string into an array of tokens . '\n' and ';' are delimiters , for e.g. :
hello;hello
world
should be converted to an array containing: {"hello","hello","world"}.
I tried many different methods for doing this and always I fail (since it needs a dynamic array of char * I have trouble with implementing it).
Please note that I cannot use strtok or lexical analyzer.
How may I do this ? Any points ?
EDIT : here is one of methods I tried to use but I get segmentation fault (maybe a memory access issue somewhere in my code) :
#include <stdio.h>
#include <malloc.h>
#include <fcntl.h>
#include <string.h>
typedef struct {
int fd;
char *path;
int size;
char *mem;
struct stat st;
} file;
file *readfile(char *path) {
file *a=malloc(sizeof(file));
a->path=path;
a->fd=open(a->path,O_RDONLY);
if(a->fd<0) return 0;
fstat(a->fd,&a->st);
a->size=a->st.st_size;
a->mem=malloc(a->size);
read(a->fd,a->mem,a->size);
return a;
}
void releasefile(file *a) {
free(a->mem);
close(a->fd);
free(a);
}
char **parse(int *w,file *a) {
int i,j=0;
w=0;
for(i=0;i<=a->size;i++) {
if(a->mem[i]=='\n' || a->mem[i]==';') { a->mem[i]='\0'; j++; }
}
char **out=malloc(sizeof(char *)*j);
for(i=0;i<=a->size;i++) {
if(a->mem[i-1]!='\0') continue;
out[*w]=malloc(strlen(a->mem+i)+1);
memcpy(out[*w],a->mem+i,strlen(a->mem+i)+1);
w++;
return out;
}
int main(int argc,char **argv) {
file *a=readfile(argv[1]);
int *w=malloc(sizeof(int));
char **tokens=parse(w,a);
int i;
for(i=0;i<=*w;i++) {
puts(tokens[i]);
}
releasefile(a);
// ATM no need to check for mem leaks :)
}
Algorithm description : read file, put \0 where you see a delimiter, start and push tokens seprated by \0 into an array.
What has happened to computer science?
Anyway write a FSA - http://en.wikipedia.org/wiki/Finite-state_machine
Can do this using a table