468,463 Members | 2,058 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,463 developers. It's quick & easy.

Help in this programm in C

Hi.I am started learning Programm language C before some time.I am
trying to make a programm about a very simple "sell shop".This programm
hasn't got any compile problem but when i run it i face some other
ploblems which i can not correct.I would appreciated if someone take a
look at my programm so as to help me.I tried many times to find out
where my mistakes are but i didn't manage something.
I have made some comments due to the programm so as to make it more
easy to as.
Any recommendations about my writing style in the programm are
acceptable.
Please help me!!!

Programm
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

/* Functions*/
int menu(void);
struct sells *insert(void);
struct sells *search(void);
int show(struct sells *list);
int exit(void);

/*Struct*/
struct sells{
char *tittle;
char *singer;
int price;
int count;
struct sells *next;
};

struct sells *list;
struct sells *alloc(void)
{
return(struct sells*)malloc(sizeof(struct sells));
}
/*Function main*/
int main(void)
{
menu();
return 0;
}

/*Function menu.In this function the user has the opportunity to choose

what he/she want to do*/
int menu(void)
{
int i;

printf("---------MENU---------\n");
printf("Press \"1\" to insert data\n");
printf("Press \"2\" to search data\n");
printf("Press \"3\" to show data\n");
printf("Press \"4\" to exit from programm\n");
putchar('\n\n');

printf("Make your choice\t");
scanf("%d",&i);

while((i<1)&&(i>4))
{
printf("You made wrong choice.\nPlease make a new
choice\n");
scanf("%d",&i);
}

switch(i)
{
case 1:
{
insert();
break;
}
case 2:
{
search();
break;
}
case 3:
{
show(list);
break;
}
case 4:
{
exit();
break;
}
}
return i;
}

/*In this function the user insert the data.*/
struct sells *insert(void)
{
char titlos[15];
char tragoudisths[15];
int timi;
struct sells *n;
float m_out;
int i;
m_out=0;
printf("%f\n",&m_out);
n=alloc();

printf("Give the title of the CD\n");
scanf("%s",&titlos);
getchar();
printf("Give the name of the singer\n");
scanf("%s",&tragoudisths);
getchar();

printf("Give the price of the CD\n");
scanf("%d",&timi);
getchar();

while((timi<0)||(timi>100))
{
printf("You have insert a wrong price.\nGive a new
price.\n");
scanf("%d",&timi);
getchar();
}
getchar();

n->tittle=strdup(titlos);
n->singer=strdup(tragoudisths);
n->price=timi;

if(list==NULL)
{
list=alloc();
list->tittle=strdup(n->tittle);
list->singer=strdup(n->singer);
list->price=n->price;
list->next=NULL;
printf("%f",&m_out);
}
else if((m_out=(strcmp(titlos,n->tittle)))==0)
{
list->count++;
printf("%f",&m_out);
}
else if((m_out=(strcmp(titlos,n->tittle)))<0)
{
n=alloc();
n->tittle=strdup(titlos);
n->singer=strdup(tragoudisths);
n->price=timi;
n->count=1;
n->next=list;
list=n;

printf("%s\t\t%s\t\t%d\t\t\n",list->tittle,list->singer,list->price);
}
else
{
list->next=insert();
return list;
}
printf("Press \"1\" to return to menu or \"2\" to exit\n");
printf("Make your choice");
scanf("%d",&i);

switch(i)
{
case 1:
{
menu();
break;
}
case 2:
{
exit();
break;
}
}
return n;
}
/*In this function the user search for an element.Also he can modify
it.
If someone can i would like to tell me what i have to do so as to
delete an element.*/
struct sells *search(void)
{
char titlos[15];
int i,k,out;
char choice;

printf("Give the tittle of the CD that you want to find\n");
gets(titlos);
getchar();
if(list==NULL||(out=strcmp(list->tittle,titlos))>0)
{
printf("The tittle that you want doesn't exist.\n");
printf("Press \"1\" to return to menu or \"2\" to exit\n");
printf("Make your choice");
scanf("%d",&i);

switch(i)
{
case 1:
{
menu();
break;
}
case 2:
{
exit();
break;
}
}
return list;
}
else if(out==0)
{
printf("Tittle: \t%s\n",list->tittle);
printf("Singer: \t%s\n",list->singer);
printf("Price: \t%d\n",list->price);

printf("Do you want to make any change;\n");
printf("If Yes press \"1\" else \"0\" to return to
menu\n");
printf("Make your choice");
scanf("%d",&k);
switch(k)
{
case 1:
{
printf("Do you want ot change the tittle;\nPress Y(YES)
or N(NO)\t");
scanf("%s",&choice);
getchar();
if(choice=='Y')
{
printf("Give new tittle:\n");
gets(list->tittle);
getchar();
}
printf("Do you want ot change the name of the
singer;\nPress Y(YES) or N(NO)\t");
scanf("%s",&choice);
getchar();
if(choice=='Y')
{
printf("Give new name:\n");
gets(list->singer);
getchar();
}
printf("Do you want ot change the price of the
CD;\nPress Y(YES) or N(NO)\t");
scanf("%s",&choice);
getchar();
if(choice=='Y')
{
printf("Give new price:\n");
scanf("%d",&list->price);
while((list->price<0)&&(list->price>100))
{
printf("You have insert a wrong price.\nGive a new
price.\n");
scanf("%d",&list->price);
}
putchar('\n');
}
break;
}
case 0:
{
menu();
break;
}
}
}
return list;
}
/*Function which shows to the user all the element that has already
insert.
In this functio there is a problem.When i insert more the 3 elements,
these elements doesn't appear to me.I think that the problem is in my
insert
but i am not quite sure.*/
int show(struct sells *list)
{
int i,k;
k=1;
printf("\t\t-------LIST--------\n");
printf("Num\t\tTittle\t\tSinger\t\tPrice\n");
while(list!=NULL)
{

printf("%d\t%s\t\t%s\t\t%d\t\t\n",k,list->tittle,list->singer,list->price);

k++;
list=list->next;
}
printf("What do you want to do\n");
printf("Press \"1\" to retutn to menu or \"2\" to exit\n");
printf("Make your choice");
scanf("%d",&i);

switch(i)
{
case 1:
{
menu();
break;
}
case 2:
{
exit();
break;
}
}
return 0;
}

/*Exit from the programm*/
int exit(void)
{
int i;

printf("Do you really want to exit from the programm;\n");
printf("If Yes press \"1\" else \"0\"\n");
printf("Make your choice");
scanf("%d",&i);

switch(i)
{
case 1:
{
menu();
break;
}
case 2:
{
break;
}
return 0;
}
}

Jul 7 '06
83 6763
Andrew Poelstra napsal(a):
According to my newserver, I was the first person to actually comment
on the entire code. I've no idea what you mean.
Ok, may be my fault...
>
>>> case 4:
exit();
break;
}
Okay, here's where you need smaller tabs. I've corrected case 4 for you.
Ugly as hell.
switch (whatever) {
case 1:
whatever
break;
}
is one of correct indentation.

1) Tabs are never correct indentation.
why? where?
2) Aside from that, there is no "correct" indentation. 2, 3, or 4-space
is fine. 8 is rarely readable for real code.
I don't think so, that's all.

>>> case 2:
exit();
break;
}
Fixed case 2 for you. (I use 2-space tabs, but 3 or 4 is fine.)
Blaah. Mixing of variable length indent is Evil(TM).
Read linux/Documentation/CodingStyle...

"Mixing of variable length indent"? Please tell me what that means
and where I did it.
It seemed, that you want him to mix 2 and 4 cols indentation...
>
>>> printf("Give the tittle of the CD that you want to find\n");
puts("Text doesn't need a \n with puts().");
Moreover it's not parsed...

It's an output statement. You don't "parse" output. Unless you meant
spellchecked or proofread...
Not you, but the compiler needn't.

--
js
Jul 8 '06 #51
Mark McIntyre napsal(a):
On Fri, 7 Jul 2006 15:49:56 GMT, in comp.lang.c , Jiri Slaby
<ge*@wo.czwrote:
>Nope, indentation is done by 8-columns wide tabs, period.

Apparently you haven't worked with many large programmes...
Linux kernel is not large enough :D? Then...

--
js
Jul 8 '06 #52
Jiri Slaby napsal(a):
Andrew Poelstra napsal(a):
>>>> printf("Give the tittle of the CD that you want to find\n");
puts("Text doesn't need a \n with puts().");
Moreover it's not parsed...
It's an output statement. You don't "parse" output. Unless you meant
spellchecked or proofread...

Not you, but the compiler needn't.
I meant libc, of course.

--
js
Jul 8 '06 #53

Joe Wright wrote:
ballpointpenthief wrote:
Dann Corbit wrote:
Right, all you have to do to use it safely is to reopen standard input as a
file, do some seeks and voilla! The gets() function can be used safely.
For some reason I want to know if anything like this is possible.
Anyone know how to do this?

/* Attempt to reopen stdin manually as a FILE *
Quite clearly impossible */

#include <stdio.h>
int main(void)
{
long offset;
fclose(stdin);
FILE *f = fopen("readfile.txt", "r");
if (f == NULL)
return 1;
printf("Address of stding: %d / Address of f: %d\n", stdin, f);
offset = (long)f - (long)stdin;
printf("Offset %i\n", offset);
if (fseek(f, offset, SEEK_SET) == -1)
return 1;
printf("New address of f: %p\n", &f);
char buf[10];
fgets(buf, 10, f);
printf("%s\n", buf);
fclose(f);
return 0;
}

You misunderstand something central. stdin is of type FILE*. stdin is
already open when your program starts.
Yeah, just messing.
The first argument to fopen is const char*. stdin cannot be that.

You need more practice.
Good. That means that I'm not wasting my time.

Was it a joke?
Yes.
But is it possible?

Jul 8 '06 #54
On Sat, 8 Jul 2006 01:36:16 GMT, in comp.lang.c , Jiri Slaby
<ge*@wo.czwrote:
>Mark McIntyre napsal(a):
>On Fri, 7 Jul 2006 15:49:56 GMT, in comp.lang.c , Jiri Slaby
<ge*@wo.czwrote:
>>Nope, indentation is done by 8-columns wide tabs, period.

Apparently you haven't worked with many large programmes...

Linux kernel is not large enough :D? Then...
Evidently, if 8-space tabs are acceptable....

:-)

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 8 '06 #55
On Sat, 8 Jul 2006 01:40:36 GMT, in comp.lang.c , Jiri Slaby
<ge*@wo.czwrote:
>Andrew Poelstra napsal(a):
>>
1) Tabs are never correct indentation.

why? where?
Because, as you know from the elsehtread discussion, nobody can agree
on the size and so what looks nicely formatted to you, with tabstops
set to eight, looks hideous to me, with them set to 4, and looks
bizarre in a proportional font. If you use spaces, everything stays
nicely lined up. .
>2) Aside from that, there is no "correct" indentation. 2, 3, or 4-space
is fine. 8 is rarely readable for real code.

I don't think so, that's all.
As I said elsethread, in large complex programmes, with many levels of
intentation, eight spaces becomes quite unworkable in no time flat. If
you stick to a sensible linelength, by the time you're five or six
levels of indentation in, youre out of space for any actual code.
>"Mixing of variable length indent"? Please tell me what that means
and where I did it.

It seemed, that you want him to mix 2 and 4 cols indentation...
No, he was sayin the code was indifferent to the spacing.
>It's an output statement. You don't "parse" output. Unless you meant
spellchecked or proofread...

Not you, but the compiler needn't.
I propose to ignore this as it doesn't seem to have any relationship
to the point being made.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 8 '06 #56
Mark McIntyre wrote, in regard to tab vs. space indentation:
Because, as you know from the elsehtread discussion, nobody can agree
on the size and so what looks nicely formatted to you, with tabstops
set to eight, looks hideous to me, with them set to 4, and looks
bizarre in a proportional font. If you use spaces, everything stays
nicely lined up.
With proportional font, nothing stays nicely lined up, whether
you use spaces or tabs.
>
As I said elsethread, in large complex programmes, with many levels of
intentation, eight spaces becomes quite unworkable in no time flat. If
you stick to a sensible linelength, by the time you're five or six
levels of indentation in, youre out of space for any actual code.
By the time you are at 5 or 6 levels of indentation, you need to
refactor the code. Very rarely is it appropriate to be that
deeply nested. The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C. A "large
complex program" absolutely must be broken down into
simple manageable components. Modularity really is a
good idea.

Jul 8 '06 #57

Bill Pursell wrote:
By the time you are at 5 or 6 levels of indentation, you need to
refactor the code. Very rarely is it appropriate to be that
deeply nested. The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.
This is from the first ever serious exercise I did. It was a sudoku
solver.

for (int i=0; i<3; i++) // Set up 'box' matrix
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
for (int l=0; l<3; l++)
for (int m=0; m<9; m++)
if (init->state[(3*i)+k][(3*j)+l] == m+1)
init->box[(3*i)+j][m] = 0;

Jul 8 '06 #58

ballpointpenthief wrote:
Bill Pursell wrote:
By the time you are at 5 or 6 levels of indentation, you need to
refactor the code. Very rarely is it appropriate to be that
deeply nested. The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.

This is from the first ever serious exercise I did. It was a sudoku
solver.

for (int i=0; i<3; i++) // Set up 'box' matrix
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
for (int l=0; l<3; l++)
for (int m=0; m<9; m++)
if (init->state[(3*i)+k][(3*j)+l] == m+1)
init->box[(3*i)+j][m] = 0;
I seem to have failed in lining it up aswell.

Jul 8 '06 #59
ballpointpenthief wrote:
Bill Pursell wrote:
By the time you are at 5 or 6 levels of indentation, you need to
refactor the code. Very rarely is it appropriate to be that
deeply nested. The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.

This is from the first ever serious exercise I did. It was a sudoku
solver.

for (int i=0; i<3; i++) // Set up 'box' matrix
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
for (int l=0; l<3; l++)
for (int m=0; m<9; m++)
if (init->state[(3*i)+k][(3*j)+l] == m+1)
init->box[(3*i)+j][m] = 0;
I think this is intended as an example of code that
requires deep indentation. I think it's actually a great
example of code that needs to be re-designed. One
idea that immediately springs to mind is:

struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.

Jul 8 '06 #60

Bill Pursell wrote:
ballpointpenthief wrote:
Bill Pursell wrote:
By the time you are at 5 or 6 levels of indentation, you need to
refactor the code. Very rarely is it appropriate to be that
deeply nested. The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.
This is from the first ever serious exercise I did. It was a sudoku
solver.

for (int i=0; i<3; i++) // Set up 'box' matrix
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
for (int l=0; l<3; l++)
for (int m=0; m<9; m++)
if (init->state[(3*i)+k][(3*j)+l] == m+1)
init->box[(3*i)+j][m] = 0;

I think this is intended as an example of code that
requires deep indentation.
Yes, that's right.
I think it's actually a great
example of code that needs to be re-designed. One
idea that immediately springs to mind is:

struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.
I don't think my programme needs to be redesigned. I don't understand
how you can infer that from what I posted.

Given the current board (.state), we need a way of knowing where each
number can go.
(.poss), so we can put it into a solving function (which, is what the
..low variable is for).

struct sud {
int state[9][9];
_Bool row[9][9];
_Bool col[9][9];
_Bool box[9][9];
_Bool ava[9][9];
_Bool poss[9][9][9];
int nposs[9][9];
int low;
} ;

void init(struct sud *init) // Compute matrices
{
for (int i=0; i<9; i++) // Set up row and column matrices
for (int j=0; j<9; j++)
{
init->row[i][j] = 1;
init->col[i][j] = 1;
init->box[i][j] = 1;
if (!init->state[i][j])
init->ava[i][j] = 1;
else
init->ava[i][j] = 0;
for (int k=0; k<9; k++)
{
if (init->state[i][k] == j+1)
init->row[i][j] = 0;
if (init->state[k][i] == j+1)
init->col[i][j] = 0;
}
}
for (int i=0; i<3; i++) // Set up box matrix
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
for (int l=0; l<3; l++)
for (int m=0; m<9; m++)
if (init->state[(3*i)+k][(3*j)+l] == m+1)
init->box[(3*i)+j][m] = 0;

for (int i=0; i<9; i++) // multiply elements from each previous 9x9
mats & obtain 9x9x9
for (int j=0; j<9; j++)
for (int k=0; k<9; k++)
init->poss[i][j][k] = init->row[j][i] * init->col[k][i] *
init->box[((k-(k%3))/3) + (j-(j%3))][i] * init->ava[j][k];

init->low = 10;
for (int i=0; i<9; i++) // Set up number of possibilities matrix
for (int j=0; j<9; j++)
{
int count=0;
for (int k=0; k<9; k++)
if (init->poss[k][i][j])
count++;
init->nposs[i][j] = count;
if ((init->low count) && (count))
init->low = count;
}
if (init->low == 10)
init->low = 0;
}

Jul 8 '06 #61
On 8 Jul 2006 04:30:44 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>Mark McIntyre wrote, in regard to tab vs. space indentation:
>As I said elsethread, in large complex programmes, with many levels of
intentation, eight spaces becomes quite unworkable in no time flat. If
you stick to a sensible linelength, by the time you're five or six
levels of indentation in, youre out of space for any actual code.

By the time you are at 5 or 6 levels of indentation, you need to
refactor the code.
Sometimes. Sometimes not.
>Very rarely is it appropriate to be that deeply nested.
I disagree with such sweeping statements.
>The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.
Then you've less experience than me.
>A "large
complex program" absolutely must be broken down into
simple manageable components. Modularity really is a
good idea.
Sure, but this has nothing to do with the level of indentation, and
has its downside too (eg increasing execution time due to stack setup
/ parameter preparation etc) . Working with large multidimensional
arrays might be an example.
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 8 '06 #62
On 8 Jul 2006 06:09:31 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.
a) how?
b) with what cost at runtime?

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 8 '06 #63
Mark McIntyre wrote:
On 8 Jul 2006 04:30:44 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:

>>Mark McIntyre wrote, in regard to tab vs. space indentation:

>>>As I said elsethread, in large complex programmes, with many levels of
intentation, eight spaces becomes quite unworkable in no time flat. If
you stick to a sensible linelength, by the time you're five or six
levels of indentation in, youre out of space for any actual code.

By the time you are at 5 or 6 levels of indentation, you need to
refactor the code.


Sometimes. Sometimes not.

>>Very rarely is it appropriate to be that deeply nested.


I disagree with such sweeping statements.

>>The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.


Then you've less experience than me.

>>A "large
complex program" absolutely must be broken down into
simple manageable components. Modularity really is a
good idea.


Sure, but this has nothing to do with the level of indentation, and
has its downside too (eg increasing execution time due to stack setup
/ parameter preparation etc) . Working with large multidimensional
arrays might be an example.
The cost is often small, if the extracted function is short, it is a
likely candidate for inlining. If it is long, the call overhead (as a
percentage) is low.

--
Ian Collins.
Jul 8 '06 #64
Mark McIntyre wrote:
On 8 Jul 2006 06:09:31 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.

a) how?
Via addition.
b) with what cost at runtime?
Practically none. You either set up your memory
so that all of the structures representing a cell in
the grid are contiguous and iterate over them with
a simple for loop, or if for some reason you can't
make them contiguous, you establish an array
of pointers into the data structure that you can
iterate over. I am pretty sure that the difference
is going to be completely negligible, but I would
bet that

for (v = start; v< end; v++)
do_something(v);

will be more efficient than

for (i=0; i<3; i++)
for (j=0;j<3;j++)
for(k=0;k<3;k++)
for(l=0;l<3;l++)
do_something(i,j,k,l);

And it is certainly easier to read. It would be
even cleaner to understand:

iterate_over_grid(do_something);

Jul 8 '06 #65

ballpointpenthief wrote:
Bill Pursell wrote:
ballpointpenthief wrote:
Bill Pursell wrote:
By the time you are at 5 or 6 levels of indentation, you need to
refactor the code. Very rarely is it appropriate to be that
deeply nested. The only time I've ever seen a situation where
it is appropriate to be that deeply nested is in VHDL, where
your first line of actual code is generally indented 3 or 4 levels.
I've never seen a case where it's appropriate in C.
>
This is from the first ever serious exercise I did. It was a sudoku
solver.
>
for (int i=0; i<3; i++) // Set up 'box' matrix
for (int j=0; j<3; j++)
for (int k=0; k<3; k++)
for (int l=0; l<3; l++)
for (int m=0; m<9; m++)
if (init->state[(3*i)+k][(3*j)+l] == m+1)
init->box[(3*i)+j][m] = 0;
I think this is intended as an example of code that
requires deep indentation.

Yes, that's right.
I think it's actually a great
example of code that needs to be re-designed. One
idea that immediately springs to mind is:

struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.

I don't think my programme needs to be redesigned. I don't understand
how you can infer that from what I posted.
I'm simply stating that the code snippet you posted was
obfuscated. You are using a bunch of nested for loops
for the purpose of iterating over your data structure. I'm
arguing that it would be cleaner to write it as
a single loop. If the program as currently designed
does not allow that iteration, then I think some extra
work should be put into the data structures. Sudoku
has a concept of squares and grids and rows and columns
(I'm not a Sudoku fan, so I don't know if they have
technical names in the game.) All I see in the code
is indexes i,j,k,l,m. I think you're iterating over the
rows, or over the columns, or over the cells, but it's
not entirely clear. It would be better to make calls
like:

iterate_over_rows(do_something);
or
iterate_over_all_cells(do_something);

where do_something is a function pointer that will
act on each row or each cell. It makes understanding
the code easier, and it reduces the problem of
excessive indentation.

Jul 8 '06 #66
Skarmander wrote:
Flash Gordon wrote:
>Skarmander wrote:
>>Richard Heathfield wrote:
jaysome said:

On Fri, 07 Jul 2006 09:10:14 +0000, Richard Heathfield
<in*****@invalid.invalidwrote:
>
<snip>
What other Standard C functions would be good candidates for the
"-function" option?

Just gets(). But I'd flag a few others as being "experts-only"
functions, which you should not use in "real" code unless you know
/exactly/ what you're doing:

<snip>
From <stdlib.h>

[...] calloc, malloc, realloc, free, [...]

Let's get this straight: you shouldn't dynamically allocate memory in
C unless you're an expert?

It is extremely easy to get wrong.
I see you did not address this point.
>>Well, actually, no arguments there -- but why not just say C is for
experts and leave it at that, then? For most applications, you need
to be an expert to write a program *without* dynamic memory allocation!

Well, in significant parts of the embedded world you are explicitly
banned from using allocated memory, and I wrote a *lot* of code
without any difficulty with that restriction even when I was new to
programming.

Oh, let's get *that* straight too: obviously it's actually very *easy*
to write code if you can't use more than, say, 42 memory units exactly
-- or tell people such code can't be written.
You haven;t kept up with the embedded world, have you. There are pretty
powerful embedded systems with lots of memory. I know of one embedded
system which was upgraded to 1MB of RAM in the days when 640K was still
considered plenty for a desktop PC (it may even have been done before
you could get a desktop PC with 640K of RAM, since it was done before I
came across the project). Don't assume you know what goes on in all
parts of the embedded industry.
For many applications that's simply not good enough, though. You'll want
a program that can scale to core without having to recompile it.
I never said it was good enough for all or even the majority of C
programs, and certainly did not say it was the case for all desktop or
server applications! I only stated that there were plenty of
applications where dynamic memory allocation is not needed.
If you want a program that has to utilize those 42 units of memory to
the best of its ability, it's not unthinkable that you'll end up
implementing (pseudo-)dynamic memory allocation yourself.
I've had to do that *exactly* once. That was on a project where they had
selected completely the wrong HW for the job a long time before I became
involved. I was just brought on to pick up the pieces and try to at
least get *something* out the door.
>For example, the first significant program I ever wrote (which I wrote
in BASIC) was "The Game of Life".
http://www.google.com/search?sourcei...ame+of+life%22

If you have a static board size there is absolutely no need for
dynamic memory allocation. IIRC it was interesting to implement.
The key point being "if you have a static board size". And for Life,
that's indeed not a significant restriction.
There are plenty of other applications where it is not a significant
restriction. As well as plenty where it is. Did you know that a commonly
used text editor has a fixed maximum size of text document it can
process? A limit that is orders of magnitude smaller than the amount of
free memory on the PC I am currently using?
>There are plenty of other significant projects one can implement
without dynamic memory allocation.

This I do not dispute.
So why do you say that limiting the use of dynamic memory allocation to
experts would limit the use of C to experts?
>Sometimes by having a reasonable static size and reporting if the user
tries to go beyond it, sometimes without any need at all for dynamic
memory allocation.

But the latter class is a minority,
I don't know whether it is a minority or not, but it is an *extremely*
large class. I had several years of programming for a living before I
came across a situation at work where using dynamic allocation was the
simplest solution.
and the former a distinct nuisance.
I cannot recount the number of times a program (quite likely written in
C) used a "reasonable" static size and refused my input.
I never said that it was always appropriate.
The programmer
responsible would probably shug their shoulders, increase the #define'd
constants a bit and recompile. Problem solved! For now.
When an application really does need dynamic memory allocation because
there is no reasonable static size (which is more often the case when
writting SW for others than when writing it for oneself and *not*
distribution it as source) then you want it written by someone
sufficiently expert that they will get the dynamic memory allocation
right, and some otherwise good programmers don't have the experience to
do this.

Personally, I would want there to be an expert programmer involved in
*all* of the complex software that I use, unfortunately I'm not
convinced that this is the case.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 8 '06 #67
On 8 Jul 2006 13:58:21 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>Mark McIntyre wrote:
>On 8 Jul 2006 06:09:31 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.

a) how?

Via addition.
I was thinking more of you showing us how this works, rather than a
vague comment. I'd have said arithmetic myself.
>b) with what cost at runtime?

Practically none.
Mhm, and you've tested this in all possible cases?
>iterate over. I am pretty sure that the difference
is going to be completely negligible, but I would
bet that

for (v = start; v< end; v++)
do_something(v);

will be more efficient than

for (i=0; i<3; i++)
for (j=0;j<3;j++)
for(k=0;k<3;k++)
for(l=0;l<3;l++)
do_something(i,j,k,l);
And I'm willing to bet that its quite impossible to predict which will
be more efficient, and that it will depend on

a) compiler flags
b) operating system
c) memory layout and access rules
d) object type and structure
e) CPU structure, pipelines, branch methodology etc
f) number and size of registers
e) other things, too tedious to enumerate

This is rather like the old chestnut about the guy who insisted on
unrolling all his loops, and couldn't work out why they ran slower on
a Convex.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 8 '06 #68
On Sun, 09 Jul 2006 08:12:12 +1200, in comp.lang.c , Ian Collins
<ia******@hotmail.comwrote:
>Mark McIntyre wrote:
>Sure, but this has nothing to do with the level of indentation, and
has its downside too (eg increasing execution time due to stack setup
/ parameter preparation etc) . Working with large multidimensional
arrays might be an example.

The cost is often small, if the extracted function is short, it is a
likely candidate for inlining. If it is long, the call overhead (as a
percentage) is low.
But not if the function is called many many times.

This is a real world situation I've been in. Some pricing calcs ran
significantly slower after we refactored the code along the lines
discussed here. We eventually realised that a specific set of
functions were called repeatedly in tight loops. By manually inlining
the code, we more than doubled performance, at the expense of more
complex code and some repetition.

The code now has comment blocks to warn people NOT to refactor it
again. I fully expect it to happen anyway. :-(
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 8 '06 #69
On 2006-07-08, Jiri Slaby <ge*@wo.czwrote:
Andrew Poelstra napsal(a):
>1) Tabs are never correct indentation.

why? where?
They display inconsistantly; on Usenet they often don't display, and they
have different widths on different editors. If you want 8 spaces, that's
fine, but you should use spaces instead of tabs.
>2) Aside from that, there is no "correct" indentation. 2, 3, or 4-space
is fine. 8 is rarely readable for real code.

I don't think so, that's all.
You're entitled to your opinion, and I have no right to try and change that;
there's no right or wrong when it comes to style.
>"Mixing of variable length indent"? Please tell me what that means
and where I did it.

It seemed, that you want him to mix 2 and 4 cols indentation...
No, I wanted him to use 2 /or/ 4 cols indentation. Sorry if I didn't
make that clear enough.

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>
To email me, use "apoelstra" at the above domain.
"You people hate mathematics." -- James Harris
Jul 8 '06 #70
Flash Gordon wrote:
Skarmander wrote:
>Flash Gordon wrote:
>>Skarmander wrote:
Richard Heathfield wrote:
jaysome said:
>
>On Fri, 07 Jul 2006 09:10:14 +0000, Richard Heathfield
><in*****@invalid.invalidwrote:
>>
<snip>
>What other Standard C functions would be good candidates for the
>"-function" option?
>
Just gets(). But I'd flag a few others as being "experts-only"
functions, which you should not use in "real" code unless you know
/exactly/ what you're doing:
>
<snip>
From <stdlib.h>
>
[...] calloc, malloc, realloc, free, [...]
>
Let's get this straight: you shouldn't dynamically allocate memory
in C unless you're an expert?

It is extremely easy to get wrong.

I see you did not address this point.
Sure I did, in this statement:
>>>Well, actually, no arguments there
I don't think anybody's arguing that it's not a big source of mistakes. Then
again, plenty of common tasks in C are big sources of mistakes, as the
lengthy FAQ illustrates.
>>Well, in significant parts of the embedded world you are explicitly
banned from using allocated memory, and I wrote a *lot* of code
without any difficulty with that restriction even when I was new to
programming.

Oh, let's get *that* straight too: obviously it's actually very *easy*
to write code if you can't use more than, say, 42 memory units exactly
-- or tell people such code can't be written.

You haven;t kept up with the embedded world, have you. There are pretty
powerful embedded systems with lots of memory. I know of one embedded
system which was upgraded to 1MB of RAM in the days when 640K was still
considered plenty for a desktop PC (it may even have been done before
you could get a desktop PC with 640K of RAM, since it was done before I
came across the project). Don't assume you know what goes on in all
parts of the embedded industry.
I have no idea why this is relevant to my statement, but you are probably
misled by my "42 memory units". I deliberately used a magic number and
didn't specify what those units were. The idea that assuming a specific
amount of memory makes things easier holds whether you're talking 42 bytes
or 42 megabytes. (Of course, there's a huge practical difference.)
>For many applications that's simply not good enough, though. You'll
want a program that can scale to core without having to recompile it.

I never said it was good enough for all or even the majority of C
programs, and certainly did not say it was the case for all desktop or
server applications! I only stated that there were plenty of
applications where dynamic memory allocation is not needed.
And my point is that as long as such programs are *not* the majority,
dynamic memory allocation is something that belongs in the arsenal of every
C programmer. We'll return to this later.

<snip>
There are plenty of other applications where it is not a significant
restriction. As well as plenty where it is. Did you know that a commonly
used text editor has a fixed maximum size of text document it can
process? A limit that is orders of magnitude smaller than the amount of
free memory on the PC I am currently using?
Well, I know that the Notepad that came with Windows 3.x, 95, 98 and
presumably ME was limited to 64K, a holdover from the segmented memory era.
Ironically, the DOS-based EDIT.COM that came with Windows 9x did not have
this limitation.

Of course, that version of Notepad is restricted to the point of being
inappropriate for anything more ambitious than a grocery list, so the size
limit is just the finishing touch.
>>There are plenty of other significant projects one can implement
without dynamic memory allocation.

This I do not dispute.

So why do you say that limiting the use of dynamic memory allocation to
experts would limit the use of C to experts?
I don't. I think it *should* limit the use of C to experts (at least for
applications programming -- but outside of applications programming there
are other things that require expert attention, so it probably evens out). I
don't really think it's acceptable for a C programmer to say "well, I
program C very well, but I can't really handle dynamic memory allocation".
If you said you had no idea how to use longjmp(), I could sympathize, but
dynamic memory allocation? No.

This is just me being a snob. In reality C is a tool, and it will be used
with various levels of competence. As long as the job gets done, you won't
hear anyone comment about how competently a tool was used. In the case of
static memory sllocation, you won't hear people comment until the job
instances get bigger.

I'm sure plenty of C users can write plenty of useful programs that do not
dynamically allocate memory. I'm also pretty sure most of the programs run
don't or shouldn't fall in this category.
>>Sometimes by having a reasonable static size and reporting if the user
tries to go beyond it, sometimes without any need at all for dynamic
memory allocation.

But the latter class is a minority,

I don't know whether it is a minority or not, but it is an *extremely*
large class. I had several years of programming for a living before I
came across a situation at work where using dynamic allocation was the
simplest solution.
Dynamic allocation is almost never the *simplest* solution in C.

The simplest solution is often the most appropriate one because simplicity
cuts development and maintenance costs -- but for general applications, when
the simplest solution involves no dynamic memory allocation, it will often
be *too* simple.
and the former a distinct nuisance.
I cannot recount the number of times a program (quite likely written
in C) used a "reasonable" static size and refused my input.

I never said that it was always appropriate.
My argument is that even were it is appropriate, it tends to become
inappropriate sooner than later.
The programmer
responsible would probably shug their shoulders, increase the
#define'd constants a bit and recompile. Problem solved! For now.

When an application really does need dynamic memory allocation because
there is no reasonable static size (which is more often the case when
writting SW for others than when writing it for oneself and *not*
distribution it as source) then you want it written by someone
sufficiently expert that they will get the dynamic memory allocation
right, and some otherwise good programmers don't have the experience to
do this.
If dynamic memory allocations is for experts, then please let C be for
experts, so I don't have to cope with exactly this attitude anymore. (Note:
snobbery.)

"Well I thought a maximum of 12,564 sprockets would be reasonable enough,
but no worries if it's not, you just go to arbitrarylimits.h and increase
the third #define from the top to 47. Recompile and reinstall and you're all
set. That wasn't so hard, was it?"

Like you said, I'm sure there are a good many situations where this will
work. But it definitely does not work in general, and software tends to
evolve in the "more general" direction.

S.
Jul 8 '06 #71
Mark McIntyre wrote:
On 8 Jul 2006 13:58:21 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
Mark McIntyre wrote:
On 8 Jul 2006 06:09:31 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:

struct value *v;
for (v=start; v<end; v++)
v->box[v->val] = 0;

where v iterates over all the entries in the game grid.

a) how?
Via addition.

I was thinking more of you showing us how this works, rather than a
vague comment. I'd have said arithmetic myself.
Below is some code that more or less does what I'm thinking
of.
b) with what cost at runtime?
Practically none.

Mhm, and you've tested this in all possible cases?
Of course not.
iterate over. I am pretty sure that the difference
is going to be completely negligible, but I would
bet that

for (v = start; v< end; v++)
do_something(v);

will be more efficient than

for (i=0; i<3; i++)
for (j=0;j<3;j++)
for(k=0;k<3;k++)
for(l=0;l<3;l++)
do_something(i,j,k,l);

And I'm willing to bet that its quite impossible to predict which will
be more efficient, and that it will depend on

a) compiler flags
b) operating system
c) memory layout and access rules
d) object type and structure
e) CPU structure, pipelines, branch methodology etc
f) number and size of registers
e) other things, too tedious to enumerate

I agree whole-heartedly. I'm not in anyway suggesting that
this is a performance benefit. (Well, okay, I did somewhat suggest
that, but it was really just to deflect the counter argument that
my method may cost in performance. It might, but if the difference
matters then a new compiler is probably warranted.) I'm
coming at this strictly from a maintenance and aesthetic perspective.
Here's a sample of the type of code I am picturing. In my experience
(which is limited), I find this type of structure extremely useful.
There
are cases where a sufficiently complex data structure may make
it impractical to store multiple different accesses into the
data, but I find multiple nested loops of indices and computing
things from them to be generally difficult to understand and
fairly brittle.
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#define NUM_CELLS 81
#define NUM_ROWS 9
#define NUM_COLS 9
#define NUM_BOX 9

/* All the command line arguments. */
struct args {
FILE *in;
};

typedef enum {
top,
right,
left,
bottom
} edge;

/*
* Information about a cell in the game grid.
*/
struct cell {
int index;
int row;
int column;
int box;
int value;
enum {fixed, variable} type;
struct cell *above;
struct cell *right;
struct cell *left;
struct cell *below;
};

void parse_args(struct args *a, int argc, char *const*argv);
void read_initial_values(struct cell *c, FILE *in);
void initialize_grid(struct cell *, struct cell
*row[NUM_ROWS][NUM_COLS],
struct cell *col[NUM_COLS][NUM_ROWS], struct cell **);
int compute_box(int i);
int at_edge(int index, edge which);

int
main(int argc, char **argv)
{
struct cell grid[NUM_CELLS];
struct args a;
struct cell *row[NUM_ROWS][NUM_COLS];
struct cell *col[NUM_COLS][NUM_ROWS];
struct cell *box[NUM_BOX];
struct cell *this;
const struct cell *end=grid+NUM_CELLS;

parse_args(&a, argc, argv);
initialize_grid(grid, row, col, box);
read_initial_values(grid, a.in);

/* print the grid. */
for (this = grid; this < end; this++)
printf("%d%s", this->value, this->right ? " ":"\n");

/* print column 5. */
printf("\n column 5:\n");
for (this = col[5][0]; this; this=this->below)
printf("%d%s", this->value, this->below? " ":"\n");

/* print row 3. */
printf("\n row 3:\n");
for (this = row[3][0]; this; this=this->right)
printf("%d%s", this->value, this->right? " ":"\n");
return EXIT_SUCCESS;
}

/*
* initialize_grid()
*
* Set up the indices in all of the cells.
*/
void
initialize_grid(struct cell *g, struct cell *row[NUM_ROWS][NUM_COLS],
struct cell *col[NUM_COLS][NUM_ROWS], struct cell **box)
{
int i;
int row_idx;
int col_idx;

row_idx = col_idx = 0;
for (i=0; i< NUM_CELLS; i++) {
g[i].index = 0;
g[i].row = row_idx;
g[i].column = col_idx;
g[i].box = compute_box(i);
g[i].value = 0;
g[i].type = variable;
g[i].above = at_edge(i,top) ? NULL : g+i-NUM_COLS;
g[i].right = at_edge(i,right) ? NULL : g+i+1;
g[i].left = at_edge(i,left) ? NULL : g+i-1;
g[i].below = at_edge(i,bottom)? NULL : g+i+NUM_COLS;
row[row_idx][col_idx] = g+i;
col[col_idx][row_idx] = g+i;
box[compute_box(i)] = g+i;
if (col_idx == NUM_COLS - 1)
row_idx++;
col_idx = (col_idx + 1) % NUM_COLS;

}
assert(row_idx == NUM_ROWS);
assert(col_idx == 0);
}

/*
* at_edge()
*
* return true if the given index
* is at the given edge of the grid.
*/
int /* this is a boolean value */
at_edge(int index, edge which)
{
int ret;
switch(which) {
case top : ret = index < NUM_COLS; break;
case right : ret = index % NUM_COLS == (NUM_COLS-1); break;
case left : ret = index % NUM_COLS == 0; break;
case bottom: ret = index >= (NUM_COLS*(NUM_ROWS-1)); break;
}
return ret;
}

/*
* compute_box() TODO
*
* Compute the index of the box that
* contains cell i.
*/
int
compute_box(int i)
{
return 0;
}

/*
* parse_args()
*
* parse the command line arguments.
*/
void
parse_args(struct args *a, int argc, char *const*argv)
{
a->in = stdin;
}

/*
* read_initial_values()
*
* read the input stream to determine the
* initial fixed values in the game grid.
* TODO
*/
void
read_initial_values(struct cell *grid, FILE *in)
{
/* Insert some toy values for testing purposes. */
grid[14].value = 5;
grid[14].type = fixed;

grid[34].value = 7;
grid[34].type = fixed;
}
Note: the above code was cut/pasted into a web interface, and
a few lines were modified by hand after the paste. Apologies
for any errors.

Jul 9 '06 #72

Andrew Poelstra wrote:
On 2006-07-08, Jiri Slaby <ge*@wo.czwrote:
Andrew Poelstra napsal(a):
1) Tabs are never correct indentation.
why? where?

They display inconsistantly; on Usenet they often don't display, and they
have different widths on different editors. If you want 8 spaces, that's
fine, but you should use spaces instead of tabs.
The second point you make (that tabstops have different widths in
different
editors) is not a point against tabs. It simply demonstrates that
people
need to learn their editor. Editors do not randomly select a
tabstop setting (at least, no editor that I'm aware of. Wouldn't
that be fun, though?). If your editor is displaying tabstops on
a column width that you don't like, it is because of the configuration.
If you don't know how to change the configuration, you shouldn't
be using that editor. (or you should learn how to configure it)

Jul 9 '06 #73
Skarmander wrote:
Flash Gordon wrote:
>Skarmander wrote:
>>Flash Gordon wrote:
Skarmander wrote:
Richard Heathfield wrote:
>jaysome said:
>>
>>On Fri, 07 Jul 2006 09:10:14 +0000, Richard Heathfield
>><in*****@invalid.invalidwrote:
>>>
><snip>
>>What other Standard C functions would be good candidates for the
>>"-function" option?
>>
>Just gets(). But I'd flag a few others as being "experts-only"
>functions, which you should not use in "real" code unless you know
>/exactly/ what you're doing:
>>
<snip>
>From <stdlib.h>
>>
> [...] calloc, malloc, realloc, free, [...]
>>
Let's get this straight: you shouldn't dynamically allocate memory
in C unless you're an expert?

It is extremely easy to get wrong.

I see you did not address this point.
Sure I did, in this statement:
>>>>Well, actually, no arguments there
It would have been more obvious had you put that statement by the comment.
I don't think anybody's arguing that it's not a big source of mistakes.
Then again, plenty of common tasks in C are big sources of mistakes, as
the lengthy FAQ illustrates.
Indeed.
>>>Well, in significant parts of the embedded world you are explicitly
banned from using allocated memory, and I wrote a *lot* of code
without any difficulty with that restriction even when I was new to
programming.

Oh, let's get *that* straight too: obviously it's actually very
*easy* to write code if you can't use more than, say, 42 memory units
exactly -- or tell people such code can't be written.

You haven;t kept up with the embedded world, have you. There are
pretty powerful embedded systems with lots of memory. I know of one
embedded system which was upgraded to 1MB of RAM in the days when 640K
was still considered plenty for a desktop PC (it may even have been
done before you could get a desktop PC with 640K of RAM, since it was
done before I came across the project). Don't assume you know what
goes on in all parts of the embedded industry.
I have no idea why this is relevant to my statement, but you are
probably misled by my "42 memory units". I deliberately used a magic
number and didn't specify what those units were. The idea that assuming
a specific amount of memory makes things easier holds whether you're
talking 42 bytes or 42 megabytes. (Of course, there's a huge practical
difference.)
Ah, but on this embedded system the assumption of X units was broken
because it was found not to be sufficient so they increased the memory
to what was then an extremely large amount.
>>For many applications that's simply not good enough, though. You'll
want a program that can scale to core without having to recompile it.

I never said it was good enough for all or even the majority of C
programs, and certainly did not say it was the case for all desktop or
server applications! I only stated that there were plenty of
applications where dynamic memory allocation is not needed.
And my point is that as long as such programs are *not* the majority,
dynamic memory allocation is something that belongs in the arsenal of
every C programmer. We'll return to this later.
Where do you get your statistics? I know I have far more embedded
processors in my house than PCs (and I have more PCs than most people)
and it is entirely possibly I regularly use more programs on embedded
processors than I use on PCs. I have no easy way to find out whether
those embedded programs use dynamic memory allocation or not.
<snip>
>There are plenty of other applications where it is not a significant
restriction. As well as plenty where it is. Did you know that a
commonly used text editor has a fixed maximum size of text document it
can process? A limit that is orders of magnitude smaller than the
amount of free memory on the PC I am currently using?
Well, I know that the Notepad that came with Windows 3.x, 95, 98 and
presumably ME was limited to 64K, a holdover from the segmented memory
era. Ironically, the DOS-based EDIT.COM that came with Windows 9x did
not have this limitation.
It is still in XP and I believe unchanged.
Of course, that version of Notepad is restricted to the point of being
inappropriate for anything more ambitious than a grocery list, so the
size limit is just the finishing touch.
I find it very useful when I want to be able to quickly take note. It
starts instantly and does exactly what I tell it to. I don't use it for
editing code though.
>>>There are plenty of other significant projects one can implement
without dynamic memory allocation.

This I do not dispute.

So why do you say that limiting the use of dynamic memory allocation
to experts would limit the use of C to experts?
I don't. I think it *should* limit the use of C to experts (at least for
applications programming
Even for programs that have absolutely no need of dynamic memory? I've
already pointed out that there are plenty of them whether or not they
are the majority.
-- but outside of applications programming
there are other things that require expert attention, so it probably
evens out). I don't really think it's acceptable for a C programmer to
say "well, I program C very well, but I can't really handle dynamic
memory allocation". If you said you had no idea how to use longjmp(), I
could sympathize, but dynamic memory allocation? No.
So now you are restricting your requirement to just the range of
programming tasks you know use dynamic memory allocation?
This is just me being a snob. In reality C is a tool, and it will be
used with various levels of competence. As long as the job gets done,
you won't hear anyone comment about how competently a tool was used. In
the case of static memory sllocation, you won't hear people comment
until the job instances get bigger.
There are plenty of situations where there is some other limit that
prevents the job getting bigger.
I'm sure plenty of C users can write plenty of useful programs that do
not dynamically allocate memory.
And for such programs it does not matter whether the author has learnt
dynamic memory allocation or not yet. So restricting dynamic memory
allocation to experts does *not* restrict C to experts for those programs.
I'm also pretty sure most of the
programs run don't or shouldn't fall in this category.
I know for a fact from personal experience that it is possible to spend
years programming professionally on use programs, so whether they are
the majority or not there are plenty of them. BTW, I *did* know how to
manage dynamic memory allocation, I just did not need it.
>>>Sometimes by having a reasonable static size and reporting if the user
tries to go beyond it, sometimes without any need at all for dynamic
memory allocation.

But the latter class is a minority,

I don't know whether it is a minority or not, but it is an *extremely*
large class. I had several years of programming for a living before I
came across a situation at work where using dynamic allocation was the
simplest solution.
Dynamic allocation is almost never the *simplest* solution in C.
Well, it has been the simplest solution for me in a number of instances
where I had no way of knowing in advance how much memory would be required.
The simplest solution is often the most appropriate one because
simplicity cuts development and maintenance costs -- but for general
applications, when the simplest solution involves no dynamic memory
allocation, it will often be *too* simple.
If it does not solve the problem due to being too simple then it fails
to be the simplest solution because it is not a solution. If you are
going to allow things which don't solve the problem then the "simplest
solution" is
int main(void)
{
return 0;
}
> and the former a distinct nuisance.
I cannot recount the number of times a program (quite likely written
in C) used a "reasonable" static size and refused my input.

I never said that it was always appropriate.
My argument is that even were it is appropriate, it tends to become
inappropriate sooner than later.
If a program lasts the entire lifetime of the kit it is designed to
support without such things having to be changed (say, 20 years), I'm
happy. The next piece of kit will require changes to the supporting
software in any case.
> The programmer
responsible would probably shug their shoulders, increase the
#define'd constants a bit and recompile. Problem solved! For now.

When an application really does need dynamic memory allocation because
there is no reasonable static size (which is more often the case when
writting SW for others than when writing it for oneself and *not*
distribution it as source) then you want it written by someone
sufficiently expert that they will get the dynamic memory allocation
right, and some otherwise good programmers don't have the experience
to do this.
If dynamic memory allocations is for experts, then please let C be for
experts, so I don't have to cope with exactly this attitude anymore.
(Note: snobbery.)
I disagree. I've worked on C projects with people who have not yet
finished their degrees and are not yet expert programmers, let alone
expert C programmers, and it was no problem at all. You just have an
expert programmer reviewing their work and assisting them as necessary.
The same applies *whatever* language is being used.
"Well I thought a maximum of 12,564 sprockets would be reasonable
enough, but no worries if it's not, you just go to arbitrarylimits.h and
increase the third #define from the top to 47. Recompile and reinstall
and you're all set. That wasn't so hard, was it?"
The hardware can only cope with 12564 sprockets, a static array of 12564
sprockets is not an unreasonable amount of memory, OK I'll use a fixed size.

Oh, we are producing a new piece of hardware that can cope with more?
And you have all these other extra requirements? OK, we will spend the
extra 5 minutes on top of the 6 man-months to implement the other
requirements so as to increase the array size. Why did we limit it so we
now have to waste that 5 minutes? Well, it saved us a day of development
time and we will have to go through a *lot* of 5 minutes before we hit
the point where we've lots on that saving. Anyway, 5 minutes on top of
that 6 man-months is hardly significant, is it?
Like you said, I'm sure there are a good many situations where this will
work. But it definitely does not work in general, and software tends to
evolve in the "more general" direction.
Just as not using dynamic memory allocation does not work in general
(i.e. there are a significant set or problems where it is appropriate),
so *using* dynamic memory allocation does not work in general (i.e.
there are a significant set of problems where it is inappropriate).

There are programs I've written where the only way I could have used
dynamic memory allocation would have been something like:

{
T *p = malloc(SOME_CONSTANT);
if (p == NULL)
/* we are really in the shit now */
else {
/* do stuff */
free(p);
}
}

Personally I found
{
T p[SOME_CONSTANT];
/* do stuff */
}
to be a far simpler solution.

I will admit that some of these projects where only a few man-years of
software development, so only small programs. Oh, and the only way to
increase the amount of data that the program would be required to handle
would be to replace some hardware where one circuit board alone cost
9000UKP (18 layer double sided), I don't know how much on top of that
was spent on components, now how much the other hardware that would
require replacing cost.
--
Flash Gordon, living in interesting times.
Web site - http://home.flash-gordon.me.uk/
comp.lang.c posting guidelines and intro:
http://clc-wiki.net/wiki/Intro_to_clc
Jul 9 '06 #74
On 8 Jul 2006 23:56:47 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>Mark McIntyre wrote:
>On 8 Jul 2006 13:58:21 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>but I would bet that

for (v = start; v< end; v++)
do_something(v);

will be more efficient than

for (i=0; i<3; i++)
>And I'm willing to bet that its quite impossible to predict which will
be more efficient,

I agree whole-heartedly. I'm not in anyway suggesting that
this is a performance benefit. (Well, okay, I did somewhat suggest
that,
Er, no ,you very clearly stated it! See above retained context.
>but it was really just to deflect the counter argument that
my method may cost in performance. It might, but if the difference
matters then a new compiler is probably warranted.)
Thats silly - there are many cases where refactoring code seems
counterintuitive to the simplistic approach that you've advocated.
Such instances do not mean that you have to buy new toolsets.

--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 9 '06 #75
Mark McIntyre wrote:
On 8 Jul 2006 23:56:47 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
Mark McIntyre wrote:
On 8 Jul 2006 13:58:21 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:

but I would bet that

for (v = start; v< end; v++)
do_something(v);

will be more efficient than

for (i=0; i<3; i++)
And I'm willing to bet that its quite impossible to predict which will
be more efficient,
I agree whole-heartedly. I'm not in anyway suggesting that
this is a performance benefit. (Well, okay, I did somewhat suggest
that,

Er, no ,you very clearly stated it! See above retained context.
You snipped an important part of the context. I wrote:
"I am pretty sure that the difference
is going to be completely negligible, but I would
bet that ..."

I was trying to point out that performance is not my
primary concern here, and that the performance difference
should be insignificant.
>
but it was really just to deflect the counter argument that
my method may cost in performance. It might, but if the difference
matters then a new compiler is probably warranted.)

Thats silly - there are many cases where refactoring code seems
counterintuitive to the simplistic approach that you've advocated.
Such instances do not mean that you have to buy new toolsets.
I don't understand that. Which simplistic approach do you think I am
advocating? I'm trying to say that when I see code that looks like:
for (i=0; i < N; i++)
for (j=0; j < M; j++)
for (k=0;k< P; k++)
for (l=0;l<Q; l++)
/* some code that computes an address based on i,j,k, and l*/

I find that it is usually easier to precompute the desired
addresses and build an array to iterate through linearly. I'm
acknowledging that this is not always possible, but
it has been in all cases that I've seen.

You made a point else-thread about refactoring code
to reduce such loops causing substantial performance
loss, but I suspect such losses were attributable to
other concerns than simply the overhead of the functions
used to eliminate the loop. When I refactor code to
eliminate such loops, I do a performance check. If
I come accross a case such as you described, I will
undoubtedly spend some time trying to understand
what other design issues are leading to the problem,
and I will stubbornly refuse to admit that I need to keep
the nested loops for several days. And when I see
a comment that tells me someone else tried to refactor
and it led to a performance loss...well, it depends, but
I suspect that I'll not believe it and duplicate all your
work. :)

Jul 9 '06 #76
On 9 Jul 2006 04:03:27 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>Mark McIntyre wrote:
>On 8 Jul 2006 23:56:47 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
>
but it was really just to deflect the counter argument that
my method may cost in performance. It might, but if the difference
matters then a new compiler is probably warranted.)

Thats silly - there are many cases where refactoring code seems
counterintuitive to the simplistic approach that you've advocated.
Such instances do not mean that you have to buy new toolsets.

I don't understand that. Which simplistic approach do you think I am
advocating?
The one you outlined in your post, ie unrolling the inner loops. This
is by absolutely no means guaranteed to be efficient, nor even
possible.
>I'm trying to say that when I see code that looks like:
for (i=0; i < N; i++)
for (j=0; j < M; j++)
for (k=0;k< P; k++)
for (l=0;l<Q; l++)
>I find that it is usually easier to precompute the desired
addresses and build an array to iterate through linearly.
And when N, M, P and Q all depend on the contents of the loops? Or
when you're on pipelined / vector hardware which can execute multiple
passes at once? You've just made your code massively less efficient
>I'm
acknowledging that this is not always possible, but
it has been in all cases that I've seen.
As I said earlier, there are many many reasons which mean this may not
work and may not be efficient code. A general principle of
optimisation is not to do it till you know you need to.
>You made a point else-thread about refactoring code
to reduce such loops causing substantial performance
loss, but I suspect such losses were attributable to
other concerns than simply the overhead of the functions
used to eliminate the loop.
No. surprisingly enough we were not all complete idiots and we did
check.
>and I will stubbornly refuse to admit that I need to keep
the nested loops for several days.
Admirable, but risky. Not wise to rule out anything.
>And when I see
a comment that tells me someone else tried to refactor
and it led to a performance loss...well, it depends, but
I suspect that I'll not believe it and duplicate all your
work. :)
Yeah, which is roughly the point at which I'd be reviewing your future
with the team. :-(
--
Mark McIntyre

"Debugging is twice as hard as writing the code in the first place.
Therefore, if you write the code as cleverly as possible, you are,
by definition, not smart enough to debug it."
--Brian Kernighan
Jul 9 '06 #77

Mark McIntyre wrote:
On 9 Jul 2006 04:03:27 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
Mark McIntyre wrote:
On 8 Jul 2006 23:56:47 -0700, in comp.lang.c , "Bill Pursell"
<bi**********@gmail.comwrote:
I find that it is usually easier to precompute the desired
addresses and build an array to iterate through linearly.

And when N, M, P and Q all depend on the contents of the loops? Or
when you're on pipelined / vector hardware which can execute multiple
passes at once? You've just made your code massively less efficient
That is an excellent point.
I'm acknowledging that this is not always possible, but
it has been in all cases that I've seen.

As I said earlier, there are many many reasons which mean this may not
work and may not be efficient code. A general principle of
optimisation is not to do it till you know you need to.
My first two rules of optimization:
1) don't do it
2) don't do it yet.
>
You made a point else-thread about refactoring code
to reduce such loops causing substantial performance
loss, but I suspect such losses were attributable to
other concerns than simply the overhead of the functions
used to eliminate the loop.

No. surprisingly enough we were not all complete idiots and we did
check.
I didn't actually intend to imply that you're an idiot, and I do
apologize that it reads that way.

Jul 9 '06 #78
On 2006-07-09, Bill Pursell <bi**********@gmail.comwrote:
>
Andrew Poelstra wrote:
>On 2006-07-08, Jiri Slaby <ge*@wo.czwrote:
Andrew Poelstra napsal(a):
1) Tabs are never correct indentation.

why? where?

They display inconsistantly; on Usenet they often don't display, and they
have different widths on different editors. If you want 8 spaces, that's
fine, but you should use spaces instead of tabs.

The second point you make (that tabstops have different widths in
different
editors) is not a point against tabs. It simply demonstrates that
people
need to learn their editor. Editors do not randomly select a
tabstop setting (at least, no editor that I'm aware of. Wouldn't
that be fun, though?). If your editor is displaying tabstops on
a column width that you don't like, it is because of the configuration.
If you don't know how to change the configuration, you shouldn't
be using that editor. (or you should learn how to configure it)
And then every time you read code written by someone with a different
tab width setting, you should reconfigure your editor?

That only applies to people who use tabs to align things, like so:
int main (int argc,
TAB;TAB; char *argv[])

which would become
int main (int argc,
TAB____;TAB____; char *argv[])

on an 8-spaced editor (assuming the original was 4).

However, with spaces you never have problems.

--
Andrew Poelstra <http://www.wpsoftware.net/projects/>
To email me, use "apoelstra" at the above domain.
"You people hate mathematics." -- James Harris
Jul 9 '06 #79

Andrew Poelstra wrote:
On 2006-07-09, Bill Pursell <bi**********@gmail.comwrote:
The second point you make (that tabstops have different widths in
different
editors) is not a point against tabs. It simply demonstrates that
people
need to learn their editor. Editors do not randomly select a
tabstop setting (at least, no editor that I'm aware of. Wouldn't
that be fun, though?). If your editor is displaying tabstops on
a column width that you don't like, it is because of the configuration.
If you don't know how to change the configuration, you shouldn't
be using that editor. (or you should learn how to configure it)

And then every time you read code written by someone with a different
tab width setting, you should reconfigure your editor?
No. The person who wrote the code should write it so
that things align properly regardless of the tabstop setting.
This is not difficult to do, and is only hampered by dogmatic
assertions that one must use only spaces. However,
if the author of the code failed to indent properly, you don't
reconfigure the editor, you merely reconfigure the session.
It is hardly difficult to type
:set ts=4

I don't know what is involved in changing the tabstop in
other editors, but I gather it is extremely difficult, given
that the great majority of persons I encounter don't know
how to do it.

Jul 9 '06 #80
"Bill Pursell" <bi**********@gmail.comwrites:
Andrew Poelstra wrote:
>On 2006-07-09, Bill Pursell <bi**********@gmail.comwrote:
The second point you make (that tabstops have different widths in
different
editors) is not a point against tabs. It simply demonstrates that
people
need to learn their editor. Editors do not randomly select a
tabstop setting (at least, no editor that I'm aware of. Wouldn't
that be fun, though?). If your editor is displaying tabstops on
a column width that you don't like, it is because of the configuration.
If you don't know how to change the configuration, you shouldn't
be using that editor. (or you should learn how to configure it)

And then every time you read code written by someone with a different
tab width setting, you should reconfigure your editor?

No. The person who wrote the code should write it so
that things align properly regardless of the tabstop setting.
This is not difficult to do, and is only hampered by dogmatic
assertions that one must use only spaces. However,
if the author of the code failed to indent properly, you don't
reconfigure the editor, you merely reconfigure the session.
It is hardly difficult to type
:set ts=4

I don't know what is involved in changing the tabstop in
other editors, but I gather it is extremely difficult, given
that the great majority of persons I encounter don't know
how to do it.
Yes, it's easy to type

:set ts=4

in vi (which happens to be the editor I normally use). Should I also
find out how to change the tabstop setting in my newsreader? My
pager? My web browser? My printer? My terminal emulator (if the
source is short enough for "cat foo.c")?

If I need to look at code that is legible only with 4-column tabstops,
I'm more likely to filter it through "expand -t 4" -- once I figure
out that 4 is the magic number, which probably won't be immediately
obvious. And then I'll wonder why the author didn't do this in the
first place -- or at least use the 8-column tabstops that are the
default in every piece of software I've ever used. (No doubt there
are counterexamples.)

Note that tabstop settings and indentation levels aren't necessarily
tied together. Before I started avoiding tabs altogether (<OT>except
in Makefiles -- sigh</OT>), I typically used 2-, 3-, or 4-column
indentation and 8-column tabstops; my editor, vi, handles this almost
transparently.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Jul 9 '06 #81
"Dann Corbit" <dc*****@connx.comwrote:
"Richard Bos" <rl*@hoekstra-uitgeverij.nlwrote in message
news:44****************@news.xs4all.nl...
jaysome <ja*****@spamcop.netwrote:
[snip]
What other Standard C functions would be good candidates for the
"-function" option?
None, really. gets() is the only one that can _not_ be used safely.
Functions like scanf() are easy to use unsafely, but can be made safe in
a simple, though WOMBATty, way, by constructing the format string at run
time, using something like (warning: not tested!)

sprintf(format_string, "%%%ds", current_size_of_buffer);
scanf(format_string, destination_string);

I would add strtok(), which is hopelessly broken. The POSIX strtok_r() is
the correct way to write a simple token parser.
I wouldn't. strtok() is very easy to misuse, but it _can_ be used
correcly. Usually, you're right, there are much better functions
(although I would not use strtok_r() unless I were already tied to POSIX
anyway - replacements for strtok() aren't that hard to write yourself,
in clean ISO C); but the option in question is for functions that are
irredeemably dangerous, not just a pain in the neck.
Anyway, I _have_ found strtok() useful. Just the once, IIRC, and the
circumstances now escape my memory, but that one time, strtok()
sufficed.

Richard
Jul 11 '06 #82
On Sun, 09 Jul 2006 10:54:18 +0100, Flash Gordon
<sp**@flash-gordon.me.ukwrote:
Skarmander wrote:
Well, I know that the Notepad that came with Windows 3.x, 95, 98 and
presumably ME was limited to 64K, a holdover from the segmented memory
era. Ironically, the DOS-based EDIT.COM that came with Windows 9x did
not have this limitation.

It is still in XP and I believe unchanged.
<OTNT/2k/XP notepad does not have the 64K limit.

I know from experience* it will happily try to slurp a file over 500MB
and (on the machine I was using then) swap for about half an hour
before completing that task.

* experience = the result of making a mistake. In this case I didn't
notice how big the log file, normally a few MB, had gotten.

- David.Thompson1 at worldnet.att.net
Jul 17 '06 #83
On Fri, 07 Jul 2006 14:57:30 GMT, Andrew Poelstra
<ap*******@wpsoftware.netwrote:
On 2006-07-07, de*****@hotmail.com <de*****@hotmail.comwrote:
putchar('\n\n');

This isn't correct. You can put two characters into single quotes. You'll
need to do printf ("\n\n"), two puts("") or two putchar ('\n').
Presumably you meant can't. In fact, the standard allows multiple
characters in a 'character constant' but the resulting value is
implementation-defined, and extremely likely to not produce what was
apparently desired here, although reasonably likely to produce a
single newline, which IMHO would actually be just fine here.

<snip much else>

- David.Thompson1 at worldnet.att.net
Jul 17 '06 #84

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

reply views Thread by Alexander F?hrmann | last post: by
reply views Thread by sipetar | last post: by
reply views Thread by shahrazad78 | last post: by
reply views Thread by NPC403 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.