Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Having C code looking like C++ code

Reply
Thread Tools

Having C code looking like C++ code

 
 
Richard Heathfield
Guest
Posts: n/a
 
      10-12-2003
Fronsac wrote:

>> You posted the same question with slightly different subject lines
>> to (at least) a.c.l.l.c-c++ and c.l.c.

>
> Yeah, I was too lazy to copy-paste the subject line from the other post.


Lazy doesn't win friends on Usenet - at least, not when the lazy person is
the one asking for help.

> I
> posted in two forums just to be sure at least one person answered me.
>
>> If you feel the need to post to more than one news-group, please
>> cross-post rather than multi-post. Thank you.

>
> What is cross-post? Could you explain me what it is and how to do it?


Cross-posting is the posting of one article to more than one newsgroup
(rather than posting two identical articles to one newsgroup each). Typical
newsreaders allow you to do this by typing more than one group name into
the "Groups" header when you are creating your article.

The reason for cross-posting is that it allows newsreaders to deal
intelligently with the thread when a reader (such as myself) subscribes to
/both/ the newsgroups to which you have cross-posted. Having presented your
article to me in one group, it would not bother to do so in the second,
because it would "know" that I'd already read the article.

When you post identical articles with separate message IDs in separate
groups (as you did this time around), the newsreader can't legitimately
associate them, so it doesn't. This costs your readers time. Incurring
unnecessary costs of your readers is not a good idea when /you/ are asking
/them/ for help.

--
Richard Heathfield : http://www.velocityreviews.com/forums/(E-Mail Removed)
"Usenet is a strange place." - Dennis M Ritchie, 29 July 1999.
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
K&R answers, C books, etc: http://users.powernet.co.uk/eton
 
Reply With Quote
 
 
 
 
Fronsac
Guest
Posts: n/a
 
      10-12-2003
> Cross-posting is the posting of one article to more than one newsgroup
> (rather than posting two identical articles to one newsgroup each).

Typical
> newsreaders allow you to do this by typing more than one group name into
> the "Groups" header when you are creating your article.


Thanks a lot. I'm not sure Outlook Express does this, but Outlook is only a
temporary solution anyway. Thanks for the info.


 
Reply With Quote
 
 
 
 
Mike Wahler
Guest
Posts: n/a
 
      10-12-2003
"Fronsac" <(E-Mail Removed)> wrote in message
news:bUjib.17268$(E-Mail Removed)...
> > Cross-posting is the posting of one article to more than one newsgroup
> > (rather than posting two identical articles to one newsgroup each).

> Typical
> > newsreaders allow you to do this by typing more than one group name into
> > the "Groups" header when you are creating your article.

>
> Thanks a lot. I'm not sure Outlook Express does this,


Yes, Outlook Express does handle crossposts correctly
as far as I can tell.

-Mike


 
Reply With Quote
 
Michael Winter
Guest
Posts: n/a
 
      10-12-2003

"Fronsac" <(E-Mail Removed)> wrote in message
news:bUjib.17268$(E-Mail Removed)...
> > Cross-posting is the posting of one article to more than one

newsgroup
> > (rather than posting two identical articles to one newsgroup

each).
> Typical
> > newsreaders allow you to do this by typing more than one group

name into
> > the "Groups" header when you are creating your article.

>
> Thanks a lot. I'm not sure Outlook Express does this, but Outlook is

only a
> temporary solution anyway. Thanks for the info.


Outlook Express does support cross-posting. If you click "Newsgroups"
(the icon and label, not the text-box to it's right) a dialog will
appear. Here you can select one or more destination groups.
Alternatively, you can type them in the text-box separated by commas,
if you really want. If you do cross-post, you might also want to set
up where follow-ups to your post are sent, rather than have them
bounce around all of the groups (why have a potentially huge
conversation appear in multiple groups?). To do this, select "All
Headers" from the "View" menu then use the "Followup-To" section like
the "Newgroups" section, but only add one newgroup (the most
appropriate for your question is probably best). You can ignore the
other sections it adds (except "Subject", of course).

Mike

--
Michael Winter
M.Winter@[no-spam]blueyonder.co.uk (remove [no-spam] to reply)


 
Reply With Quote
 
James Hu
Guest
Posts: n/a
 
      10-13-2003
On 2003-10-12, Fronsac <(E-Mail Removed)> wrote:
> I've been asked in a job interview how to make C code look like C++
> code, and honestly I didn't know what to answer because I have never
> really done a lot of C. Now, I've been searching around the web about
> web sites that talk about this subject, but I've had no luck. Can
> anyone point me to some web site about this subject? Thanks a lot!


Let's consider a simple example: providing an integer stack.

Here's a typical way of doing it:

+---
| /* -- stack.h -- */
| extern int push(int value);
| extern int pop(int *value);
| extern void popall(void);
+---
| /* -- stack.c -- */
| #include "stack.h"
|
| #define MAX_STACK 100
| static int stack[MAX_STACK];
| static unsigned count;
|
| int push(int value) {
| if (count >= MAX_STACK) return -1;
| stack[count++] = value;
| return 0;
| }
|
| int pop(int *value) {
| if (count == 0) return -1;
| *value = stack[--count];
| return 0;
| }
|
| void popall(void) {
| count = 0;
| }
+---

There may be other deficiencies with this implementation, but at least
one of them is that any application that uses this implementation is
limited to only one stack. There are various ways of addressing this
issue, but one of the most short sighted ways is to simply copy off
stack.c to another file stack2.c and rename the functions push2 and
pop2 to create a second stack.

Better is to encapsulate the stack in a structure so that an
application can create as many stacks as it needs without having to
apply cut and paste coding.

+---
| /* -- stack.h -- */
| #define MAX_STACK 100
| typedef struct stacktype {
| int stack[MAX_STACK];
| unsigned count;
| } stacktype;
|
| extern int push(stacktype *s, int value);
| extern int pop(stacktype *s, int *value);
| extern void popall(stacktype *s);
+---
| /* -- stack.c -- */
| #include "stack.h"
|
| int push(stacktype *s, int value) {
| if (s->count >= MAX_STACK) return -1;
| s->stack[s->count++] = value;
| return 0;
| }
|
| int pop(stacktype *s, int *value) {
| if (s->count == 0) return -1;
| *value = s->stack[--s->count];
| return 0;
| }
|
| void popall(stacktype *s) {
| s->count = 0;
| }
+---

This implementation is sufficient for most applications needing an
integer stack. However, another minor drawback is that all stacks
are always of the same size. In order to avoid the cut and paste
solution to allow different sized stacks, this property should also be
encapsulated within the stack data structure. However, now the stack
implementation is exposed to the extent that users of the interface must
muck around inside the encapsulation to use the interface. In order to
decouple the interface from the implementaiton, we make the stacktype
opaque. The result provides a limited form of polymorphism, since
the stack interface client need not be aware of how the stack was
created to use the stack.

+---
| /* -- stack.h -- */
| typedef struct stacktype stacktype;
|
| extern stacktype *create_bounded_stack(unsigned stacksize);
| extern void destroy_stack(stacktype *s);
|
| extern int push(stacktype *s, int value);
| extern int pop(stacktype *s, int *value);
| extern void popall(stacktype *s);
+---
| /* -- stack.c -- */
| #include <stdlib.h>
| #include "stack.h"
|
| struct stacktype {
| unsigned max_stack;
| unsigned count;
| int stack[];
| };
|
| int push(stacktype *s, int value) {
| if (s->count >= s->max_stack) return -1;
| s->stack[s->count++] = value;
| return 0;
| }
|
| int pop(stacktype *s, int *value) {
| if (s->count == 0) return -1;
| *value = s->stack[--s->count];
| return 0;
| }
|
| void popall(stacktype *s) {
| s->count = 0;
| }
|
| void destroy_stack(stacktype *s) {
| free(s);
| }
|
| stacktype *create_bounded_stack(unsigned stacksize) {
| stacktype *s;
| if (stacksize == 0) return 0;
| s = malloc(sizeof(stacktype) + stacksize*sizeof(int));
| if (s != 0) {
| s->max_stack = stacksize;
| s->count = 0;
| }
| return s;
| }
+---

The final point we will address is that the interface only provides
a bounded stack implementation. Suppose an application is utilizing
the stack in multiple modules. In some modules, the bounded stack
is required, because it is used to throttle the work load. In other
modules, it has been determined that a bounded stack is unacceptable,
since pre-allocating the maximum required memory is too wasteful, and
and the most common cases only require a small amount of memory.

Again, one could perform cut and paste, rename the stack interfaces
for an unbounded implementation, and alter the modules that need the
unbounded implementation to use the new interface. However, to avoid
the pitfalls of cut and paste programming, an alternative solution
is to make the interface inheritable and extensible. Then, applying
reuse on the interface, implement the unbounded stack.

+---
| /* -- stack.h -- */
| typedef struct stacktype stacktype;
| struct stacktype {
| int (*push)(stacktype *s, int value);
| int (*pop)(stacktype *s, int *value);
| void (*popall)(stacktype *s);
| void (*destroy)(stacktype *s);
| };
|
| static inline int push(stacktype *s, int value) {return s->push(s, value);}
| static inline int pop(stacktype *s, int *value) {return s->pop(s, value);}
| static inline void popall(stacktype *s) {s->popall(s);}
| static inline void destroy_stack(stacktype *s) {s->destroy(s);}
+---
| /* -- bounded_stack.h -- */
| #include "stack.h"
| extern stacktype *create_bounded_stack(unsigned stacksize);
+---
| /* -- bounded_stack.c -- */
| #include <stdlib.h>
| #include "bounded_stack.h"
|
| typedef struct bounded_stacktype {
| stacktype interface;
| unsigned max_stack;
| unsigned count;
| int stack[];
| } bounded_stacktype;
|
| static int bounded_push(stacktype *s, int value) {
| bounded_stacktype *bs = (void *)s;
| if (bs->count >= bs->max_stack) return -1;
| bs->stack[bs->count++] = value;
| return 0;
| }
|
| static int bounded_pop(stacktype *s, int *value) {
| bounded_stacktype *bs = (void *)s;
| if (bs->count == 0) return -1;
| *value = bs->stack[--bs->count];
| return 0;
| }
|
| static void bounded_popall(stacktype *s) {
| bounded_stacktype *bs = (void *)s;
| bs->count = 0;
| }
|
| static void destroy_bounded_stack(stacktype *s) {
| free(s);
| }
|
| static const stacktype bounded_stack_interface = {
| bounded_push,
| bounded_pop,
| bounded_popall,
| destroy_bounded_stack,
| };
|
| stacktype *create_bounded_stack(unsigned stacksize) {
| bounded_stacktype *bs;
| if (stacksize == 0) return 0;
| bs = malloc(sizeof(bounded_stacktype) + stacksize*sizeof(int));
| if (bs == 0) return 0;
| bs->interface = bounded_stack_interface;
| bs->max_stack = stacksize;
| bs->count = 0;
| return &bs->interface;
| }
+---
| /* -- unbounded_stack.h -- */
| #include "stack.h"
| extern stacktype *create_unbounded_stack(void);
+---
| /* -- unbounded_stack.c -- */
| #include <stdlib.h>
| #include "unbounded_stack.h"
| #include "bounded_stack.h"
|
| #define UB_STACK_DEFAULT 100
| static unsigned UB_STACK_SIZE = UB_STACK_DEFAULT;
|
| typedef struct unbounded_substacktype {
| struct unbounded_substacktype *link;
| stacktype *substack;
| } unbounded_substacktype;
|
| static unbounded_substacktype *create_unbounded_substack(void) {
| unbounded_substacktype *s;
| s = malloc(sizeof(unbounded_substacktype));
| if (s == 0) return 0;
| s->substack = create_bounded_stack(UB_STACK_SIZE);
| if (s->substack == 0) {
| free(s);
| return 0;
| }
| s->link = 0;
| return s;
| }
|
| static void destroy_unbounded_substack(unbounded_substacktype *s) {
| destroy_stack(s->substack);
| free(s);
| }
|
| typedef struct unbounded_stacktype {
| stacktype interface;
| unbounded_substacktype *current_stack;
| unbounded_substacktype *free_stack;
| } unbounded_stacktype;
|
| static int unbounded_push(stacktype *s, int value) {
| unbounded_stacktype *us = (void *)s;
| unbounded_substacktype *cs = us->current_stack;
| unbounded_substacktype *fs;
| if (cs == 0 || push(cs->substack, value) == -1) {
| fs = us->free_stack;
| if (fs == 0) {
| if ((fs = create_unbounded_substack()) == 0) return -1;
| } else us->free_stack = 0;
| fs->link = cs;
| cs = us->current_stack = fs;
| return push(cs->substack, value);
| }
| return 0;
| }
|
| static int unbounded_pop(stacktype *s, int *value) {
| unbounded_stacktype *us = (void *)s;
| unbounded_substacktype *cs = us->current_stack;
| unbounded_substacktype *fs;
| if (cs == 0) return -1;
| if (pop(cs->substack, value) == -1) {
| fs = cs;
| cs = us->current_stack = cs->link;
| if (us->free_stack == 0) us->free_stack = fs;
| else destroy_unbounded_substack(fs);
| return pop(cs->substack, value);
| }
| return 0;
| }
|
| static void unbounded_popall(stacktype *s) {
| unbounded_stacktype *us = (void *)s;
| unbounded_substacktype *cs = us->current_stack;
| unbounded_substacktype *fs = us->free_stack;
| if (cs == 0) return;
| if (fs == 0) {
| fs = us->free_stack = cs;
| cs = us->current_stack = cs->link;
| fs->link = 0;
| popall(fs->substack);
| }
| while (cs != 0) {
| cs = cs->link;
| destroy_unbounded_substack(us->current_stack);
| us->current_stack = cs;
| }
| }
|
| static void destroy_unbounded_stack(stacktype *s) {
| unbounded_stacktype *us = (void *)s;
| unbounded_popall(s);
| if (us->free_stack) destroy_unbounded_substack(us->free_stack);
| free(s);
| }
|
| static const stacktype unbounded_stack_interface = {
| unbounded_push,
| unbounded_pop,
| unbounded_popall,
| destroy_unbounded_stack,
| };
|
| stacktype *create_unbounded_stack(void) {
| unbounded_stacktype *us;
| us = malloc(sizeof(unbounded_stacktype));
| if (us == 0) return 0;
| us->interface = unbounded_stack_interface;
| us->current_stack = 0;
| us->free_stack = 0;
| return &us->interface;
| }
+---

The final example shows an extensible polymorphic interface in C. The
interface is exposed in an object that can be inherited. The example
leverages the inheritance to provide multiple implementations of the
interface. Code utilizing the interface can be simultaneously reused to
manipulate either a bounded or unbounded stack. Code can furthermore
inherit the interface and provide their own implementations.

This is of course only an example, and the techniques applied here is
arguably overkill for such a simple data structure. The simplicity,
however, allows the techniques to be illustrated in a relatively
straight forward and compact manner. These techniques here are nothing
new to the experienced software professional. They will be found in OS
kernel code, I/O interface APIs, protocol stacks, GUI APIs, and many
other places.

-- James
 
Reply With Quote
 
Lorenzo Villari
Guest
Posts: n/a
 
      10-14-2003

> Or you can study the lightweight C++ preprocessor, which takes as input
> a language that looks like C++ and produces good old C.


AHEM... although I think it's really interesting and I've successfully
used it, given something like

my_var_ptr = new myclass(param);

you get

my_var_ptr = (
{ struct myclass*InTeRnAl_y = (struct myclass *)malloc(sizeof(struct
myclass));
myclass_ctor(InTeRnAl_y, param);
InTeRnAl_y; } );

I think this should be instead

struct myclass *InTeRnAl_y = malloc(sizeof(struct myclass));
my_var_ptr = InTeRnAl_y
myclass_ctor(InTeRnAl_y, param);

Not to mention some gcc extensions like

static void GlObALcOnStRuCtOr ( )
{
}
static void (*_Counter_cppAsCiiArT)(void) __attribute__ ((unused,__section__
(".ctors"))) = GlObALcOnStRuCtOr;

appended to every source "translated"...

Ah... and you can't compile the sources without gcc... (plus cygwin on
Windows..).

PS: Anyway I've supported it from the start ^^







 
Reply With Quote
 
E. Robert Tisdale
Guest
Posts: n/a
 
      10-14-2003
Fronsac wrote:

> I've been asked in a job interview how to make C code look like C++
> code, and honestly I didn't know what to answer because I have never really
> done a lot of C. Now, I've been searching around the web about web sites
> that talk about this subject, but I've had no luck.



$ cat Point.h
#ifndef _Point_h
#define _Point_h 1

typedef struct {
/* representation */
double X;
double Y;
} Point;
/* functions */
double
xPoint(const Point *p);
double
yPoint(const Point *p);
/* constructors */
Point
createDefaultPoint(void);
Point
createExplicitPoint(double x, double y);
/* destructor */
void
destroyPoint(Point* p);

#endif /* _Point_h */

$ cat Point.c
/* gcc -I. -O2 -c Point.c
*/
#include<Point.h>

/* functions */
double
xPoint(const Point *p) {
return p->X; }
double
yPoint(const Point *p) {
return p->Y; }
/* constructors */
Point
createDefaultPoint(void) {
Point p;
p.X = 0.0;
p.Y = 0.0;
return p; }
Point
createExplicitPoint(double x, double y) {
Point p;
p.X = x;
p.Y = y;
return p;
}
/* destructor */
void
destroyPoint(Point* p) { }

$ cat Color.h
#ifndef _Color_h
#define _Color_h 1
typedef struct {
unsigned char R; /* red */
unsigned char G; /* green */
unsigned char B; /* blue */
} Color;
/* functions */
unsigned int
redColor(const Color *c);
unsigned int
greenColor(const Color *c);
unsigned int
blueColor(const Color *c);
/* constructors */
Color
createDefaultColor(void);
Color
createExplicitColor(
unsigned int r,
unsigned int g,
unsigned int b);
/* destructor */
void
destroyColor(Color *c);

#endif /* _Color_h */

$ cat Color.c
/* gcc -I. -O2 -c Color.c
*/
#include<Color.h>

/* functions */
unsigned int
redColor(const Color *c) {
return c->R; }
unsigned int
greenColor(const Color *c) {
return c->G; }
unsigned int
blueColor(const Color *c) {
return c->B; }
/* constructors */
Color
createDefaultColor(void) {
Color c;
c.R = 0;
c.G = 0;
c.B = 0;
return c; }
Color
createExplicitColor(
unsigned int r,
unsigned int g,
unsigned int b) {
Color c;
c.R = r;
c.G = g;
c.B = b;
return c; }
/* destructor */
void
destroyColor(Color *c) { }

$ cat Shape.h
#ifndef _Shape_h
#define _Shape_h 1

#include<Point.h>
#include<Color.h>

typedef void* virtual_t;
typedef struct {
Point P; /* first public base class */
Color C; /* second public base class */
virtual_t* V; /* virtual function table */
} Shape;
/* functions */
Point*
pointShape(Shape* s);
Color*
colorShape(Shape* s);
void
drawShape(const Shape *s);
void
drawGeneralShape(const Shape *s);
double
areaShape(const Shape *s);
double
areaGeneralShape(const Shape *s);
/* constructors */
Shape
createDefaultShape(void);
Shape
createExplicitShape(
const Point *p,
const Color *c);
/* destructor */
void
destroyShape(Shape *s);

#endif /* _Shape_h */

$ cat Shape.c
/* gcc -I. -O2 -c Shape.c
*/
#include<stdio.h>
#include<Shape.h>

typedef void (*drawShape_t)(const Shape *);
typedef double (*areaShape_t)(const Shape *);
/* functions */
Point*
pointShape(Shape* s) {
return &(s->P); }
Color*
colorShape(Shape* s) {
return &(s->C); }
void
drawGeneralShape(const Shape *s) {
fprintf(stderr, "drawShape(const Shape *s)\n");
fflush(stderr); }
double
areaGeneralShape(const Shape *s) {
fprintf(stderr, "areaShape(const Shape *s)\n");
fflush(stderr);
return 0.0; }
static virtual_t
vtableShape[] = {(virtual_t)drawGeneralShape,
(virtual_t)areaGeneralShape};
void
drawShape(const Shape *s) {
((drawShape_t)(s->V[0]))(s); }
double
areaShape(const Shape *s) {
return ((areaShape_t)(s->V[1]))(s); }
/* constructors */
Shape
createDefaultShape(void) {
Shape S;
S.P = createDefaultPoint();
S.C = createDefaultColor();
S.V = vtableShape;
return S; }
Shape
createExplicitShape(
const Point *p,
const Color *c) {
Shape S;
S.P = *p;
S.C = *c;
S.V = vtableShape;
return S; }
/* destructor */
void
destroyShape(Shape *s) {
destroyColor(colorShape(s));
destroyPoint(pointShape(s));
}

$ cat Circle.h
#ifndef _Circle_h
#define _Circle_h 1

#include<Shape.h>

typedef struct {
Shape S; /* public base class */
double R; /* radius */
} Circle;
/* functions */
Shape*
shapeCircle(Circle* c);
double
radiusCircle(const Circle* c);
void
drawCircle(const Circle *c);
double
areaCircle(const Circle *c);
/* constructors */
Circle
createDefaultCircle(void);
Circle
createExplicitCircle(const Shape *s, double r);
/* destructor */
void
destroyCircle(Circle *c);

#endif /* _Circle_h */

$ cat Circle.c
/* gcc -I. -O2 -c Circle.c
*/
#include<math.h>
#include<stdio.h>
#include<Circle.h>

typedef void (*drawCircle_t)(const Circle *);
typedef double (*areaCircle_t)(const Circle *);
/* functions */
Shape*
shapeCircle(Circle* c) {
return &(c->S); }
double
radiusCircle(const Circle* c) {
return c->R; }
void
drawCircle(const Circle *c) {
fprintf(stderr, "drawCircle(const Circle *c)\n");
fflush(stderr); }
double
areaCircle(const Circle *c) {
const
double pi = 3.14159265358979323846;
double r = radiusCircle(c);
fprintf(stderr, "areaCircle(const Circle *c)\n");
fflush(stderr);
return pi*r*r; }
static virtual_t
vtableCircle[] = {(virtual_t)drawCircle,
(virtual_t)areaCircle};
/* constructors */
Circle
createDefaultCircle(void) {
Circle C;
C.S = createDefaultShape();
C.R = 0.0;
C.S.V = vtableCircle;
return C; }
Circle
createExplicitCircle(const Shape *s, double r) {
Circle C;
C.S = *s;
C.R = r;
C.S.V = vtableCircle;
return C; }
/* destructor */
void
destroyCircle(Circle *c) {
destroyShape(shapeCircle(c));
}

$ cat main.c
/* gcc -I. -O2 -o main main.c Circle.o Shape.o Color.o Point.o
*/
#include<stdio.h>
#include<Circle.h>

int
main(int argc, char* argv[]) {
Shape s = createDefaultShape();
Circle c = createExplicitCircle(&s, 2.0);
drawShape((Shape*)(&c));
fprintf(stdout, "%g = radius\t %g = area\n",
radiusCircle(&c), areaShape((Shape*)(&c)));
return 0;
}

$ cat Makefile
CC=gcc
DEFINES=
INCLUDE=-I.
OPTIONS=-O2
LIBRARY=
OBJECTS=Point.o Color.o Shape.o Circle.o
SOURCES=Point.c Color.c Shape.c Circle.c
HEADERS=Point.h Color.h Shape.h Circle.h
library=
COMPILE=$(CC) $(DEFINES) $(INCLUDE) $(LIBRARY) $(OPTIONS)

main: $(HEADERS) $(OBJECTS) main.c
$(COMPILE) -o main main.c $(OBJECTS) $(library)

Point.o: Point.h Point.c
$(COMPILE) -c Point.c

Color.o: Color.h Color.c
$(COMPILE) -c Color.c

Shape.o: Shape.h Shape.c
$(COMPILE) -c Shape.c

Circle.o: Circle.h Circle.c
$(COMPILE) -c Circle.c

clean:
rm $(OBJECTS) main



 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Which film characters would you least like having as a neighbor and why ? Eric DVD Video 3 09-14-2007 12:26 PM
Internet networking , group networking,business leads,new business opportunities,like having many sales peoples elie Computer Support 0 08-18-2007 10:12 AM
object-like macro used like function-like macro Patrick Kowalzick C++ 5 03-14-2006 03:30 PM
Would like to load a datagrid already in edit mode instead of having the user click the edit button Frank Kurka ASP .Net Datagrid Control 8 04-29-2005 09:33 AM
After having 8mm film reels digitally archived, film looks very grainy/ filled with static. Is this digital-looking noise normal? + more 8mm film questions Phil Edry Digital Photography 11 10-10-2004 11:57 PM



Advertisments