code snippet

R

Rui Maciel

Bill said:
I don't know. I was going to manually type data into a a text file and
read using fscanf. Maybe a parser is what I want.


Unless it's a "write once, run once" kind of thing, developing a proper
parser could considerably help you on that. For example, you would be able
to abandon your get() function and instead call a function defined
specifically to handle an object of type int/double/whatever whenever your
parser stumbled on a specific token.


Rui Maciel
 
G

Geoff

I can change the parameters I guess but I want this function to return
at times an unsigned int, sometimes a double, sometimes a signed int.
The only way I know to return multiple types without getting into the
possibility of structs is a generic pointer to point to where the values are
stored.

Why are you intent on avoiding structures? Since a stock price, volume
and date are naturally carried together a structure would be the
natural object to keep them associated. Your get function becomes much
more simple if you avoid opening the file with the get function and
open the file from the caller or at a higher level and simply pass the
file pointer to it.

#include <stdio.h>

struct stock
{
double price;
long int date;
unsigned int number;
};

int get_stock_data(FILE *fp, stock *pv)
{
int check;

check = fscanf(fp, "%u %df %ul", &pv->number, &pv->price,
&pv->date);
if (check == EOF || check != 3)
{
printf("%d\n", ferror(fp));
clearerr(fp);
return 1;
}
return 0;
}
 
B

Bill Cunningham

Geoff said:
Why are you intent on avoiding structures?

Well I guess it could work.

Since a stock price, volume
and date are naturally carried together a structure would be the
natural object to keep them associated. Your get function becomes much
more simple if you avoid opening the file with the get function and
open the file from the caller or at a higher level and simply pass the
file pointer to it.

#include <stdio.h>

struct stock
{
double price;
long int date;
unsigned int number;
};

int get_stock_data(FILE *fp, stock *pv)
{
int check;

check = fscanf(fp, "%u %df %ul", &pv->number, &pv->price,
&pv->date);
if (check == EOF || check != 3)
{
printf("%d\n", ferror(fp));
clearerr(fp);
return 1;
}
return 0;
}

Would that struct if not put into a header need to be extern if my other
functions were in files of their own?


Bill
 
B

Bill Cunningham

Rui said:
Unless it's a "write once, run once" kind of thing, developing a
proper parser could considerably help you on that. For example, you
would be able to abandon your get() function and instead call a
function defined specifically to handle an object of type
int/double/whatever whenever your parser stumbled on a specific token.

Sounds like strtok would come into play here.

Bill
 
B

Bill Cunningham

Rui said:
Unless it's a "write once, run once" kind of thing, developing a
proper parser could considerably help you on that. For example, you
would be able to abandon your get() function and instead call a
function defined specifically to handle an object of type
int/double/whatever whenever your parser stumbled on a specific token.

Does it sound like I want a parser using line numbers for the data.

1 12.35 122011
2 11.75 122111

So if I wanted to pull certain data like the 2nd column numbers 1 through n
an unsigned int number variable would be what was needed. Pass all that data
to a parameter of a function.
 
R

Rui Maciel

Bill said:
Does it sound like I want a parser using line numbers for the data.

1 12.35 122011
2 11.75 122111

So if I wanted to pull certain data like the 2nd column numbers 1 through
n an unsigned int number variable would be what was needed.

From what I understood, there appears to be two distinct objectives, which
are:
- parse a text document which is described in a specific language
- operate on the data which has been extracted by the parser

The parser is trivial to write, as it appears that the syntax you've adopted
for your file format is simple. The part where you will need to make some
fundamental decisions will be the on what data to extract and how to operate
on the extracted data.

Usually, a the parser is employed to fill a specific data structure in a
direct way, while in your case it appears that the data structure which you
need to fill, along with the data that you extract, are arbitrary. So, a
possible approach is to define an interface consisting of a set of functions
to handle parser events such as "stumbled on a line number" and "just parsed
a line". Then, from that, you can use that interface to define operators of
sorts, to perform tasks such as "get 1st column from line M to N",
"calculate the average value of the 2nd column", etc...

Pass all that
data to a parameter of a function.

Maybe it would be better to define a new data structure that includes a list
and then write your functions so that they accept that data structure
instead of relying on an unknown number of parameters. With this, you only
need to define a single function to handle any number of parameters you may
extract from the list.

Hope this helps,
Rui Maciel
 
R

Rui Maciel

Bill said:
Sounds like strtok would come into play here.

Developing a lexer specifically for that task is easy and ends up being a
far better solution. In fact, it isn't even necessary to develop it by
hand, as there are tools which automatically generate them. A tool which I
tend to use for this purpose is re2c[1], and it works quite well.


Rui Maciel


[1] http://re2c.org/
 
8

88888 Dihedral

int binsearch ( int a[], int length, int key)
{
register int lo=0;
register int hi=length-1;
register int gap=hi-lo;
register mid=lo+ (gap>>1);

//

while(gap) // gap==0 then lo==hi==mid
{
if (key== a[mid] ) { return mid;}
else if (key >a[mid]) { lo=mid;}
else { hi=mid; }

gap= hi-lo; mid=lo+(gap>>1);

}

//gap ==0
if (key==a[hi]) return hi; else return -1;

//return the 32 bit or 64 bit integer

}
 
B

Ben Bacarisse

88888 Dihedral said:
int binsearch ( int a[], int length, int key)
{
register int lo=0;
register int hi=length-1;
register int gap=hi-lo;
register mid=lo+ (gap>>1);

Implicit int was removed from C99. Even if you prefer the older
standard it's not a very good idea to use it.
//

while(gap) // gap==0 then lo==hi==mid
{
if (key== a[mid] ) { return mid;}
else if (key >a[mid]) { lo=mid;}
else { hi=mid; }

gap= hi-lo; mid=lo+(gap>>1);

}

Your loop is not guaranteed to terminate.
//gap ==0
if (key==a[hi]) return hi; else return -1;

//return the 32 bit or 64 bit integer

}
 
8

88888 Dihedral

88888 Dihedral said:
int binsearch ( int a[], int length, int key)
{
register int lo=0;
register int hi=length-1;
register int gap=hi-lo;
register mid=lo+ (gap>>1);

Implicit int was removed from C99. Even if you prefer the older
standard it's not a very good idea to use it.
//

while(gap) // gap==0 then lo==hi==mid
{
if (key== a[mid] ) { return mid;}
else if (key >a[mid]) { lo=mid;}
else { hi=mid; }

gap= hi-lo; mid=lo+(gap>>1);

}

Your loop is not guaranteed to terminate.
//gap ==0
if (key==a[hi]) return hi; else return -1;

//return the 32 bit or 64 bit integer

}

Add gap>1 in the while

and else if (key==a[lo]) return lo; // outside the loop

What else can you suggest?
 
S

Seebs

What else can you suggest?

I would suggest starting over from scratch, and learning about style,
layout, and maintenance of code. As is, while that's not the worst code
I've seen today, this is only because of a hilarious coincidence.

-s
 
B

Ben Bacarisse

88888 Dihedral said:
88888 Dihedral said:
int binsearch ( int a[], int length, int key)
{
register int lo=0;
register int hi=length-1;
register int gap=hi-lo;
register mid=lo+ (gap>>1);

Implicit int was removed from C99. Even if you prefer the older
standard it's not a very good idea to use it.
//

while(gap) // gap==0 then lo==hi==mid
{
if (key== a[mid] ) { return mid;}
else if (key >a[mid]) { lo=mid;}
else { hi=mid; }

gap= hi-lo; mid=lo+(gap>>1);

}

Your loop is not guaranteed to terminate.
//gap ==0
if (key==a[hi]) return hi; else return -1;

//return the 32 bit or 64 bit integer

}

Add gap>1 in the while

and else if (key==a[lo]) return lo; // outside the loop

What else can you suggest?

I'd (a) use size_t for the indexes and length, (b) tidy up the layout,
(c) keep all the testing in one place:

size_t binsearch(int a[], size_t length, int key)
{
size_t low = 0, high = length;
while (high > low) {
size_t middle = low + (high - low)/2;
if (key == a[middle])
return middle;
else if (key > a[middle])
low = middle + 1;
else high = middle;
}
return -1;
}

The loop invariant is that the key's index (if it exists) is in [low,
high) i.e. low <= index < high. These asymmetric bounds avoid any
problems with unsigned indexes when length == 0. They also explain the
different settings for low and high.
 
8

88888 Dihedral

88888 Dihedral said:
int binsearch ( int a[], int length, int key)
{
register int lo=0;
register int hi=length-1;
register int gap=hi-lo;
register mid=lo+ (gap>>1);

Implicit int was removed from C99. Even if you prefer the older
standard it's not a very good idea to use it.

//

while(gap) // gap==0 then lo==hi==mid
{
if (key== a[mid] ) { return mid;}
else if (key >a[mid]) { lo=mid;}
else { hi=mid; }

gap= hi-lo; mid=lo+(gap>>1);

}

Your loop is not guaranteed to terminate.

//gap ==0
if (key==a[hi]) return hi; else return -1;

//return the 32 bit or 64 bit integer

}

Add gap>1 in the while

and else if (key==a[lo]) return lo; // outside the loop

What else can you suggest?

I'd (a) use size_t for the indexes and length, (b) tidy up the layout,
(c) keep all the testing in one place:

size_t binsearch(int a[], size_t length, int key)
{
size_t low = 0, high = length;
while (high > low) {
size_t middle = low + (high - low)/2;
if (key == a[middle])
return middle;
else if (key > a[middle])
low = middle + 1;
else high = middle;
}
return -1;
}

The loop invariant is that the key's index (if it exists) is in [low,
high) i.e. low <= index < high. These asymmetric bounds avoid any
problems with unsigned indexes when length == 0. They also explain the
different settings for low and high.

Do you consider to convert 5 to 10 lines of C to assembly?
 
S

Seebs

Do you consider to convert 5 to 10 lines of C to assembly?

Of course not.

1. It's a great way to introduce errors and bugs.
2. It eliminates portability.
3. It takes time.
4. It is very unlikely to produce a measurable benefit.

When you're about to pop out to the store, do you take your car's fuel
system apart and rebuild the carburetor? If so, why do you do this given
that the vast majority of modern cars don't even have one?

-s
 
J

jacob navia

Le 22/12/11 16:11, 88888 Dihedral a écrit :
The loop invariant is that the key's index (if it exists) is in [low,
high) i.e. low<= index< high. These asymmetric bounds avoid any
problems with unsigned indexes when length == 0. They also explain the
different settings for low and high.

Do you consider to convert 5 to 10 lines of C to assembly?

Each time you see that you have done a mistake you go to assembly man,
that's just to impress people here.

Well, you are not going to do that here in general, nor with me in
particular. I know enough assembly to know when to use it. That
routine doesn't do anything where an assembly language program would
be much better.

Places where assembly shines are computations and operations that have
NO equivalent in higher level languages. That is surely not the case
with the small routine above
 
B

BartC

Seebs said:
Of course not.

1. It's a great way to introduce errors and bugs.

Well, you could say that same about using C! Compared to something higher
level, safer, but slower.
2. It eliminates portability.

So what? If this is a product to be sold/used in thousands and millions,
you'll probably find that a small number of platforms will dominate. Then
it's worth producing a custom version for the top one or two. The rest can
use the slow version.

If you're distributing the code as binaries, then you will need multiple
versions anyway. And if you're distributing as source code, you will have
just as many headaches with getting the right combinations of compiler,
compiler switches, makefiles and libraries that will work 'out-of-the-box'
on anything.
3. It takes time.
4. It is very unlikely to produce a measurable benefit.

You're assuming this is for a one-off program that will only be run once.
Then you could well spend more time programming than will be saved in
runtime. But usually that is not the case.
When you're about to pop out to the store, do you take your car's fuel
system apart and rebuild the carburetor?

But if you're working in automobile design and production, this is just the
sort of thing you might do. Then you end with a version with a very slightly
better fuel consumption, but which is significant over a million units and
thousands of journeys each.
 
M

Markus Wichmann

i have just one argument against yours:
all code going out from one assembly programmer is from 10
to 1000 times better the one not know assembly
this is only what i think
one can not be sure of all and has to syntesis his results

You really ought to try out a compiler from this century. Compilers are
in general worse than competent assembly hand crafters, but not in that
order of magnitude. Compiler-generated code has most of the time at most
twice the run-time of the best known assembly code. That's if you write
your C code to actually describe the algorithm you meant. Just saying.
I've seen assembly advocates comparing apples to oranges on that
question. (And then complain that the oranges don't taste as sweet.)

If you need pointers: Try the current gcc, llvm or possibly dragonegg.

HTH,
Markus
 
S

Seebs

Well, you could say that same about using C! Compared to something higher
level, safer, but slower.

True. And I use C, for the most part, only when I have a specific and
compelling reason to work at that level.
So what? If this is a product to be sold/used in thousands and millions,
you'll probably find that a small number of platforms will dominate. Then
it's worth producing a custom version for the top one or two. The rest can
use the slow version.

It might be worth producing a custom version... IF you knew that this
particular small hunk of code was actually that expensive to run, and was
being run enough to matter, and performance was remotely an issue. But
that's a very, very, rare circumstance.
If you're distributing the code as binaries, then you will need multiple
versions anyway. And if you're distributing as source code, you will have
just as many headaches with getting the right combinations of compiler,
compiler switches, makefiles and libraries that will work 'out-of-the-box'
on anything.

Not just as many. Trust me! I work on a build system that has to manage
about 60 targets. The handful of programs that have assembly hacks which
are optional in some way consume a very noticably disproportionate amount of
time because of all the extra hassles they introduce *on top of* all the
stuff with compilers and compiler switches.
You're assuming this is for a one-off program that will only be run once.
Then you could well spend more time programming than will be saved in
runtime. But usually that is not the case.

No, I'm including cases where a program is run millions of times. There is
a reason that the vast majority of programs don't contain inline assembly,
and it's not that software developers are stupid.
But if you're working in automobile design and production, this is just the
sort of thing you might do. Then you end with a version with a very slightly
better fuel consumption, but which is significant over a million units and
thousands of journeys each.

The key to the analogy is that they haven't used carburetors in something over
a decade in any major line of vehicles I'm aware of.

A significant improvement in the perforumance of a carburetor isn't even
remotely competitive with a cheap fuel injection system.

-s
 
8

88888 Dihedral

Are you saying that you are not good enough to write a compiler
and help the GNU GCC projects?
 
S

Seebs

Seebs ha scritto:
maybe that's offtopic, but i am curious: what languages and tools do you
use most for your work?

Boy, that's pretty open-ended.

Right now, my favorite language in which to express something is Ruby; if I
don't really know how to do something yet, that seems to be a very friendly
language in which to try to figure it out. Also very nice for refactoring.
I love me some Rails.

I use PHP for things which had to be in PHP for compatibility at some point
in the past, but I hate it. It is a stupendously bad language.

I use various modern derivatives of Bourne shell, and Makefile type stuff,
and perl, all as-needed. Not super fond of them as languages, although the
shell really is extremely powerful as glue.

I use Lua a fair bit, largely because I play RIFT (really nice MMO), and
that's what their addon API is done in. (If you've ever wanted to mess
around with addon development in video games, the guy doing the RIFT API
is a genius, and while the API isn't complete yet, the parts it has really
are delightful to use.)

The main thing I'm using C for these days is pseudo, which is a program
which intercepts calls into libc (and thus in effect most system calls)
and fakes up a virtual root environment; we use this for a build system
to allow the creation of filesystem images with ownership and permissions
and devices, without needing root access. (It's similar to fakeroot, but
different in a few philosophical ways.)

As an interesting example, I do plan to write something in C "soon", which
is a wrapper. Right now the wrapper is implemented as a shell script, but
we have performance issues with that which mandate a reimplementation.
This is a case where we know this wrapper has to run millions of times,
and the performance overhead really DOES matter. (We'd do it in a more
efficient scripting language, but for Various Sound Technical Reasons, we
end up being unable to do this.)

-s
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

code 34
URGENT 1
comparison error 12
code 50
error 28
Q for a source code in an exercise 1
no error by fscanf on reading from output file 18
malloc 40

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top