Reading complicated format string with fscanf - c

I have a kindof complicated file format:
{
"color": [
45,
200,
34
],
"docnum": 5183,
"form": "avoir",
"graph": "jdm.N.flat",
"id": 0,
"lang": "fr",
"neighbors": 17,
"pos": "N",
"pzero": true,
"rank": 1,
"score": 0.0028284271,
"type": 1
},
{
"color": [
45,
200,
34
],
"docnum": 22809,
"form": "argent",
"graph": "jdm.N.flat",
"id": 1,
"lang": "fr",
"neighbors": 65,
"pos": "N",
"pzero": false,
"rank": 2,
"score": 0.0028284271,
"type": 1
},
This kind of list goes on, for hundreds of entries. I would like to read in the variable numbers, and a string (docnum, form, id, neighbors, rank, score) so i created a format string for this kind of input:
main(){
FILE* in=fopen("fr.N.bien2","r");
int maxwords=100;
int maxstringlen=100;
char* nodes=malloc(sizeof(char)*maxstringlen*maxwords);
if(!nodes){printf("Nodes couldn't be allocated!\n");}
int i=0;
int* IDs=malloc(sizeof(int)*3*maxwords);
int docnum,nei,rank;
float score;
char* pzero;
while(fscanf(in," { \"color\": [ 45, 200, 34 ], \"docnum\": %i, \"form\": %s \"graph\": \"jdm.N.flat\", \"id\": %i , \"lang\": \"fr\", \"neighbors\": %i , \"pos\": \"N\", \"pzero\": false, \"rank\": %i , \"score\": %f , \"type\" :1 },",&docnum,&nodes[i],&IDs[i],&nei,pzero,&rank,&score))
{
printf("node:%s,ID=%i\n",&nodes[i],IDs[i]);
i++;
}
}
It looks complicated, but it seems to be working, because I get the first instance right. The output is:
>>node:"avoir",,ID=0
However, output stops at that, even though the format is exactly repeating in the file (as you can see in the sample).
Am I missing something important here?
Is there an easier way to read in this kind of data from such a file?

And this complicated format is JSON
As the comments suggest, look for a library instead (they can be found following the previous link) there's many libraries and for different languages as well.
In fact, your question might be already answered here

Related

Support for negative lookbehind regex in app.yaml

I am trying to exclude all source map files, i.e files ending with .map from being uploaded to app engine.
Here's a snippet of the config in app.yaml file.
handlers:
- url: /(.*\\..+(?\<!map))$
static_files: \\1
upload: /(.*\\..+(?\<!map))$
secure: always
However, when deploying, this is the error that I get.
content <{
"error": {
"code": 400,
"message": "The request is invalid.",
"status": "INVALID_ARGUMENT",
"details": [
{
"#type": "type.googleapis.com/google.rpc.BadRequest",
"fieldViolations": [
{
"field": "version.handlers[0].url_regex",
"description": "Value \"/(.*\\..+(?\\\u003c!map))$\" must be a valid regular expression. Details: invalid or unsupported Perl syntax."
},
{
"field": "version.handlers[0].static_files.upload_path_regex",
"description": "Value \"/(.*\\..+(?\\\u003c!map))$\" must be a valid regular expression. Details: invalid or unsupported Perl syntax."
}
]
}
In the app.yaml reference documentation, it implies that it supports POSIX extended regular expression syntax.
Might anyone advice on what should be done to fix this.
You can use
^(.*([^.].{3}|.[^m].{2}|.{2}[^a].|.{3}[^p])|.{0,3})$
See the regex demo. Details:
^ - start of string
(.*([^.].{3}|.[^m].{2}|.{2}[^a].|.{3}[^p])|.{0,3}) - Group 1 matching:
.*([^.].{3}|.[^m].{2}|.{2}[^a].|.{3}[^p]) - any text, and then any of
[^.].{3}| - a char other than a . and then any 3 chars, or
.[^m].{2}| - any char, a char other than m, and then any two chars, or
.{2}[^a].| - any two chars, any char other than a, and then any one char
.{3}[^p] - any three chars, and then a char other than p
| - or
.{0,3} - any zero, one, two or three chars.
$ - end of string.

Extract different set of keys for different nesting level of json

I have the following JSON object, from which I need to retrieve values of certain keys.
For example, in outer JSON object, I need only "timestamp" and "type", next from a nested "meta" object I need only "version", and from nested "payload" I want fields "reason", "type" and "condition" from its nested object "data"
{
"timestamp": "1568961295627",
"type": "test",
"namespace": "internal",
"meta": {
"version": "2.0-test",
"id": "123"
},
"payload": {
"data": {
"reason": "user_request",
"type": "asd",
"condition": "bad"
},
"contentType": "application/json"
}
}
I wrote a function to retrieve such data:
void log_values(json_t *data) {
json_t *obj = NULL;
json_t *nested = NULL;
syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(data, "timestamp")));
syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(data, "type")));
obj = json_object_get(data, "meta");
syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(obj, "version")));
obj = json_object_get(data, "payload");
nested = json_object_get(obj, "data");
syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(nested, "reson")));
syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(nested, "type")));
syslog(LOG_INFO, "%s: ", json_string_value(json_object_get(nested, "condition")));
}
However, the code looks repetitive and I'm wondering if there is any way to generalize it?
The first thing which came to mind is to create a jagged array of pointers to keys needed for each stage, and then walk through the array and retrieve only certain keys on certain nesting level, for example:
char *nested0 = {"timestamp", "type"};
char *nested1 = {"anomaly", "version"};
char *nested2 = {"reason", "type", "condition"};
char *(*keys[])[] = { &nested0, &nested1, &nested2 }
But, this solution does not solve problem regarding where to store key names, which point to nested JSONs (e.g "meta, payload, data").
So, the question is: How to generalize the aforementioned code and what data structure should I use to store names of keys holding a json object and keys for which I need to get values.
Take a look at jsmn, it should fit your needs : https://github.com/zserge/jsmn
exemple of what you could do with jsmn :
[user#machine ~]$ ./json_parser_with_keys test.json timestamp type meta/version
timestamp=1568961295627
type=test
meta/version=2.0-test
[user#machine ~]$ ./json_parser_full test.json
/timestamp=1568961295627
/type=test
/namespace=internal
/meta/version=2.0-test
/meta/id=123
/payload/data/reason=user_request
/payload/data/type=asd
/payload/data/condition=bad
/payload/contentType=application/json
[user#machine ~]$

Can angular-translate support multi-line translations?

I have some translations now that are paragraphs of text which quickly become tedious to manage as single JSON strings:
{
"a": {
"b": "This is a really long translated value I have here..."
}
}
I think ideally I would like to be able to represent the values differently and then transform them. For example as an array of strings that would be concatenated together:
{
"a": {
"b": [
"This is a really long ",
"translated value ",
"I have here..."
]
}
}
Does angular-translate have the appropriate hooks to achieve this?? And if so, what is the best approach?

Print string from 2 dimensional character array

I've looked around and tried different syntax's for this but I can't seem to get it to work. I know this is elementary, but it's something that shouldn't take too long to figure out.
I have the character array...
char *roster[2][14] = {
{"13", "10", "24", "25", "15", "1", "00", "4", "11", "23", "22", "32", "3", "35"},
{"Isaiah Briscoe", "Jonny David", "EJ Floreal", "Dominique Hawkins", "Isaac Humphries", "Skal Labissiere", "Marcus Lee", "Charles Matthews", "Mychal Mulder", "Jamal Murray", "Alex Poythress", "Dillon Pulliam", "Tyler Ulis", "Derrick Willis"}
};
Then I'm generating a random element from that array...
random = rand() % 14;
printf("What is %s 's number?", roster[2][random]);
Then I try to print it out, but it fails...
printf("What is %s 's number?", roster[2][random]);
It outputs
What is (null) 's number?
and lldb shows that the printf statement jumps into...
libsystem_c.dylib`strlen:
-> 0x7fff9a596d32 <+18>: pcmpeqb (%rdi), %xmm0
0x7fff9a596d36 <+22>: pmovmskb %xmm0, %esi
0x7fff9a596d3a <+26>: andq $0xf, %rcx
0x7fff9a596d3e <+30>: orq $-0x1, %rax
Array index starts from 0.
For char *roster[2][14];, the possible indices are
roster[0][random];
roster[1][random];
Arrays in c start at 0, so if you declare:
char *roster[2]
Then you can only reference roster[0] and roster[1].
printf("What is %s 's number?", roster[2][random]);
You access index out of bound invoking undefined behaviour .
Because you can have indices roster[0][random] and roster[1][random] not roster[2][random] because it is declared as -
char *roster[2][14] = {
{"13", "10", "24", "25", "15", "1", "00", "4", "11", "23", "22", "32", "3", "35"},
{"Isaiah Briscoe", "Jonny David", "EJ Floreal", "Dominique Hawkins", "Isaac Humphries", "Skal Labissiere", "Marcus Lee", "Charles Matthews", "Mychal Mulder", "Jamal Murray", "Alex Poythress", "Dillon Pulliam", "Tyler Ulis", "Derrick Willis"}
};
You can print these -
printf("What is %s 's number?", roster[1][random]);
Or -
printf("What is %s 's number?", roster[0][random]);

parse json arrays using cJSON library

First off, this is a very broad question, and it might come across as me asking for the community to write my code for me. That is not my intent, but I am so lost, I don't know how to give enough information.
I am attempting to use the cJSON library, written by Dave Gamble,
I found this is very useful to use for my embedded device for JSON parse and composing.
to read in the following JSON array
{
"name": "Jack",
"types":[23,56,78],
"format": {
"type": "rect",
"width": 1920, }
}
.. and parsing the getting the object worked with this method
cJSON *format = cJSON_GetObjectItem(json,"format");
int framerate = cJSON_GetObjectItem(format,"width")->valueint;
but I am not able to parse the key "name" and object simple key value ,
I tried this
cJSON *array = cJSON_GetArrayItem(json,"types");
int value = cJSON_GetArrayItem(format1,1)->valueint;
but did not work, how to parse the array object and simple key value..
Your json is just fine. You can iterate through array of values in cJSON:
cJSON * array = cJSON_GetObjectItem(json, "types");
for (i = 0 ; i < cJSON_GetArraySize(array) ; i++)
{
printf("%d ",cJSON_GetArrayItem(array, i)->valueint);
}
will print
23 56 78
I think JSON element should respect key:value format.
{
"name": "Jack",
"types":[{"type" : 23}, {"type" : 56}, {"type":78}],
"format": {
"type": "rect",
"width": 1920, }
}

Resources