|
I know how to do this in C++, but a bit rusty on C,
char line[1024]="d(Text1)b(ID1)n(node1)d(Text2)b(ID2)n(node2)d(Text3)b(ID3)n(node3)...
I would like to parse the line above into item0 = d(Text1)b(ID1)n(node1), item2 - d(Text2)b(ID2)n(node2)... and so forth
char *py;
char *px = line;
while ((py=strstr(px,"d(")) != NULL) {
px++;
}
return 0;
Thanks
|
|
|
|
|
|
so, is it "n(nodename)" that signals the end of a 'node' and "d(whatever)" for the start?
i always find state-machines the easiest way to do simple parsing.
off the top of my head...
typedef struct item_t
{
char d[100];
char b[100];
char n[100];
} item;
const char *consume_between_parens(const char *p, char *out)
{
if (*p!='(') return NULL;
p++;
while (*p)
{
if (p==')')
{
p++;
break;
}
*out = *p;
out++; p++;
}
return p;
}
void parse(const char *p, itemArray array ... some array thing)
{
enum {wantD, wantB, wantN} state = wantD;
item * curItem = null;
while (*p)
{
switch (state)
{
case wantD:
if (*p=='d')
{
curItem = malloc(sizeof(item));
p = consume_between_parens(p, curItem->d);
state = wantB;
}
else error
break;
case wantB:
if (*p=='b')
{
p = consume_between_parens(p, curItem->b);
state = wantN;
}
else error
case wantN:
if (*p=='n')
{
p = consume_between_parens(p, curItem->n);
addToArray(array, curItem);
state = wantD;
}
else error
break;
default:
error;
}
p++;
}
while
|
|
|
|
|
Fantastic! I did get it to work with very minor modifications.
typedef struct item_t
{
char d[8192];
char n[8192];
char i[8192];
} item;
char *consume_between_parens(char *p, char *out)
{
p++;
if (*p!='(') return NULL;
int paren_count = 1;
p++;
while (*p)
{
if (*p=='(')
paren_count++;
if (*p==')')
paren_count--;
if(!paren_count) break;
*out = *p; out++; p++; }
return p;
}
void parse(char *p)
{
item * curItem = NULL;
while (*p)
{
if (*p=='d')
{
curItem = (item*)malloc(sizeof(item));
p = consume_between_parens(p, curItem->d);
}
if (*p=='n')
{
p = consume_between_parens(p, curItem->n);
}
if (*p=='i')
{
p = consume_between_parens(p, curItem->i);
}
p++;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
char *text ="1:7\22\\d(2011)n(0)i(711910)d(2010)n(1)i(711911)";
parse(text);
return 0;
}
|
|
|
|
|
Have you looked at strtok() ?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
I just did. Thanks for mentioning it, this function actually makes things a lot easier, since it does most of the pointer work for you. I will give it a try.
Thanks again
|
|
|
|
|
I have one more question C- related:
char *getLine(char *p, char *out)
{
int Dees = 0;
char *px = p;
p++;
if (*p!='(') return NULL;
int paren_count = 1;
while (*px)
{
if(*px=='d')
{
Dees++;
if(Dees >1 && *(px+1)=='(') break;
}
*out = *px; out++; px++; }
return px;
}
char *px="d(text)n(0)l(1)d(text2)n(1)l(2)...";
char line[8192];
char *py = getLine(px,line);
In the main program, after calling the function getLine(), I do get line correctly as in "d(text)n(0)l(1)" but filled with garbage after that as its trying to fill out 8192 characters. How do I make it not fill the rest of the unused space. Note, I don't know the size of "line" as it varies, but I need it big enough. I know strcpy could be useful here somewhere, just can't get it to work.
I also tried in getLine() the following:
char field[4095];
strcpy(field,out);
But nothing gets copied, out shows null in the debugger.
Thanks
modified 12-Dec-11 12:00pm.
|
|
|
|
|
After the while() loop, you need to terminate out with a '\0' character.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
modified 12-Dec-11 14:26pm.
|
|
|
|
|
Fabulous!
while (*px != '\0') did the trick. I have to admit i don't quite get it though, In the string "d(2011)n(0)i(711910)d(2010)n(1)i(711911)", I am telling to break out when it sees the next 'd(', so why do I need the terminating character? Could you clarify?
Thanks much
|
|
|
|
|
Software2007 wrote:
while (*px != '\0')
did the trick.
Not sure how, since these three staments are identical:
while (*px)
while (*px != 0)
while (*px != '\0')
What you should have done instead is add a '\0' character to out after the while() loop. That way, it'll be properly (i.e., null) terminated.
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|
|
|
Hello All, I am using visual studio 2008 and maniplulating double addition.
double a = 1.5000010
double b = 0.0000090;
double c = a+b;
The output I am expecting here is 1.5000100 but the actual output comes as 1.5000099999999998.
I dont have to consider more than 7 fractional points so the it looks like 1.5000099.
How do i convert or store this in to the format which i like? that means 1.5000100.
Is there any built-in method or win32 API available to do this?
Thanks in advance.
|
|
|
|
|
May be this will help you
#include<stdio.h>
void main()
{
double a,b,c;
a = 1.5000010;
b = 0.0000090;
c = a + b;
printf("%.7f\n",c);
}
Every new day is another chance to change your life.
|
|
|
|
|
Hi Chandrasekhran, thanks for your reply.
I want to store this in to another double variable for calculation and not for printing in to console.
|
|
|
|
|
Maybe its a roundabout way.
Use the sprintf and save the result in a buffer.
sprintf(buffer,"%.7f\n",c);
Then convert the buffer which is a char array to double using "atof"
d = atof(buffer);
where "d" is a double data type.
and then use d in your calculations.
Every new day is another chance to change your life.
|
|
|
|
|
mutpan wrote: How do i convert or store this in to the format which i like? that means 1.5000100.
You shouldn't do that.
You should store it 'as is' and use 'the format I like' just when you need to output it.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Good point 
|
|
|
|
|
|
File this away for future reference:
The "imprecision" is in producing the OUTPUT, the conversion of the binary / computer representation of the number into the string of characters that you display. This is true regardless of whether it is you printing the value or the debugger displaying it for you. Both processes need to take the binary value and convert it to a string of characters for your eyes.
If you a computing a value and wish to use it in other compututations then always carry the binary value around, don't convert it to a string and then reconvert it to binary. The binary value is as precise as you are going to get, converting it back and forth only adds "imprecision"
Computer binary representations (Base 2) and printed represetnations (in Base 10) are inherently incompatible and can only be approximated. You control the approximation with the format specifier for how many digits you want to see.
|
|
|
|
|
Everyone is doing a good job explaining this.
Doubles only provide approximations of decimal numbers.
As another commentator pointed out, there are mathematical difficulties in converting from binary to decimal and back again.
The difference in your output, and the number you expect, is close enough for science.
But for other systems, like money, not good quite enough.
To get the results you want you might roll your own number class, or use one of the many public ones that are available.
Maybe this one?
CLN - Class Library for Numbers
|
|
|
|
|
True about money values, floats / doubles are just no good. That's why, back in the 60's, IBM invented a 'decimal' machine as opposed to the traditional 'binary' machine, the IBM7070. Eventually, they added an entire 'packed decimal' arithmatic package to the IBM360 line so that financial applications written in COBOL would work with proper precision.
|
|
|
|
|
That was a BCD system wasn't it?
Google turns up a lot of hits on that numbering system too.
|
|
|
|
|
The 7070 used a two-out-of-five system for the decimal representation, the 360 was BCD for the packed decimal.
|
|
|
|
|
Windows 2008 Server, Access 2000 and 2010 (fails on both), Visual Studio 2010
Long story short, I'm trying to use the following query:
SELECT PARAM.param INTO CHKPARAM FROM PARAM WHERE ( ( PARAM.param = 'Y' ) )
When I execute this in my code it works about 15% of the time. If I add a 3.5 second sleep after the execution of this query before the "read" it seems to work about 95% of the time. The process looks something like this:
1. SELECT INTO chkparam (it should create the table and add 1 record to the table)
2. select from the table looking for the record
However the SELECT INTO doesn't always populate the table with the Y. Yes I verified that the table "param" does have a Y. My best guess is the query isn't completing before the code is executed. Is there some way to force completion of the query/transaction? I was alawys under the impression that control wasn't passsed back to the calling procedure until the function was completed. However it seems like I'm getting control back before the function is completing.
This is part of our test network, on our live older system we have been using DAO with the same query (obviously different implementation) for 10+ years with no problems. We found that using DAO on our new network slowed down the queries (plus you can't use it with anything new), thus the change to ODBC.
This is the code in quesiton (in the live version some of this is replaced by varaibles, but we have hardcoded this for testing for now until it works):
strSQL = _T("SELECT PARAM.param INTO CHKPARAM FROM PARAM WHERE ( ( PARAM.param = 'Y' ) ) ")
try
{
cdw.ExecuteSQL(strSQL);
Sleep(3500);
CString xstrSQL = _T("SELECT TOP 1 * FROM CHKPARAM");
CRecordset getinfoonly(&cdw);
getinfoonly.Open(CRecordset::snapshot, xstrSQL );
if (!getinfoonly.IsEOF())
{
CString tstring1;
short indx = 0;
getinfoonly.GetFieldValue(indx, tstring1);
}
else
getinfoonly.Close(); }
catch( CDBException* e )
{
AfxMessageBox(_T("Given SQL Expression \n") + strSQL + e->m_strError );
ok = FALSE;
}
|
|
|
|
|
MacRaider4 wrote: cdw.ExecuteSQL(strSQL);
How long is this statement taking to complete? Would SetQueryTimeout() be of any help?
"One man's wage rise is another man's price increase." - Harold Wilson
"Fireproof doesn't mean the fire will never come. It means when the fire comes that you will be able to withstand it." - Michael Simmons
"Show me a community that obeys the Ten Commandments and I'll show you a less crowded prison system." - Anonymous
|
|
|
|