How to get values from a config file - c

I have the following Config.cfg
[DD]
user=**
password=***
database=***
IPServidor=****
port=***
[Controller]
Control1=8
Temp=5
Hum=7
Link=8
Volt=9
[Controller]
Control2=10
Temp=5
Hum=7
Link=8
Volt=9
I would like to read the values of the controllers only and print them to the screen like
Controller_8: 5,7,8,9
I do not want to use libconfig or glib because I have problem with undefined functions. I did the installation, I have the headers but I do not know why it does not work. So I want another solution. My first thought is with the usage of strchr to find the lines which I want (to ignore [DD] table in my case) and with the usage of strtok to get only the values of temp,hum,link,volt
char buffer1[100];
FILE *f = fopen("/home/pi/Desktop/Config.cfg","r");
while(fgets(buffer1, sizeof(buffer1), f))
{
printf("%s",buffer1);
char *pos1 = strchr(buffer1,'Controller');
if (pos1)
{
item = strtok (buffer1,"Control");
printf("Results: %s\n", buffer1);
}
}
The above code is not correct. Is just a thought. Is there any better way?

Don't try parsing ini files, use some existing library.
Ini file parsing is included in a number of "frameworks", for instance in Gtk+ or on Windows. If you can't access those, you can still use some standalone library, for instance: http://ndevilla.free.fr/iniparser/

Related

Can memmove accessing the contents of a FILE* and delete information?

Does memmove work on file pointer data?
I am trying to remove a line from a C file. I am trying to use memmove to make this more efficient than the internet's recommendation to create a duplicate file and overwrite it. I have debugged and I can't figure out why this code isn't working. I am asking for input. The logic is a for loop. Inside the loop, I have logic to do a memmove but it doesn't seem effective.
nt RemoveRow(int iRowNum)
{
char sReplaceLineStart[m_MaxSizeRow]={0};
char sTemp[m_MaxSizeRow] ={0};
size_t RemovalLength = 0;
GoToBeginningOfFile();
for(int i =0;i<m_iNumberOfRows;i++)
{
if(i == iRowNum)
{
// Line to remove
fgets(m_sRemovalRow,m_MaxSizeRow,pFile);
}
if(m_sRemovalRow == NULL)
{
// Were removing the last line
// just make it null
memset(m_sRemovalRow,0,sizeof(m_MaxSizeRow));
}
}
else if(i==iRowNum+1)
{
// replace removal line with this.
RemovalLength+=strlen(sTemp);
fgets(sReplaceLineStart, m_MaxSizeRow, pFile);
}
else if(i>iRowNum) {
// start line to replace with
RemovalLength+=strlen(sTemp);
fgets(sTemp, m_MaxSizeRow, pFile);
}
else
{
// were trying to get to the removal line
fgets(m_sCurrentRow, m_MaxSizeRow, pFile);
printf("(not at del row yet)iRow(%d)<iRowNum(%d) %s\n",
i,
m_iNumberOfRows,
m_sCurrentRow);
}
}
{
memmove(m_sRemovalRow,
sReplaceLineStart,
RemovalLength);
}
return 1;
}
FILE is a so-called opaque type, meaning that the application programmer is purposely locked out of its internals as per design - private encapsulation.
Generally one would create an opaque type using the concept of forward declaration, like this:
// stdio.h
typedef struct FILE FILE;
And then inside the private library:
// stdio.c - not accessible by the application programmer
struct FILE
{
// internals
};
Since FILE was forward declared and we only have access to the header, FILE is now an incomplete type, meaning we can't declare an instance of that type, access its members nor pass it to sizeof etc. We can only access it through the API which does know the internals. Since C allows us to declare a pointer to an incomplete type, the API will use FILE* like fopen does.
However, the implementation of the standard library isn't required to implement FILE like this - the option is simply there. So depending on the implementation of the standard library, we may or may not be able to create an instance of a FILE objet and perhaps even access its internals. But that's all in the realm of non-standard language extensions and such code would be non-portable.

Parse JSON message manually in C

I need to parse manually, without external libraries, a JSON message coming from a server, in C language.
The message coming from server would be like:
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 72[CR+LF]
}[CR+LF]
or
{[CR+LF]
"Tmg": "R",[CR+LF]
"STP": 150[CR+LF]
}[CR+LF]
I need the number after STP:. The number is different in each message structure, so I need to get that number from the JSON structure. I can't use external libraries because this code is in an embedded system and exernal code is not allowed.
I tried this following:
int main (){
const char response_message[35] = "{\r\n\"Tmg\":\"R\",\r\n\"STP\":72,\r\n}";
const char needle[8] = "P\":";
char *ret;
ret = strstr(response_message, needle);
printf("The number is: %s\n", ret);
return 0;
}
But obviously, I am getting this result:
The number is: P":72,
}
So I need to only get the number, how can I get this?
Thanks
You can use a hacked solution. Use strstr () to find "STP": then find the following , or } and extract the digits in between.
And that's a hack. Not guaranteed to work. For something that's guaranteed to work, you use a JSON parser.

Unique String generator

I want to make a program (network server-client).
One of the specification for this program is next:
The server will receive the sent packages and save it into a file, with a unique name (generated by the server at the moment the transfer starts.
Ex __tf_"unique_random_string".txt
I made a function that returns a pointer to a "unique" string created.
The problem is: If i stop the server and then start it again it will generate the same names.
Ex:this file names were generated and then i stopped the server.
__ft_apqfwk.txt
__ft_arzowk.txt
__ft_cdyggx.txt
I start it again and i try to generate 3 file names. Them will be the same.
Sorry for my english. I'm still learning it.
My function to generate this "unique string" is:
char *create_random_name(void)
{
const char charset[] = "abcdefghijklmnopqrstuvwxyz";
char *file_name;
int i=0;
int key;
if((file_name = malloc(16 * sizeof ( char )) ) == NULL)
{
printf("Failed to alloc memory space\n");
return NULL;
}
strcpy(file_name,"__ft_");
for(i=5 ; i<11 ; i++)
{
key = rand() % (int)(sizeof(charset)-1);
file_name[i]=charset[key];
}
strcat(file_name,".txt");
file_name[15] = '\0';
return file_name;
}
One option is saving to a file the names that have been used, and using them as a checklist. You also want to seed rand with something like srand(time(NULL)).
another is ignoring the randomisation, and just going in order, e.g. aaa, aab aac...aba ,abb etc. Again, save where your cycle is up to on a file.
Your question seems a little bit unclear but if you want to generate a unique string there are a couple of things you can consider:
Get System timestamp ( yyyy-MM-dd-HH-mm-ss-fff-tt)
Use Random function to generate a random number
Combine this with your function and I am sure you will get a unique string.
Hope it helps !
If it's available, you could avoid manually generating random names that might collide and let the system do it for you (and handle collision resolution by creating a new name) by using mkstemps. This is also safer because it opens the file for you, removing the risk of a random name being generated, verified to be unique, then trying to open it and discovering another thread/process raced in and created it.
char name[] = "/path/to/put/files/in/__ft_XXXXXX.txt";
int fd = mkstemps(name, strlen(".txt"));
if (fd == -1) { ... handle error ... }
After mkstemps succeeds, name will hold the path to the file (it's mutated in place, replacing the XXXXXX string), and fd will be an open file descriptor to that newly created file; if you need a FILE*, use fdopen to convert to a stdio type.
Before calling rand(),--- once and only once---, call srand(time()) to initialize the random number generator.
Before settling on any specific file name, call stat() to assure that file name does not already exist.

play .wav file using c language

I was asked to play .wav files using C language, the compiler I'm using is Devcpp.
I was trying to use the function PlaySound() as below:
PlaySound("C:/Users/wavfiles/13.1.wav", NULL, SND_FILENAME);
If I directly input the directory to the function like this, it is able to successfully play the sound.
However, I want to set the directory as a variable. I create a text file with a list of directory and extract the one that I want, then put it into PlaySound() function. Here is part of my code:
FILE *fw;
char addr[1000]
char schapter[50];
while(fgets(addr, 1000, fw) != NULL) {
if((strstr(addr, schapter)) != NULL) {
printf("\n%s", addr);
PlaySound(addr, NULL, SND_FILENAME);
}
}
In this case, the directory is assigned to addr (addr = "C:/Users/wavfiles/13.1.wav") and then I put addr into PlaySound(), but it doesn't work.
I have been stuck on this problem for a long time and cannot move on.
I would really appreciate it if anyone can give me suggestions or solutions.
Thank you.
The string returned by fgets() contains the terminal newline. You'll need to remove that to get the filename.
An easy way to do this is to use strchr() to locate the newline:
while (fgets(addr, 1000, fw) != NULL) {
char *nl = strchr(addr, '\n');
if (nl) *nl = 0;
…
}

include UNIX utility 'file' in C program

I'm writing a program in C, and I need to known the mime-type of a file.
I have yet searched with Google, and I found that I must include the 'file' UNIX utility in my project.
The source code of file need configure and make. How I can include this in my project? Do I have to crop a part of the source code into a new file.c and file.h?
Do you want to guess the MIME type based on the extension, or do something like file and examine the headers?
To get functionality similar to file, you don't need to include file in your project. Instead, you'll want to use libmagic which file is based on. Unfortunately I'm not aware of a good source of documentation for this, but it's pretty straightforward.
magic_t magic = magic_open(MAGIC_MIME_TYPE);
magic_load(magic, NULL);
char *mime_type = magic_file(magic, "/path/to/file");
magic_close(magic);
Thanks for yours answers and comments.
I solved with this:
const char *w_get_mime(const char *arg, const char *file, int line_no)
{
const char *magic_full;
magic_t magic_cookie;
if(arg == NULL)
w_report_error("called with NULL argument.",file,line_no,__func__,0,1,error);
else if ((magic_cookie = magic_open(MAGIC_MIME) ) == NULL)
report_error("unable to initialize magic library.",0,1,error);
else if (magic_load(magic_cookie, NULL) != 0)
{
magic_close(magic_cookie);
snprintf(globals.err_buff,MAX_BUFF,"cannot load magic database - %s .",magic_error(magic_cookie));
report_error(globals.err_buff,0,1,error);
}
magic_full = magic_file(magic_cookie, arg);
magic_close(magic_cookie);
return magic_full;
}
thanks a lot! :)

Resources