473,320 Members | 2,111 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

What do you think about the code?

Can you give any comments on this code?
I used one goto, is it bad?

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <assert.h>

#define NOT_NULL 1
#define NUMERIC 2
#define MULTI_LINE 4

/* Describes one field of a record */
struct field_desc {
char *name;
int length;
int type;
};

#define FIELD_PROMPT "%s (%d): "

struct record {
size_t count;
struct field_desc *desc;
char **entries;
};

struct field_desc movies_desc[] = {
{ "id", 13, NOT_NULL | NUMERIC },
{ "title", 50, NOT_NULL },
{ "genre", 15, NOT_NULL },
{ "length", 3, NOT_NULL | NUMERIC },
{ "description", 65535, MULTI_LINE },
{ "owner", 10, NOT_NULL },
{ "available", 1, NOT_NULL | NUMERIC },
{ "customer", 30, 0 } };

#define MOVIES_LENGTH (sizeof(movies_desc)/sizeof(movies_desc[0]))

char *readl(size_t length, int multiline, char stop)
{
const size_t bufsize = 32;
int c, lastc;
size_t index;
size_t size;
char *str, *tmp;

size = 0;
str = NULL;

if (multiline)
lastc = '\n';
else
lastc = 0;

index = 0;
while ((c = getchar()) != EOF && index < length) {
if (index + 1 >= size) {
size += bufsize;
if (size > length + 1)
size = length + 1;

tmp = realloc(str, size);
if (tmp == NULL) {
if (str)
free(str);
return NULL;
}
str = tmp;
}

/* Will only be true if multiline */
if (c == stop && lastc == '\n') {
if (stop == '\n')
break;
if ((c = getchar()) == '\n' || c == EOF)
break;
else {
ungetc(c, stdin);
c = stop;
}
}
if (c == '\n' && !multiline)
break;

assert(index + 1 < size);
str[index++] = c;
lastc = c;
}
if (c == EOF && index == 0)
return NULL;

assert(str != NULL);
assert(index < size);
str[index] = '\0';

/* Remove trailing '\n's (multiline only) */
if (index != 0 && lastc == '\n')
str[index - 1] = '\0';

/* Remove remaining characters on the line. */
while(c != '\n' && c != EOF)
c = getchar();

return str;
}

/* This function assumes sticky eof. That means,
* if an EOF is encountered, it will be read again
* from getchar() at the next call to this function. */
char *read_multiline(size_t length)
{
return readl(length, 1, '\n');
}

/* Reads one line of max length and discards additional
* characters on the line. Intended for interactive use */
char *read_line(size_t length)
{
return readl(length, 0, 0);
}

int isnumeric(const char *str)
{
if (!str)
return 0;
while (*str) {
if (!isdigit(*str) && *str != '\n')
return 0;
str++;
}
return 1;
}

static int validate_entry(const char *entry, struct field_desc desc)
{
if ((desc.type & NUMERIC) && !isnumeric(entry)) {
fprintf(stderr, "Error: Value must be numeric\n");
return -1;
}
if ((desc.type & NOT_NULL) && entry[0] == '\0') {
fprintf(stderr, "Error: Value must not be null\n");
return -1;
}

return 0;
}

static void field_prompt(struct field_desc desc)
{
printf(FIELD_PROMPT, desc.name, desc.length);
fflush(stdout);
}

static int get_field(char **entry, struct field_desc desc)
{
if (desc.type & MULTI_LINE)
*entry = read_multiline(desc.length);
else
*entry = read_line(desc.length);

if (*entry == NULL)
return EOF;

return 0;
}

int set_record_type(struct record *r, struct field_desc *desc, size_t
length)
{
size_t i;
r->count = length;
r->desc = desc;
r->entries = malloc(length * sizeof(char *));
if (r->entries == NULL)
return -1;
/* Init all data to NULL */
for (i = 0; i < length; i++)
r->entries[i] = NULL;
return 0;
}

/* Fills record with input from user */
int fill_record(struct record r)
{
size_t i;
for (i = 0; i < r.count; i++) {

field_prompt(r.desc[i]);
if (get_field(&r.entries[i], r.desc[i]) == EOF)
goto atEOF;

while (validate_entry(r.entries[i], r.desc[i]) != 0) {
free(r.entries[i]);
field_prompt(r.desc[i]);
if (get_field(&r.entries[i], r.desc[i]) == EOF)
goto atEOF;
}
}

return 0;

atEOF:
while (i--) {
free(r.entries[i]);
r.entries[i] = NULL;
}
return EOF;
}

void print_record(struct record r)
{
size_t i;
for (i = 0; i < r.count; i++) {
printf("%s:\"%s\"\n", r.desc[i].name, r.entries[i]);
}
}

void free_record(struct record r)
{
size_t i;

for (i = 0; i < r.count; i++) {
if (r.entries[i])
free(r.entries[i]);
}
free(r.entries);
}

int main(void)
{
struct record movies_record;

set_record_type(&movies_record, movies_desc, MOVIES_LENGTH);

fill_record(movies_record);

print_record(movies_record);

free_record(movies_record);

return EXIT_SUCCESS;
}
Jun 22 '06
53 3104
(On using longjmp in place of some form of built-in exception
handling...)

In article <11**********************@75g2000cwc.googlegroups. com>
goose <ru**@webmail.co.zawrote:
>Fair enough; longjmp cannot call destructors automatically like
C++/Java/etc exceptions can but it *can* unwind the stack.
Well, maybe. "Can" is sometimes architecture-dependent, and
"does" is not actually true on many real implementations.
>The jmp_buf initialised with setjmp only gets invalidated when the
function scope where setjmp is called returns[1]. I'd assume that,
with language support for destructors (variables going out of
scope automatically get a certain function called), exceptions
can be implemented with longjmp.
It is more complicated than that: in languages like Lisp (with
unwind-protect) and C++ (with destructors), you *must* "unwind
the stack", and transfer control (or act "as if" you had) to
those points at which runtime action is to be taken.

There are a lot of ways to implement this, but they all have some
costs, either in runtime for all functions, or in executable and/or
runtime-image space, or both. Since C lacks the requirement for
"one frame at a time unwinding", C implementations can save the
space and/or time -- and many do.
>How is this different from exceptions? I might be way off here, but I
always assumed that exceptions could only unwind the stack, not magically
unlock or call free (or delete).
In a language that supports exceptions and has destructors (like
C++), the "unwind sequence" in longjmp() looks something like
this:

void longjmp(jmp_buf buf, int value) {
struct frame *fp = some_sort_of_magic();
struct frame *target_frame = more_magic(buf);

if (value == 0)
value = 1;
while (fp != target_frame) {
if (fp == NULL)
panic("bad call to longjmp");
if (fp->flags & UNWIND_ACTION)
(*fp->unwind)(fp);
fp = fp->prev_frame;
}
yet_more_magic(buf, value); /* resume at setjmp, returning "value" */
}

In C, it often looks instead like this:

void longjmp(jmp_buf buf, int value) {
if (value == 0)
value = 1;
magic(buf, value); /* resume at setjmp, returning "value" */
}

Note that the C++ "longjmp" is much heavier-weight, and requires
every function-call to set up fp->flags and (if the flags include
"take action on unwind") fp->unwind.

In both cases, the final magic sets the frame and/or stack pointers.

On some architectures, there is no separate "frame pointer", and
each subroutine can make up its own "virtual frame". If this
is carried through to the C++-style longjmp, the longjmp() code
becomes substantially more convoluted, as the last line of the
loop becomes:

while (fp != target_frame) {
...
fp = reconstruct_previous_frame(fp);
}

where "reconstruct previous frame" is arbitrarily complicated (it
may have to look in a table to correlate a "program counter" value
with a "function address range", then use that to find a "virtual
frame pointer offset" given a saved-stack-pointer; this is how it
works on MIPS processors for instance).

The shorter, C-specific "longjmp" remains unchanged, even on the
MIPS. (The jmp_buf can simply record the stack pointer and PC.
Going to the target PC automatically restores the virtual frame
pointer. Or, usage of setjmp() may force an actual frame pointer,
just like using a C99 VLA. In this case the "now-real" fp register
can be stored in the jmp_buf, along with the always-real sp. Note
that in either case, longjmp()ing wipes out VLAs allocated after
the call to setjmp().)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: forget about it http://web.torek.net/torek/index.html
Reading email is like searching for food in the garbage, thanks to spammers.
Jul 28 '06 #51
Richard Heathfield wrote:
On the whole, C is still written by hackers, and it shows.
you say that like it's a bad thing...

you'll love this code I encountered earlier:-

void f ()
{
/* i is static and initialised elsewhere */
while (i < max)
{
process_item (i++);
break;
}
}

--
"The Real Programmer wants a "you asked for it, you got it"
text editor--complicated, cryptic, powerful, unforgiving,
dangerous. TECO, to be precise."

Jul 28 '06 #52
Nick Keighley said:
Richard Heathfield wrote:
>On the whole, C is still written by hackers, and it shows.

you say that like it's a bad thing...
Um. Yes, no, maybe. Neither, really. Just an observation.

I suppose the thing is this - that C /can/ be written "properly", i.e. how I
would write it (modulo bugs), but to do so takes time and effort. Having
said that, it can also be written "improperly" - hack it, get it working,
move on to the next brilliant idea. C lets you do that. It doesn't get in
the way, doesn't make value judgements, doesn't berate you for hacking out
something that does the job. With my comp.lang.c hat on, or when writing
production code for other people (or indeed for myself), I write "proper"
C. But when nobody's looking (particularly me) and it's 3am and I'm on a
roll...
>
you'll love this code I encountered earlier:-

void f ()
{
/* i is static and initialised elsewhere */
while (i < max)
{
process_item (i++);
break;
}
Er... :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Jul 28 '06 #53
in 688813 20060728 131039 Richard Heathfield <in*****@invalid.invalidwrote:
>I suppose the thing is this - that C /can/ be written "properly", i.e. how I
would write it (modulo bugs), but to do so takes time and effort. Having
said that, it can also be written "improperly" - hack it, get it working,
move on to the next brilliant idea. C lets you do that. It doesn't get in
the way, doesn't make value judgements, doesn't berate you for hacking out
something that does the job. With my comp.lang.c hat on, or when writing
production code for other people (or indeed for myself), I write "proper"
C. But when nobody's looking (particularly me) and it's 3am and I'm on a
roll...
All true, of course, but I don't see how this makes C different from any other language.
Jul 28 '06 #54

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

52
by: Tony Marston | last post by:
Several months ago I started a thread with the title "What is/is not considered to be good OO programming" which started a long and interesting discussion. I have condensed the arguments into a...
220
by: Brandon J. Van Every | last post by:
What's better about Ruby than Python? I'm sure there's something. What is it? This is not a troll. I'm language shopping and I want people's answers. I don't know beans about Ruby or have...
92
by: Reed L. O'Brien | last post by:
I see rotor was removed for 2.4 and the docs say use an AES module provided separately... Is there a standard module that works alike or an AES module that works alike but with better encryption?...
137
by: Philippe C. Martin | last post by:
I apologize in advance for launching this post but I might get enlightment somehow (PS: I am _very_ agnostic ;-). - 1) I do not consider my intelligence/education above average - 2) I am very...
125
by: Sarah Tanembaum | last post by:
Beside its an opensource and supported by community, what's the fundamental differences between PostgreSQL and those high-price commercial database (and some are bloated such as Oracle) from...
121
by: typingcat | last post by:
First of all, I'm an Asian and I need to input Japanese, Korean and so on. I've tried many PHP IDEs today, but almost non of them supported Unicode (UTF-8) file. I've found that the only Unicode...
46
by: Keith K | last post by:
Having developed with VB since 1992, I am now VERY interested in C#. I've written several applications with C# and I do enjoy the language. What C# Needs: There are a few things that I do...
13
by: Jason Huang | last post by:
Hi, Would someone explain the following coding more detail for me? What's the ( ) for? CurrentText = (TextBox)e.Item.Cells.Controls; Thanks. Jason
669
by: Xah Lee | last post by:
in March, i posted a essay “What is Expressiveness in a Computer Language”, archived at: http://xahlee.org/perl-python/what_is_expresiveness.html I was informed then that there is a academic...
98
by: tjb | last post by:
I often see code like this: /// <summary> /// Removes a node. /// </summary> /// <param name="node">The node to remove.</param> public void RemoveNode(Node node) { <...> }
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
0
by: ArrayDB | last post by:
The error message I've encountered is; ERROR:root:Error generating model response: exception: access violation writing 0x0000000000005140, which seems to be indicative of an access violation...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.