How to count statements in C ignoring the comments - count

int Emptylines(FILE *fp);
int Numberofstatements(FILE *fp);
int main() {
FILE *fp = NULL;
FILE *fp1 = NULL;
int n1, n2;
char fname[255], fname1[255];
printf("Enter file name for reading");
fflush(stdin);
scanf("%s", &fname);
fp = fopen(fname, "r");
if (fp == NULL) {
printf("File with name %s couldn't be open", fname);
exit(1);
}
n1 = Emptylines(fp); // this is for empty lines
n2 = Numberofstatements(fp);
printf("Insert file name for writing");
fflush(stdin);
scanf("%s", &fname1);
fp1 = fopen(fname1, "w+");
fprintf(fp1, "The number of empty lines=%d", n1);
fprintf(fp1, "The number of statements=%d", n2);
fclose(fp);
fclose(fp1);
return 0;
}
int Numberofstatements(FILE *fp) {
char line[128];
int nofstatements = 0;
while (fgets(line, sizeof line, fp) != NULL) {
if (strstr(line, "if") != 0)
nofstatements++;
}
return nofstatements;
}
I need to count all statements like if, do, while, break, etc. as well as empty lines and then save the result in a new file. I succeed in counting the empty lines but I have no idea how to count the statements. I tried 2 different ways but both failed.
I also need to ignore comments while reading the code, so if there is a for, while, etc. in the comments it shouldn't be counted.

A very basic answer addressing the fundamental issue (although there are others).
When you call int Numberofstatements(FILE *fp) you already reached the end of file in int Emptylines(FILE *fp); so you must add the statement
rewind(fp);
before trying to parse the file for a second time. Good luck with developing this.

OP asks: "Any ideas ?"
To do properly, suggest reading 1 char at a time. Keep track if you are in 1) on an include line, 2) inside a " " 3) inside a ' ' 4) in a // comment 5) inside a /* comment or 6) just plain code (watch for escape sequences). When in plain code look for the keywords do, while, etc. and all the while count the '\n'.
To do correctly - this is not an easy task - about 10x the code you have posted.
Sample beginning of a state machine.
state = plaincode;
while ((c = getc()) != EOF) {
switch (state) {
slashslash_commnet:
if (c == '\n) state = plaincode;
break;
plaincode:
if (c == '/') {
c2 = getc();
if (c2 == '/') { state = slashslash_commnet; break; }
else if (c2 == '*') { state = slashstar_commnet: break; }
else unget(c2);
else if (c == '\"') {
...

Related

printf("%s",stringName) prints the wrong text but only once

I have a menu function, in which I input a question and two options, then the user choses one. It works just fine everytime but one ; I call
if (menu("ou est le corps?","interieur ","exterieur")==1)
{
but instead of printing "interieur " It shows "p?"
it works just fine without the space, but I need to make a space and \n does quite the same thing.
I have another call of this function, with \n which works fine so I have no idea about why this wouldn't work. Anyone has got an idea?
PS : the value of choix1 is then sent via bluetooth, and there it stays intact.
PPS : tell me if something is unclear, I'm not naturally english
PPPS(sorry) : tried to run the same code again, it seems to print a random character followed by "?", I had twice "p?", once "?" and once " '?"
[updates] once "#?"
int menu (String texte, String choix1, String choix2)
{
envoye = 0;
rxValue = "0";
while (digitalRead(M5_BUTTON_HOME) != LOW && rxValue == "0")
{
heure();
M5.Lcd.setTextSize(2);
M5.Lcd.print(texte);
M5.Lcd.printf("\n");
if (selec == 0)
{
M5.Lcd.printf("->%s %s", choix1, choix2);
}
else
{
M5.Lcd.printf(" %s ->%s", choix1, choix2);
}
if (M5.BtnB.read() != 0)
{
if (selec == 0)
{
selec = 1;
}
else
{
selec = 0;
}
while (M5.BtnB.read() != 0)
{
if(digitalRead(M5_BUTTON_HOME) == LOW)
{
M5.Lcd.fillScreen(BLACK);
delay(1000);
if(digitalRead(M5_BUTTON_HOME) == LOW)
{
choix=50;
heure();
delay(1000);
return 1;
}
}
}
}
if (deviceConnected && envoye == 0)
{
sendchoix(texte, choix1, choix2);
envoye++;
}
}
if (rxValue != "0")
{
recuble = &rxValue[0];
selec = atoi(recuble) - 1;
rxValue = "0";
}
M5.Lcd.fillScreen(BLACK);
delay(300);
return selec;
}
int menu (String texte, String choix1, String choix2) {
[...]
M5.Lcd.printf("->%s %s", choix1, choix2);
You cannot treat String objects as const char*, which is what the format specifier %s is expecting. String is an Arduino class for storing.. strings/character data, but an object of this class is not equivalent to the raw pointer to the data.
For that, you need to call the c_str() method on the String object to get the C-String pointer to the data, as shown in the documentation [1].
[..]
M5.Lcd.printf("->%s %s", choix1.c_str(), choix2.c_str());
[..]
[1] https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/c_str/

Finding duplicates in Array of structure

I am using QT to search for duplicate entries in a structure.I have a struct as follows:
struct information{
QString fname;
QString lname;
QString gender;
QString age;
QString cod;
};
I have this code here which has bool variable for each variable in the structure and changes the bool value to true if data in the two arrays are the same and checks to see if all the bool values are true and prints out the two lines where duplicates are.
for (int i=0; i<numlines; i+=1){
for (int j=i+1; j<numlines; i+=1){
bool fname = false;
bool lname = false;
bool age = false;
bool cod = false;
bool gender= false;
if (person[i].fname == person[j].fname){
fname = true;
//qDebug() <<fname;
}
if (person[i].lname == person[j].lname){
lname = true;
//qDebug() <<lname;
}
if (person[i].gender == person[j].gender){
gender = true;
//qDebug() <<gender;
}
if (person[i].age == person[j].age){
age = true;
//qDebug() <<age;
}
if (person[i].cod == person[j].cod){
cod = true;
//qDebug() <<cod;
}
if (fname==true && lname==true && gender==true && age==true && cod==true){
//print out where duplicate are.
//duplicates at line i+1 and j+1
}
}
}
When I click my duplicate check button which activates the code it enters the loop once and terminates the program unexpectedly. Any suggestions?
for (int i=0; i<numlines; i+=1){
for (int j=i+1; j<numlines; i+=1){
// ^
Simple problem (probably cut'n'paste error) - you need to increment j, not i.
And, as an aside, you could probably refactor your code to make it a bit simpler since, if any field doesn't match, you can just move to the next, something like (pseudo-code):
for i = 0 to (sz - 2) inclusive:
for j = (i + 1) to (sz - 1) inclusive:
if person[i].fname != person[j].fname: continue
if person[i].lname != person[j].lname: continue
if person[i].age != person[j].age: continue
if person[i].cod != person[j].cod: continue
if person[i].gender != person[j].gender: continue
// they're all equal at this point, log the fact.
This removes the need for those boolean variables.
But, if you do decide to keep the booleans, you can make your code more readable by choosing their names carefully. I tend to prefer booleans to be readable such as customerIsDead or managerHasPsychopathicTendencies. That way, they "flow" easier when reading the code:
if (sameFName && sameLame && sameGender && sameAge && sameCod) {
You should generally never have compare a boolean value with true or false since that just gives you another boolean and, as per reductio ad absurdum, where do you stop?
if ((((x == true) == true) != false) == true) ...

Adding Firebase data, dots and forward slashes

I try to use firebase db,
I found very important restrictions, which are not described in firebase help or FAQ.
First problem is that symbol: dot '.' prohibited in keys,
i.e. firebase reject (with unknown reason) next:
nameRef.child('Henry.Morgan#caribbean.sea').set('Pirat');
Second problem with forward slashes in your keys '/',
when you try to add key like this
{'02/10/2013': true}
In firebase you can see:
'02': {
'10': {
'2013': true
}
}
Have you got any ideas how to solve it (automatically)?
May be set some flag that it is string key with all symbols?
Of course, I can parse/restore data every time before write and after read, but...
By the way '.' '/' - all restricted symbols for firebase ?
The reason that adding a child 02/10/2013 creates a structure in Firebase is because the forward slashes are resulting in the creation of a new level.
So the line I assume you are using something similar to: firebaseRef.child('02/10/2013').set(true) is equivalent to firebaseRef.child('02').child('10').child('2013').set(true).
To avoid the problems of not being able to use the following characters in reference key names (source),
. (period)
$ (dollar sign)
[ (left square bracket)
] (right square bracket)
# (hash or pound sign)
/ (forward slash)
we can use one of JavaScript's built in encoding functions since as far as I can tell, Firebase does not provide a built in method to do so. Here's a run-through to see which is the most effective for our purposes:
var forbiddenChars = '.$[]#/'; //contains the forbidden characters
escape(forbiddenChars); //results in ".%24%5B%5D%23/"
encodeURI(forbiddenChars); //results in ".%24%5B%5D%23%2F"
encodeURIComponent(forbiddenChars); //results in ".%24%5B%5D%23%2F"
Evidently, the most effective solution is encodeURIComponent. However, it doesn't solve all our problems. The . character still poses a problem as shown by the above test and trying to encodeURIComponent your test e-mail address. My suggestion would be to chain a replace function after the encodeURIComponent to deal with the periods.
Here's what the solution would look like for your two example cases:
encodeURIComponent('Henry.Morgan#caribbean.sea').replace(/\./g, '%2E') //results in "Henry%2EMorgan%40caribbean%2Esea"
encodeURIComponent('02/10/2013'); //results in "02%2F10%2F2013"
Since both the final results are safe for insertion into a Firebase as a key name, the only other concern is decoding after reading from a Firebase which can be solved with replace('%2E', '.') and a simple decodeURIComponent(...).
I faced the same problem myself, and I have created firebase-encode for this purpose.
Unlike the chosen answer, firebase-encode encodes only unsafe characters (./[]#$) and % (necessary due to how encoding/decoding works).
It leaves other special characters that are safe to be used as firebase key while encodeURIComponent will encode them.
Here's the source code for details:
// http://stackoverflow.com/a/6969486/692528
const escapeRegExp = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
const chars = '.$[]#/%'.split('');
const charCodes = chars.map((c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
const charToCode = {};
const codeToChar = {};
chars.forEach((c, i) => {
charToCode[c] = charCodes[i];
codeToChar[charCodes[i]] = c;
});
const charsRegex = new RegExp(`[${escapeRegExp(chars.join(''))}]`, 'g');
const charCodesRegex = new RegExp(charCodes.join('|'), 'g');
const encode = (str) => str.replace(charsRegex, (match) => charToCode[match]);
const decode = (str) => str.replace(charCodesRegex, (match) => codeToChar[match]);
I wrote this for Java (since I came here expecting a java implementation):
public static String encodeForFirebaseKey(String s) {
return s
.replace("_", "__")
.replace(".", "_P")
.replace("$", "_D")
.replace("#", "_H")
.replace("[", "_O")
.replace("]", "_C")
.replace("/", "_S")
;
}
public static String decodeFromFirebaseKey(String s) {
int i = 0;
int ni;
String res = "";
while ((ni = s.indexOf("_", i)) != -1) {
res += s.substring(i, ni);
if (ni + 1 < s.length()) {
char nc = s.charAt(ni + 1);
if (nc == '_') {
res += '_';
} else if (nc == 'P') {
res += '.';
} else if (nc == 'D') {
res += '$';
} else if (nc == 'H') {
res += '#';
} else if (nc == 'O') {
res += '[';
} else if (nc == 'C') {
res += ']';
} else if (nc == 'S') {
res += '/';
} else {
// this case is due to bad encoding
}
i = ni + 2;
} else {
// this case is due to bad encoding
break;
}
}
res += s.substring(i);
return res;
}
Character limitations are documented at https://www.firebase.com/docs/creating-references.html - you cannot use '.', '/', '[', ']', '#', and '$' in key names. There is no automatic way of escaping these characters, I'd recommend avoiding their use altogether or creating your own escaping/unescaping mechanism.
If you're using Swift 3, this works for me (try it in a playground):
var str = "this.is/a#crazy[string]right$here.$[]#/"
if let strEncoded = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics) {
print(strEncoded)
if let strDecoded = strEncoded.removingPercentEncoding {
print(strDecoded)
}
}
I got annoyed with this problem so I took the answer from #sushain97 (thanks!) and built a deep encoder/decoder.
https://www.npmjs.com/package/firebase-key-encode
Basic usage:
var firebaseKeyEncode = require('firebase-key-encode');
firebaseKeyEncode.encode('my.bad.key');
// Output: my%2Ebad%2Ekey
Deep Usage:
var firebaseKeyEncode = require('firebase-key-encode');
var badTree = {
"pets": [
{
"jimmy.choo": 15}
],
"other.key": 5
}
firebaseKeyEncode.deepEncode(badTree);
// Output: {
// "pets": [
// {
// "jimmy%2Echoo": 15}
// ],
// "other%2Ekey": 5
// }
Personally, I found a simple and easy hack for this same problem I encountered
I took the dateTime string and convert it using replace('/','|')
the result will be something like this 2017|07|24 02:39:37 instead of 2017/07/24 02:39:37.
Even though it is not what OP asks,
but in my experience rather than using such dubious keys it is better to let .push() create an id,
and other things - e-mail, date etc. save as content of the dedicated fields.
$id: {
email: "Henry.Morgan#caribbean.sea"
}
P.S. Don't try to save volume by inserting what should be content into the key.
Premature optimization is the root of all evil (c).
Efficient C# implementation (for Unity and .net). Based on the answer from #josue.0.
public static string EncodeFirebaseKey(string s) {
StringBuilder sb = new StringBuilder();
foreach (char c in s) {
switch (c) {
case '_':
sb.Append("__");
break;
case '$':
sb.Append("_D");
break;
case '.':
sb.Append("_P");
break;
case '#':
sb.Append("_H");
break;
case '[':
sb.Append("_O");
break;
case ']':
sb.Append("_C");
break;
case '/':
sb.Append("_S");
break;
default:
sb.Append(c);
break;
}
}
return sb.ToString();
}
public static string DecodeFirebaseKey(string s) {
StringBuilder sb = new StringBuilder();
bool underscore = false;
for (int i = 0; i < s.Length; i++) {
if (underscore) {
switch (s[i]) {
case '_':
sb.Append('_');
break;
case 'D':
sb.Append('$');
break;
case 'P':
sb.Append('.');
break;
case 'H':
sb.Append('#');
break;
case 'O':
sb.Append('[');
break;
case 'C':
sb.Append(']');
break;
case 'S':
sb.Append('/');
break;
default:
Debug.LogWarning("Bad firebase key for decoding");
break;
}
underscore = false;
} else {
switch (s[i]) {
case '_':
underscore = true;
break;
default:
sb.Append(s[i]);
break;
}
}
}
return sb.ToString();
}
Python implementation
_escape = {'&': '&&',
'$': '&36',
'#': '&35',
'[': '&91',
']': '&93',
'/': '&47',
'.': '&46'}
_unescape = {e: u for u, e in _escape.items()}
def escape_firebase_key(text):
return text.translate(str.maketrans(_escape))
def unescape_firebase_key(text):
chunks = []
i = 0
while True:
a = text[i:].find('&')
if a == -1:
return ''.join(chunks + [text[i:]])
else:
if text[i+a:i+a+2] == '&&':
chunks.append('&')
i += a+2
else:
s = text[i+a:i+a+3]
if s in _unescape:
chunks.append(text[i:i+a])
chunks.append(_unescape[s])
i += a+3
else:
raise RuntimeError('Cannot unescape')
And a few test cases:
test_pairs = [('&hello.', '&&hello&46'),
('&&&', '&&&&&&'),
('some#email.com', 'some#email&46com'),
('#$[]/.', '&35&36&91&93&47&46')]
for u, e in test_pairs:
assert escape_firebase_key(u) == e, f"escaped '{u}' is '{e}', but was '{escape_firebase_key(u)}'"""
assert unescape_firebase_key(e) == u, f"unescaped '{e}' is '{u}', but was '{unescape_firebase_key(e)}'"
try:
unescape_firebase_key('&error')
assert False, 'Must have raised an exception here'
except RuntimeError as ex:
assert str(ex) == 'Cannot unescape'
const encodeKey = s => s.replace(/[\.\$\[\]#\/%]/g, c => '%' + c.charCodeAt(0).toString(16).toUpperCase())
const decodeKey = s => s.replace(/%(2E|24|5B|5D|23|2F|25)/g, decodeURIComponent)
console.log(encodeKey('.$[]#/%23')) // %2E%24%5B%5D%23%2F%2523
console.log(decodeKey(encodeKey('.$[]#/%23'))) // .$[]#/%23
import re
import urllib.parse
encode_key = lambda s: re.sub('[\.\$\[\]#\/%]', lambda c: f'%{ord(c.group()):X}', s)
decode_key = lambda s: re.sub('%(2E|24|5B|5D|23|2F|25)', lambda c: urllib.parse.unquote(c.group()), s)
print(encode_key('.$[]#/%23')) # %2E%24%5B%5D%23%2F%2523
print(decode_key(encode_key('.$[]#/%23'))) # .$[]#/%23

Find / search case sensitive

Is it possible to do a case sensitive find (search) in Dynamics AX 2009?
For example, when I am searching for "address", I don't want to see "Address" in the results.
Jan,
There IS a way to do it using standard Axapta X++. When you use the find screen there is a tab called 'Filter' where you can place code to do the filtering (no need to complete the fields on the name & location tab). The below code is for illustration purposes only as the below code is not complete and has not been finalised (I leave that to you).
str toMatch = 'Address';
str string;
str char, charMatch;
int i, pos;
boolean ret;
;
pos = strScan(_treeNodeName, toMatch, 1, strLen(_treeNodeName));
string = subStr(_treeNodeName, pos, strLen(toMatch));
if (string)
{
ret = true;
for (i=1;i<=strLen(toMatch);i++)
{
char = subStr(toMatch, i, 1);
charMatch = subStr(string, i, 1);
if (char2num(char,1) != char2num(charMatch,1))
{
ret = false;
}
}
if (ret)
{
return ret;
}
}
pos = strScan(_treeNodeSource, toMatch, 1, strLen(_treeNodeSource));
string = subStr(_treeNodeSource, pos, strLen(toMatch));
if (string)
{
ret = true;
for (i=1;i<=strLen(toMatch);i++)
{
char = subStr(toMatch, i, 1);
charMatch = subStr(string, i, 1);
if (char2num(char,1) != char2num(charMatch,1))
{
ret = false;
}
}
if (ret)
{
return ret;
}
}
return false;
If you have a look at the Find form window that appears when you do a find, look at the properties, this helps you narrow you down your search, unsure about a like-for-like exact match i.e. "address" and blocking out "Address".
No you cannot.
As mentioned in this answer, the find form uses the match method, which is documented on msdn here.
To quote MSDN;
Remarks
The system does not differentiate between lower and upper case.

Where to find or duplicate code that produces HttpRequestValidationException

I have some PageMethods (static methods in a page marked with <WebMethod>) defined on some pages and call them using an ajax call. This POST to the server apparently doesn't trigger the ASP.NET code that would raise HttpRequestValidationException if the data sent is deemed possible XSS, so I'd like to duplicate that checking code to run it in my page methods.
Anyone know the details of that code or where I can find it? I looked in the MS AntiXss library, but it only does encoding, not actually checking input, AFAIK.
Edit: Or point me in the direction of code or a library that does some similar checking.
Analyzing the stack trace when a System.Web.HttpRequestValidationException is raised we can find out what code is throwing it.
System.Web.HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (IdentifierTextBox="
at System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection)
Using Reflector we find that ValidateString is calling: RequestValidator.Current.IsValidRequestString, which in turn calls CrossSiteScriptingValidation.IsDangerousString which is:
internal static bool IsDangerousString(string s, out int matchIndex)
{
matchIndex = 0;
int startIndex = 0;
while (true)
{
int num2 = s.IndexOfAny(startingChars, startIndex);
if (num2 < 0)
{
return false;
}
if (num2 == (s.Length - 1))
{
return false;
}
matchIndex = num2;
char ch = s[num2];
if (ch != '&')
{
if ((ch == '<') && ((IsAtoZ(s[num2 + 1]) || (s[num2 + 1] == '!')) || ((s[num2 + 1] == '/') || (s[num2 + 1] == '?'))))
{
return true;
}
}
else if (s[num2 + 1] == '#')
{
return true;
}
startIndex = num2 + 1;
}
}

Resources