I need to write a program that fills a struct from xml file and read xml files, but it's not a problem.
Firstly I wrote a program without modules (it's compiling):
main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <strings.h>
#include <libxml/tree.h>
#include <string.h>
#include "startupDirector.h"
static void startup_from_xml(Startup_T *startup, xmlNode * curNode)
{
char * data;
for(curNode = curNode->children; curNode != NULL; curNode = curNode->next)
{
// Get "name" string field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"name"))
{
data = (char *)xmlNodeGetContent(curNode);
strcpy(startup->name, data);
continue;
}
// Get "budget" integer field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"budget"))
{
data = (char *)xmlNodeGetContent(curNode);
startup->budget = atoi(data);
continue;
}
}
}
static Director_T *director_from_xml(Director_T *curDirector, xmlNode * curNode)
{
char *data;
char *properties;
// Get "name" string attribute.
properties = (char *) xmlGetProp(curNode, (const xmlChar *)"name");
strcpy(curDirector->name, properties);
// Get "surname" string attribute.
properties = (char *)xmlGetProp(curNode, (const xmlChar *)"surname");
strcpy(curDirector->surname, properties);
for(curNode = curNode->children; curNode != NULL; curNode = curNode->next)
{
// Get "nationality" string field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"nationality"))
{
data = (char *)xmlNodeGetContent(curNode);
strcpy(curDirector->nationality, data);
continue;
}
// Get "birthdate" UTC ISO 8601 field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"birthdate"))
{
data = (char *)xmlNodeGetContent(curNode);
sscanf(data, "%d-%d-%d",
&curDirector->birthDate.tm_year,
&curDirector->birthDate.tm_mday,
&curDirector->birthDate.tm_mon);
continue;
}
// Get "enthusiasm" integer field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"enthusiasm"))
{
data = (char *)xmlNodeGetContent(curNode);
curDirector->enthusiasm = atoi(data);
continue;
}
// Get "experience" double field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"experience"))
{
data = (char *)xmlNodeGetContent(curNode);
curDirector->experience = atof(data);
continue;
}
// Get "money" integer field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"money"))
{
data = (char *)xmlNodeGetContent(curNode);
curDirector->money = atoi(data);
continue;
}
// Get "startup" (string,integer) complex field.
if(!xmlStrcmp(curNode->name, (xmlChar *)"startup"))
{
startup_from_xml(&(curDirector->startup), curNode);
continue;
}
}
return (curDirector);
}
Director_T *director_new(void)
{
Director_T *director = (Director_T *)malloc(sizeof(struct Director_S));
strcpy(director->name, "");
strcpy(director->surname, "");
strcpy(director->nationality, "");
memset(&director->birthDate, 0, sizeof(director->birthDate));
director->enthusiasm = 0;
director->experience = 0;
director->money = 0;
strcpy(director->startup.name, "");
director->startup.budget = 0;
return (director);
}
void xmlParse(Director_T **directorSet, const char * XMLFileName)
{
xmlDoc * doc = xmlReadFile(XMLFileName, "UTF-8", 0);
if(doc == NULL)
{
xmlFreeDoc(doc);
return;
}
xmlNode *xml_root = xmlDocGetRootElement(doc);
xmlNode *curNode;
int i;
for(i = 0, curNode = xml_root->children; curNode != NULL; curNode = curNode->next)
{
if(!xmlStrcmp(curNode->name, (const xmlChar *)"director"))
{
director_from_xml(directorSet[i++], curNode);
}
}
xmlFreeDoc(doc);
}
void printDirectorInfo(Director_T *director)
{
printf("\t[%s]\n"
"\t[%s]\n"
"\t[%s]\n"
"\t%d-%d-%d\n"
"\t%i\n"
"\t%f\n"
"\t%i\n"
"\t[%s]\n"
"\t%i\n\n",
director->name,
director->surname,
director->nationality,
director->birthDate.tm_year, director->birthDate.tm_mon, director->birthDate.tm_mday,
director->enthusiasm,
director->experience,
director->money,
director->startup.name,
director->startup.budget
);
}
void director_delete(Director_T *director)
{
free(director);
}
int main()
{
const char *filePath = "StartupDirector.xml";
Director_T *directors[DIRECTORS_COUNT];
// Init directors array.
for(int i = 0; i < DIRECTORS_COUNT; i++)
{
directors[i] = director_new();
}
// Parse elements from .xml file.
xmlParse(directors, filePath);
// Print parsed info.
for(int i = 0; i < DIRECTORS_COUNT; i++)
{
printf("STARTUP_DIRECTOR #%i\n", (i+1));
printDirectorInfo(directors[i]);
}
// Free allocated memory.
for(int i = 0; i < DIRECTORS_COUNT; i++)
{
director_delete(directors[i]);
}
return 0;
}
Makefile:
all:
gcc main.c -g -Werror -c -I /usr/include/libxml2
gcc *.o -lxml2
rm *.o
when I compile this main.c all going nice, but then I tried to separate my program to modules and got a problem:
new main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <strings.h>
#include <libxml/tree.h>
#include <string.h>
#include "startupDirector.h"
int main()
{
const char *filePath = "StartupDirector.xml";
Director_T *directors[DIRECTORS_COUNT];
// Init directors array.
for(int i = 0; i < DIRECTORS_COUNT; i++)
{
directors[i] = director_new();
}
// Parse elements from .xml file.
xmlParse(directors, filePath);
// Print parsed info.
for(int i = 0; i < DIRECTORS_COUNT; i++)
{
printf("STARTUP_DIRECTOR #%i\n", (i+1));
printDirectorInfo(directors[i]);
}
// Free allocated memory
for(int i = 0; i < DIRECTORS_COUNT; i++)
{
director_delete(directors[i]);
}
return 0;
}
startupDirector.c (for module)
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <time.h>
#include <libxml/tree.h>
#include "startupDirector.h"
// private:
static void startup_from_xml(Startup_T *startup, xmlNode * curNode)
{
char * data;
for(curNode = curNode->children; curNode != NULL; curNode = curNode->next)
{
// Get "name" string field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"name"))
{
data = (char *)xmlNodeGetContent(curNode);
strcpy(startup->name, data);
continue;
}
// Get "budget" integer field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"budget"))
{
data = (char *)xmlNodeGetContent(curNode);
startup->budget = atoi(data);
continue;
}
}
}
static Director_T *director_from_xml(Director_T *curDirector, xmlNode * curNode)
{
char *data;
char *properties;
// Get "name" string attribute.
properties = (char *) xmlGetProp(curNode, (const xmlChar *)"name");
strcpy(curDirector->name, properties);
// Get "surname" string attribute.
properties = (char *)xmlGetProp(curNode, (const xmlChar *)"surname");
strcpy(curDirector->surname, properties);
for(curNode = curNode->children; curNode != NULL; curNode = curNode->next)
{
// Get "nationality" string field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"nationality"))
{
data = (char *)xmlNodeGetContent(curNode);
strcpy(curDirector->nationality, data);
continue;
}
// Get "birthdate" UTC ISO 8601 field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"birthdate"))
{
data = (char *)xmlNodeGetContent(curNode);
sscanf(data, "%d-%d-%d",
&curDirector->birthDate.tm_year,
&curDirector->birthDate.tm_mday,
&curDirector->birthDate.tm_mon);
continue;
}
// Get "enthusiasm" integer field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"enthusiasm"))
{
data = (char *)xmlNodeGetContent(curNode);
curDirector->enthusiasm = atoi(data);
continue;
}
// Get "experience" double field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"experience"))
{
data = (char *)xmlNodeGetContent(curNode);
curDirector->experience = atof(data);
continue;
}
// Get "money" integer field.
if(!xmlStrcmp(curNode->name, (const xmlChar *)"money"))
{
data = (char *)xmlNodeGetContent(curNode);
curDirector->money = atoi(data);
continue;
}
// Get "startup" (string,integer) complex field.
if(!xmlStrcmp(curNode->name, (xmlChar *)"startup"))
{
startup_from_xml(&(curDirector->startup), curNode);
continue;
}
}
return (curDirector);
}
// public:
Director_T *director_new(void)
{
Director_T *director = (Director_T *)malloc(sizeof(struct Director_S));
strcpy(director->name, "");
strcpy(director->surname, "");
strcpy(director->nationality, "");
memset(&director->birthDate, 0, sizeof(director->birthDate));
director->enthusiasm = 0;
director->experience = 0;
director->money = 0;
strcpy(director->startup.name, "");
director->startup.budget = 0;
return (director);
}
void director_delete(Director_T *director)
{
free(director);
}
void xmlParse(Director_T **directorSet, const char * XMLFileName)
{
xmlDoc * doc = xmlReadFile(XMLFileName, "UTF-8", 0);
if(doc == NULL)
{
xmlFreeDoc(doc);
return;
}
xmlNode *xml_root = xmlDocGetRootElement(doc);
xmlNode *curNode;
int i;
for(i = 0, curNode = xml_root->children; curNode != NULL; curNode = curNode->next)
{
if(!xmlStrcmp(curNode->name, (const xmlChar *)"director"))
{
director_from_xml(directorSet[i++], curNode);
}
}
xmlFreeDoc(doc);
}
void printDirectorInfo(Director_T *director)
{
printf("\t[%s]\n"
"\t[%s]\n"
"\t[%s]\n"
"\t%d-%d-%d\n"
"\t%i\n"
"\t%f\n"
"\t%i\n"
"\t[%s]\n"
"\t%i\n\n",
director->name,
director->surname,
director->nationality,
director->birthDate.tm_year, director->birthDate.tm_mon, director->birthDate.tm_mday,
director->enthusiasm,
director->experience,
director->money,
director->startup.name,
director->startup.budget
);
}
startupDirector.h
#ifndef STARTUPDIRECTOR_H
#define STARTUPDIRECTOR_H
#include <time.h> // time_t
#define DIRECTOR_NAME_LEN 50
#define DIRECTOR_SURNAME_LEN 50
#define DIRECTOR_NATIONALITY_LEN 50
#define STARTUP_NAME_LEN 100
#define DIRECTORS_COUNT 4
typedef struct Startup_S
{
char name[STARTUP_NAME_LEN];
int budget;
} Startup_T;
typedef struct Director_S
{
char name[DIRECTOR_NAME_LEN];
char surname[DIRECTOR_SURNAME_LEN];
char nationality[DIRECTOR_NATIONALITY_LEN];
struct tm birthDate;
int enthusiasm;
float experience;
int money;
struct Startup_S startup;
} Director_T;
Director_T *director_new(void);
void director_delete(Director_T *director);
Startup_T *startup_new(void);
void startup_delete(Startup_T *startup);
void xmlParse(Director_T *directorSet[], const char * XMLFileName);
void printDirectorInfo(Director_T *director);
#endif
After compiling this files using makefile i had an error
Terminal:
brusentcov#brusentcov:~/projects/xml_startup$ make
gcc main.c -g -Werror -c -I /usr/include/libxml2
gcc *.o -lxml2
main.o: In function `main':
/home/brusentcov/projects/xml_startup/main.c:168: undefined reference to `director_new'
/home/brusentcov/projects/xml_startup/main.c:172: undefined reference to `xmlParse'
/home/brusentcov/projects/xml_startup/main.c:178: undefined reference to `printDirectorInfo'
/home/brusentcov/projects/xml_startup/main.c:184: undefined reference to `director_delete'
collect2: error: ld returned 1 exit status
I hope that somebody will help me. Thanks for attention if you read this.
The problem is the makefile.
Here is the make file I used (after fixing the #include statement mentioned in the comments
#all:
# gcc xml_main.c -g -Werror -c -I /usr/include/libxml2
# gcc *.o -lxml2
# rm *.o
CC := /usr/bin/gcc
RM := /bin/rm
CFLAGS := -c -Wall -Wextra -pedantic -Wconversion -std=gnu11
SRC := main.c startupDirector.c
OBJ := $(SRC:.c=.o)
target := xmlProgram
.PSEUDO: all clean
all: $(target)
$(target): $(OBJ)
$(CC) -o $# $^ -L /usr/lib/x86_64-linux-gnu/ -lxml2
%.o:%.c
$(CC) $(CFLAGS) -o $# $< -I. -I /usr/include/libxml2
clean:
$(RM) -f $(OBJ) $(target)
here is the complete output from the call to make
/usr/bin/gcc -c -Wall -Wextra -pedantic -Wconversion -std=gnu11 -o main.o main.c -I. -I /usr/include/libxml2
/usr/bin/gcc -c -Wall -Wextra -pedantic -Wconversion -std=gnu11 -o startupDirector.o startupDirector.c -I. -I /usr/include/libxml2
startupDirector.c: In function ‘director_from_xml’:
startupDirector.c:73:39: warning: conversion to ‘float’ from ‘double’ may alter its value [-Wfloat-conversion]
curDirector->experience = atof(data);
^
/usr/bin/gcc -o xmlProgram main.o startupDirector.o -L /usr/lib/x86_64-linux-gnu/ -lxml2
Strongly suggest you fix that warning about the conversion from double to float
and since I did not have the expected input file, here is the output:
I/O warning : failed to load external entity "StartupDirector.xml"
STARTUP_DIRECTOR #1
[]
[]
[]
0-0-0
0
0.000000
0
[]
0
STARTUP_DIRECTOR #2
[]
[]
[]
0-0-0
0
0.000000
0
[]
0
STARTUP_DIRECTOR #3
[]
[]
[]
0-0-0
0
0.000000
0
[]
0
STARTUP_DIRECTOR #4
[]
[]
[]
0-0-0
0
0.000000
0
[]
0
Note: I compiled, linked, ran on ubuntu linux 16.04
Thanks for all. The problem really was in the makefile: I should write "*c" when I wrote "-c".
Related
I have written a simple tool to select an audio channel in FreeBSD.
This is the code:
xaudio.c
#include <Xm/Xm.h>
#include <Xm/PushB.h>
#include <Xm/MainW.h>
#include <Xm/RowColumn.h>
#include <stdio.h>
#include <stdlib.h>
#include "devices.h"
struct button_data {
int device_num;
Widget button;
};
/* GLOBAL VARIABLES */
int num_devices;
struct device *devices;
struct button_data *buttons;
void button_callback(Widget widget, XtPointer client_data, XtPointer call_data);
void create_device_buttons(Widget parent, struct device *devices, int num_devices);
void button_callback(Widget widget, XtPointer client_data, XtPointer call_data) {
int i;
struct button_data *data = (struct button_data *)client_data;
int device_num = data->device_num;
// unclick all other buttons
for (i = 0; i < num_devices; i++) {
if (buttons[i].button != widget) {
XtVaSetValues(buttons[i].button, XmNset, False, NULL);
}
}
// click this button
XtVaSetValues(widget, XmNset, True, NULL);
// set audio device
set_audio_device(device_num);
}
void create_device_buttons(Widget parent, struct device *devices, int num_devices) {
int i;
XmString label;
struct button_data *data;
Arg args[5];
int n;
buttons = malloc(num_devices * sizeof(struct button_data));
if (buttons == NULL) {
perror("Failed to allocate memory");
exit(EXIT_FAILURE);
}
for (i = 0; i < num_devices; i++) {
// create button
n = 0;
label = XmStringCreateLocalized(devices[i].description);
XtSetArg(args[n], XmNlabelString, label); n++;
buttons[i].button = XmCreatePushButton(parent, "device_button", args, n);
XmStringFree(label);
XtManageChild(buttons[i].button);
// set button data
buttons[i].device_num = devices[i].number;
// set button callback
XtAddCallback(buttons[i].button, XmNactivateCallback, button_callback, &buttons[i]);
}
}
int main(int argc, char *argv[]) {
XtAppContext app;
Widget top_level, main_window, button_rowcolumn;
int default_device;
int n=0;
Arg args[10];
top_level = XtVaOpenApplication(&app, "XAudio", NULL, 0, &argc, argv, NULL, sessionShellWidgetClass, NULL);
main_window = XmCreateMainWindow(top_level, "main_window", NULL, 0);
XtManageChild(main_window);
n=0;
XtSetArg(args[n], XmNorientation, XmVERTICAL); n++;
button_rowcolumn = XmCreateRowColumn(main_window, "button_rowcolumn", args, n);
XtManageChild(button_rowcolumn);
/* GET LIST OF DEVICES AND DEFAULT DEVICE */
default_device = get_default_device(&devices, &num_devices);
int i=0;
for(i=0; i<num_devices; i++) {
printf("%d %s\n", devices[i].number, devices[i].description);
}
create_device_buttons(button_rowcolumn, devices, num_devices);
XtRealizeWidget(top_level);
/* CLICK DEFAULT BUTTON */
if (default_device >= 0) {
XtVaSetValues(buttons[default_device].button, XmNset, True, NULL);
}
XtAppMainLoop(app);
free(devices);
free(buttons);
return 0;
}
devices.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct device {
int number;
char description[256];
};
void set_audio_device(int device_num) {
char command[256];
sprintf(command, "sysctl hw.snd.default_unit=%d", device_num);
system(command);
}
int get_default_device(struct device **devices, int *num_devices) {
FILE *fp;
char *line = NULL;
size_t len = 0;
ssize_t read;
int num_dev = 0;
int default_device = -1;
fp = popen("cat /dev/sndstat", "r");
if (fp == NULL) {
perror("Failed to run command");
exit(EXIT_FAILURE);
}
while ((read = getline(&line, &len, fp)) != -1) {
if (strstr(line, "pcm") == line) {
// line starts with "pcm", so it is a device line
// increase number of devices and reallocate memory
num_dev++;
*devices = realloc(*devices, num_dev * sizeof(struct device));
if (*devices == NULL) {
perror("Failed to allocate memory");
exit(EXIT_FAILURE);
}
// get device number
sscanf(line, "pcm%d:", &(*devices)[num_dev - 1].number);
// get description
char *start = strchr(line, '<');
char *end = strchr(line, '>');
if (start != NULL && end != NULL) {
int length = end - start - 1;
strncpy((*devices)[num_dev - 1].description, start + 1, length);
(*devices)[num_dev - 1].description[length] = '\0';
}
// check if this is the default device
if (strstr(line, "default") != NULL) {
default_device = num_dev - 1;
}
}
}
*num_devices = num_dev;
pclose(fp);
return default_device;
}
devices.h:
#ifndef DEVICES_H
#define DEVICES_H
#include <stdio.h>
#include <stdlib.h>
struct device {
int number;
char description[256];
};
void set_audio_device(int device_num);
int get_default_device(struct device **devices, int *num_devices);
#endif
And the corresponding makefile (for FreeBSD):
CC = cc
CFLAGS = -Wall -Wextra -I/usr/local/include
LDFLAGS = -Wall -Wextra -L/usr/local/lib -lXm -lXt -lX11
all: xaudio
xaudio: xaudio.o devices.o
$(CC) $(LDFLAGS) -o $# xaudio.o devices.o
xaudio.o: xaudio.c devices.h
$(CC) $(CFLAGS) -c -o $# $<
devices.o: devices.c devices.h
$(CC) $(CFLAGS) -c -o $# $<
clean:
rm -f *.o xaudio
The program compiles and works (it switches the audio channel as expected). However, my intended behaviour was that the channel selected appeared as a permanently pushed button, and that when a new channel was selected the pushed button changed accordingly. Sort kind of "selectable button set".
It is my understanding that such behaviour was achieved by the following widget parameter:
XtVaSetValues(buttons[default_device].button, XmNset, True, NULL);
However, as seen here, this is not happening and the buttons appear always unclicked except the normal dynamic click effect when pressed.
The desired behaviour you describe is what "radio buttons" are for. In Motif, I believe you need the XmCreateRadioBox function.
No, XmPushButton cant be configured to looked always pushed.
Try using XmToggleButton instead of XmPushButton. Set XmNindicatorOn to False to get rid of the diamond checkbox. Then XmNset,False will make it looked pressed.
I've several files with main functions in C, for example, I've files called show.c, delete.c add.c (...). I also have a file, called interpreter.c, which may call one of the files, for example delete.c. Most of these file implement a main function, like the delete.c:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
int main (int argc, char *argv[])
{
int fd, rm;
char *caminho = argv[1]; // argumento inserido no terminal
char caminhod[30]="../TPSOFinal/";
strcat(caminhod,argv[1]);
fd = open(caminhod, O_RDONLY);
rm=unlink(caminhod);
// Verifica se o caminho inserido no input existe
if(rm == 0){
write(1,"Ficheiro eliminado!!!\n", 22);
return 0;
}
else{
write(1,"Erro ao eliminar ficheiro !!!\n", 29);
perror("Erro");
}
return 0;
close(fd);
}
The interpreter:
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <readline/readline.h>
#include <readline/history.h>
#define LER_BUFFER 1024
#define TBUFF 64
#define DELIM "\t\r\n\a"
int mostra(char **args);
int conta(char **args);
int acrescenta(char **args);
int apaga(char **args);
int informa(char **args);
int lista(char **args);
int manual(char **args);
int termina(char **args);
char *comando[] =
{
"mostra <caminho>",
"conta <caminho>",
"acrescenta <caminho> <caminho destino>",
"apaga <caminho>",
"informa <caminho>",
"lista <caminho>",
"manual",
"termina",
" ",
};
int (*fcomandos[]) (char**) =
{
&mostra,
&conta,
&acrescenta,
&apaga,
&informa,
&lista,
&manual,
&termina
};
int ncomandos()
{
return sizeof(comando)/sizeof(char*);
}
void processa(char *linha, char **argv)
{
while(*linha != '\0')
{
while(*linha == ' ' || *linha == '\t' || *linha == '\n')
{
*linha++ = '\0'; //troca caracteres especiais
}
*argv++ = linha; //guarda posição
while (*linha != '\0' && *linha != ' ' && *linha != '\t' && *linha != '\n')
{
linha++;
}
}
*argv = NULL;
}
char *lerlinha (void)
{
char *linha = NULL;
ssize_t tam = 0;
getline (&linha, &tam, stdin);
return linha;
}
char **separa (char *linha)
{
int tam = TBUFF, pos = 0;
char **palavras = malloc (tam *sizeof(char*));
char *palavra;
if (!palavras)
{
perror("Erro");
exit(EXIT_FAILURE);
}
palavra = strtok (linha, DELIM);
while (palavra != NULL)
{
palavras [pos] = palavra;
pos ++;
if (pos >= tam)
{
perror ("Erro");
}
}
palavra = strtok(NULL, DELIM);
palavras [pos] = NULL;
return palavras;
}
int launch (char **args)
{
pid_t pid, wpid;
int estado;
pid = fork();
if (pid == 0)
{
if(execvp(args[0],args)==-1){ perror ("Erro!"); }
exit (EXIT_FAILURE);
}
if (pid <0)
{
perror ("Erro!");
}
else
{
do{wpid = waitpid(pid, &estado, WUNTRACED);}
while (!WIFEXITED(estado)&& !WIFSIGNALED(estado));
}
return 1;
}
//Testa se os comandos existem
int mostra (char **args)
{
if (args[1] == NULL)
{
perror("sem argumentos ");
}
else if (chdir (args[1]) != 0)
{
perror ("Erro!");
}
return 1;
}
int conta ( char ** args)
{
if (args[1] == NULL)
{
perror("Sem argumentos ");
}
else if (chdir (args[1])!= 0)
{
perror ("Erro!");
}
return 1;
}
// Manual dos comandos
int manual (char **args)
{
int i;
printf("\n\nMiguel Oliveira\n");
printf("10260 - LESI\n");
printf("Sistemas Operativos e Sistemas Distribuidos\n");
printf("\nLista de Comandos\n");
for (i=0; i<ncomandos(); i++)
{
printf("%s\n", comando[i]);
}
return 1;
}
int termina (char **args)
{
return 0;
}
//Executa os comandos
int executar (char **args)
{
int i;
if (args[0] == NULL)
{
return 1;
}
for (i=0; i<ncomandos(); i++)
{
if (strcmp(args[0], comando[i])==0)
{
return (*fcomandos[i])(args);
}
}
return launch(args);
}
//Interpretador
void interpretador (void)
{
char *linha;
char **args;
int estado;
do
{
printf("%% ");
linha = lerlinha();
args = separa(linha);
estado = executar(args);
free(linha);
free(args);
} while (estado);
}
int main (void)
{
interpretador();
return EXIT_SUCCESS;
}
I've tried to research for similar problems, and i've found some little possible solutions, but cannot solve my problem, as show on bottom GCC compile mistake
You do not "call source files"; source files define functions and variables, and when compiled, ones defined in different files can use each other if they have a declaration (in a header file, usually) or a pointer (via dynamic link methods, like POSIX dlsym()).
Consider this minimal example. First, example.c:
#include <stdlib.h>
#include <stdio.h>
/* We expect someone else to define these */
extern int one(void);
int main(void)
{
printf("one() returned %d.\n", one());
return EXIT_SUCCESS;
}
and helper.c:
int one(void)
{
return 2; /* TODO: It's not one! */
}
You compile each source file to an object file:
gcc -Wall -O2 -c example.c
gcc -Wall -O2 -c helper.c
and then you link them to an executable program:
gcc -Wall -O2 example.o helper.o -o program
which you can run using
./program
Normally, each C source file that provides functions or variables usable outside that file, declares them in a header file. Here's a better example.
degrees.h
#ifndef DEGREES_H
#define DEGREES_H
double radians_to_degrees(double);
double degrees_to_radians(double);
#endif /* DEGREES_H */
The #ifndef, #define, and #endif are used as guards, so that if you #include the file more than once, the functions get declared only once. (The compiler will complain if it sees multiple declarations. Plus, we don't need to use extern here.)
The implementation of the above is then in degrees.c,
#ifndef PI
#define PI 3.14159265358979323846
#endif
double degrees_to_radians(double degrees)
{
return degrees * PI / 180.0;
}
double radians_to_degrees(double radians)
{
return radians * 180.0 / PI;
}
In a program myprog.c in the same project, you would use the above thus:
#include <stdlib.h>
#include <stdio.h>
#include "degrees.h"
int main(void)
{
printf("45 degrees is %.6f radians.\n", degrees_to_radians(45.0));
printf("2 radians is %.3f degrees.\n", radians_to_degrees(2.0));
return EXIT_SUCCESS;
}
and again you'd compile first the two source files to object files,
gcc -Wall -O2 -c degrees.c
gcc -Wall -O2 -c myprog.c
and then link together to a program, say myprog,
gcc -Wall -O2 degrees.o myprog.o -o myprog
which you can then run:
./myprog
It is also possible to compile and link the functions and variables declared in degrees.h to a static (libdegrees.a) or a dynamic (libdegrees.so) library, and install the header file to the standard location, so that your program could instead use #include <degrees.h> and the program link to the library via -ldegrees, but that is better left until you are well comfortable working with multiple files.
Until then, you might find the following Makefile useful
CC := gcc
CFLAGS := -Wall -O2
LDFLAGS :=
PROGS := myprog
all: clean $(PROGS)
clean:
rm -f *.o $(PROGS)
%.o: %.c
$(CC) $(CFLAGS) -c $^
myprog: degrees.o myprog.o
$(CC) $(CFLAGS) $^ -o $#
You can add multiple programs in the PROGS line, separated by spaces, and copy the myprog: lines for each, listing the object files that program needs.
With this, all you need to compile the program is to type make.
This forum eats Tabs, and Makefiles need indentation to use those. So, if you just copy-paste that to a file, it won't work. You can fix it, though, by running
sed -e 's|^ *|\t|' -i Makefile
which removes all initial spaces on each line with a tab in file Makefile.
If you use separate libraries, typically libm (#include <math.h>), you just need to add -lm (dash ell em) to the LDFLAGS line. If you eventually play with dynamic linking, that's -ldl.
If you were to write a graphical program using Gtk+, you'd append `pkg-config --cflags gtk+-3.0` (including the backticks `) to the CFLAGS line, and `pkg-config --libs gtk+-3.0` to the LDFLAGS line, and #include <gtk/gtk.h> to your program.
i have an issue using DLL, i have a code that encrypt strings, buf using dll the result of the function changes.
CODE:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int cantidad(char *s){
int max=0;
for (int i = 0; s[i] ; i++) {
max=i;
}
return max+1;
}
char* pascal(char *s) {
//char s1[cantidad(s)];
int cuociente;
char *s1=calloc(strlen(s)+1,sizeof(char));
strcpy(s1,s);
if (s == NULL){ //caso que sea nulo.
return NULL;
}
cuociente=cantidad(s)/2;
if(cantidad(s)%2==0){//par
for (int i = 0; i <cuociente-1 ; i++) {
if(i%2==0){ // iteracion impar debido a que esta parte siendo iteracion 1,
s[cuociente-2-i]=s1[cantidad(s)-1-i];
s[cuociente+1+i]=s1[i];
}
if(i%2!=0){// iteracion par
s[cuociente-2-i]=s1[i];
s[cuociente+1+i]=s1[cantidad(s)-1-i];
}
}
}
if(cantidad(s)%2!=0){//impar
for (int k = 0; k <cuociente-1 ; k++) {
if (k%2==0){ //iteracion impar
s[cuociente-2-k]=s1[cantidad(s)-1-k];
s[cuociente+2+k]=s1[k];
}
if (k%2!=0){ //iteracion par
s[cuociente-2-k]=s1[k];
s[cuociente+2+k]=s1[cantidad(s)-1-k];
}
}
}
printf("%s",s);
return s;
}
Using CLion and terminal, if i encrypt "btvenyz tnyvn" the function returns "teytnyz bvvnn" that its the expected result.
But if i use makefile and DLL:
MAKEFILE:
all: shared compile
shared:
gcc -c -Wall -Werror -fpic ./lib/pascal.c
mkdir ./sym
gcc -shared -o ./sym/libpascal.so pascal.o
compile:
mkdir ./bin
gcc -Wall -Werror main.c -o ./bin/hash -ldl
rm -r *.o
clean:
rm -r ./sym ./bin
MAIN WITH DLL:
int main(){
char palabra[256],seq[256];
char (*func_pascal)(char[]);
void *handle_pascal;
char *error;
//PREPARE LIBRARY
handle_pascal= dlopen("../sym/libpascal.so",RTLD_LAZY);
// ERROR
if(!handle_pascal){
fprintf(stderr, "%s \n", dlerror());
exit(EXIT_FAILURE);
}
dlerror();
func_pascal = (char (*)(char[])) dlsym(handle_pascal,"pascal");
error = dlerror();
//ERROR
if(error != NULL){
fprintf(stderr,"%s \n", error);
exit(EXIT_FAILURE);
}
//INPUT
fgets(palabra,256,stdin);
fgets(seq,256,stdin);
printf("STRING: %s\n",palabra);
for (int i = 0; seq[i]; ++i)
{
if (seq[i]=='P')
{
(*func_pascal)(palabra);
printf("ENCRYPTED WORD:%s\n",palabra);
}
}
return 0;
}
Using DLL the output is:
INPUT
btvenyz tnyvn
P
OUTPUT
STRING: btvenyz tnyvn
ynevt
z bnvyntENCRYPTED WORD:ynevt
z bnvynt
Originally there are several encryption codes, where only this one generates error in the output, so I would like to know what I am doing wrong and how to solve it, thank you very much!
I am parsing the response to "net.connman.Manager.GetServices" function, which looks like this:
<method name="GetServices">
<arg name="services" type="a(oa{sv})" direction="out"/>
</method>
which is quite complex structure.
What I got so far is this:
GVariant* result = ... // response containing data
GVariantIter* iter1;
g_variant_get( result, "a(oa{sv})", &iter1 );
GVariant* child = g_variant_iter_next_value( iter1 );
while ( nullptr != child )
{
gchar* string;
GVariant* data;
g_variant_get( child, "(oa{sv})", &string, &data );
// how to access inner array?
g_variant_unref( child );
child = g_variant_iter_next_value( iter1 );
}
g_variant_iter_free( iter1 );
So, how do I access the inner array data?
I tried this:
GVariantIter* iter2;
g_variant_get( data, "a{sv}", &iter2 );
GVariant* child2 = g_variant_iter_next_value( iter2 );
but it fails with some alignment error:
**
GLib:ERROR:../../glib-2.48.2/glib/gvarianttypeinfo.c:163:g_variant_type_info_check: assertion failed: (info->alignment == 0 || info->alignment == 1 || info->alignment == 3 || info->alignment == 7)
Aborted
data should have type GVariantIter*, not GVariant*, as per the documentation for GVariant Format Strings (you are passing a GVariant format string as the second argument to g_variant_get()).
You can simplify the code quite a bit by using g_variant_iter_loop() though:
/* Compile with: `gcc `pkg-config --cflags --libs glib-2.0 gio-2.0` -o test test.c`.
* Public domain. */
#include <glib.h>
#include <gio/gio.h>
int
main (void)
{
g_autoptr(GVariant) result = g_variant_new_parsed ("#a(oa{sv}) [('/', { 'hello': <'test'>})]");
g_autoptr(GVariantIter) iter1 = NULL;
g_variant_get (result, "a(oa{sv})", &iter1);
const gchar *string;
g_autoptr(GVariantIter) iter2 = NULL;
while (g_variant_iter_loop (iter1, "(&oa{sv})", &string, &iter2))
{
const gchar *key;
g_autoptr(GVariant) value = NULL;
while (g_variant_iter_loop (iter2, "{&sv}", &key, &value))
g_message ("%s, %s:%p", string, key, value);
}
return 0;
}
I have two files: p1.c and p2.c.
I need to use the value stored in the structure in p1.c into p2.c. Please help me figure out how to achieve this. Should I use extern?
p1.c
typedef struct What_if
{
char price[2];
} what_if ;
int main()
{
what_if what_if_var[100];
file * infile;
infile=fopen("filepath");
format_input_records();
}
int format_input_records()
{
if ( infile != NULL )
{
char mem_buf [500];
while ( fgets ( mem_buf, sizeof mem_buf, infile ) != NULL )
{
item = strtok(mem_buf,delims);
strcpy(what_if_var[line_count].price,item) ;
printf("\ntrans_Indicator ==== : : %s",what_if_var[0].price);
}
}
}
p2.c
"what_if.h" // here i include the structure
int main()
{
process_input_records(what_if_var);
}
int process_input_records(what_if *what_if_var)
{
printf("\nfund_price process_input_records ==== : : %s",what_if_var[0]->price);
return 0;
}
Try this:
whatif.h:
#ifndef H_WHATIF_INCLUDED
#define H_WHATIF_INCLUDED
struct whatif {
char price[2];
};
int wi_process(struct whatif *);
#endif
p1.c
#include "whatif.h"
int main(void) {
struct whatif whatif[100];
whatif[0].price[0] = 0;
whatif[0].price[1] = 1;
whatif[1].price[0] = 42;
whatif[1].price[1] = 74;
whatif[99].price[0] = 99;
whatif[99].price[1] = 100;
wi_process(whatif);
return 0;
}
p2.c
#include <stdio.h>
#include "whatif.h"
int wi_process(struct whatif *arr) {
printf("%d => %d\n", arr[0].price[0], arr[0].price[1]);
printf("%d => %d\n", arr[1].price[0], arr[1].price[1]);
printf("%d => %d\n", arr[99].price[0], arr[99].price[1]);
return 3;
}
Then compile and link all of them together, for example with gcc
gcc -ansi -pedantic -Wall p1.c p2.c