Copyright 2004 by M. Uli Kusterer Tue, 30 Dec 1969 07:58:58 GMT Comments on article book9 at Zathras.de http://www.zathras.de/angelweb/book9.htm book9 Comments witness_dot_of_dot_teachtext_at_gmx_dot_net (M. Uli Kusterer) witness_dot_of_dot_teachtext_at_gmx_dot_net (M. Uli Kusterer) en-us Comment 15 by phill http://www.masters-of-the-void.com/book9.htm#comment15 http://www.masters-of-the-void.com/book9.htm#comment15 I get a error when I try to build the code that says "expected expression before 'void'"

here is my code

#include <stdio.h> // declares printf(), scanf(), and fpurge()
#include <stdbool.h> //declares bool
#include <string.h> // declares strcmp()
#include <stdlib.h> // We'll need that later for malloc() and realloc()

// Data structure
struct CDDatabaseEntry
{
char artist[40];
char composer[40];
char albumName[40];
int trackCount;
bool isSampler;
};

//Global variables:
int gNumDatabaseEntries = 0;
struct CDDatabaseEntry* gDatabase = NULL;

// Main event loop:
//Fetches user input and calls our DoXXX functions to do the work.
int main()
{
bool keepRunning = true;
char userInput[11];

while ( keepRunning == true )
{
printf( "Type NEW, LIST, or QUIT:\n" );
scanf( "%10s", userInput );
fpurge( stdin );

if ( strcmp( userInput, "NEW" ) == 0 )



void DoNewCommand()
{
char yesOrNo;

// First, create a new array element (or a new array if we don't have one yet):
if( gDatabase == NULL )
{
gDatabase = malloc( sizeof(struct CDDatabaseEntry) ); // size of 1 element.
if( gDatabase == NULL ) // Still NULL? malloc() must have returned NULL due to error.
{
printf( "ERROR: Couldn't create a new entry!\n" );
return;
}
}
else
{
struct CDDatabaseEntry* newPtr = NULL;
newPtr = realloc( gDatabase, (gNumDatabaseEntries +1) *sizeof(struct CDDatabaseEntry) );
if( newPtr == NULL ) // Error! Out of memory?
{
// We just keep the old pointer in gDatabase.
printf( "ERROR: Couldn't create a new entry!\n" );
return;
}
// newPtr is our new ptr, gDatabase is no longer valid!
gDatabase = newPtr; // Remember newPtr in gDatabase.
}

// Make sure we remember we have one more entry:
gNumDatabaseEntries += 1;

// Now replace the garbage data in the new, last entry with data the user entered:
printf( "Artist Name: " );
scanf( "%39s", gDatabase[ gNumDatabaseEntries -1 ].artist );
fpurge( stdin );

printf( "Composer: " );
scanf( "%39s", gDatabase[ gNumDatabaseEntries -1 ].composer );
fpurge( stdin );

printf( "Album Name: " );
scanf( "%39s", gDatabase[ gNumDatabaseEntries -1 ].albumName );
fpurge( stdin );

printf( "No. of Tracks: " );
scanf( "%d", &gDatabase[ gNumDatabaseEntries -1 ].trackCount );
fpurge( stdin );

printf( "Sampler? (y/n): " );
scanf( "%c", &yesOrNo );
fpurge( stdin );

gDatabase[ gNumDatabaseEntries -1 ].isSampler = (yesOrNo == 'y' || yesOrNo == 'Y');
}
else if( strcmp( userInput, "LIST" ) == 0)
void DoListCommand()
{
int x = 0;

if( gDatabase == NULL )
{
printf("There are no CDs in the database.\n");
return;
}

while( x < gNumDatabaseEntries )
{
printf( "Artist Name: %s\n", gDatabase[ x ].artist );
printf( "Composer: %s\n", gDatabase[ x ].composer );
printf( "Album Name: %s\n", gDatabase[ x ].albumName );
printf( "No. of Tracks: %d\n", gDatabase[ x ].trackCount );
if( gDatabase[ x ].isSampler )
printf( "\tThis CD is a sampler.\n" );
printf( "\n" ); // Add an empty line for space to the next CD.

x += 1;
}
}
else if( strcmp( userInput, "QUIT" ) ==0)
keepRunning = false; // we're finished
else
printf("ERROR: Unknown command \"%s\"!\n\n", userInput );
}

void DoCleanUp( void )
{
if( gDatabase != NULL ) // We have allocated memory?
{
free( gDatabase );
gDatabase = NULL; // Not really necessary, but good style.
gNumDatabaseEntries = 0;
}
}
Comment 14 by phill http://www.masters-of-the-void.com/book9.htm#comment14 http://www.masters-of-the-void.com/book9.htm#comment14 I get a error when I try to build the code that says "expected expression before 'void'"

here is my code

#include <stdio.h> // declares printf(), scanf(), and fpurge()
#include <stdbool.h> //declares bool
#include <string.h> // declares strcmp()
#include <stdlib.h> // We'll need that later for malloc() and realloc()

// Data structure
struct CDDatabaseEntry
{
char artist[40];
char composer[40];
char albumName[40];
int trackCount;
bool isSampler;
};

//Global variables:
int gNumDatabaseEntries = 0;
struct CDDatabaseEntry* gDatabase = NULL;

// Main event loop:
//Fetches user input and calls our DoXXX functions to do the work.
int main()
{
bool keepRunning = true;
char userInput[11];

while ( keepRunning == true )
{
printf( "Type NEW, LIST, or QUIT:\n" );
scanf( "%10s", userInput );
fpurge( stdin );

if ( strcmp( userInput, "NEW" ) == 0 )



void DoNewCommand()
{
char yesOrNo;

// First, create a new array element (or a new array if we don't have one yet):
if( gDatabase == NULL )
{
gDatabase = malloc( sizeof(struct CDDatabaseEntry) ); // size of 1 element.
if( gDatabase == NULL ) // Still NULL? malloc() must have returned NULL due to error.
{
printf( "ERROR: Couldn't create a new entry!\n" );
return;
}
}
else
{
struct CDDatabaseEntry* newPtr = NULL;
newPtr = realloc( gDatabase, (gNumDatabaseEntries +1) *sizeof(struct CDDatabaseEntry) );
if( newPtr == NULL ) // Error! Out of memory?
{
// We just keep the old pointer in gDatabase.
printf( "ERROR: Couldn't create a new entry!\n" );
return;
}
// newPtr is our new ptr, gDatabase is no longer valid!
gDatabase = newPtr; // Remember newPtr in gDatabase.
}

// Make sure we remember we have one more entry:
gNumDatabaseEntries += 1;

// Now replace the garbage data in the new, last entry with data the user entered:
printf( "Artist Name: " );
scanf( "%39s", gDatabase[ gNumDatabaseEntries -1 ].artist );
fpurge( stdin );

printf( "Composer: " );
scanf( "%39s", gDatabase[ gNumDatabaseEntries -1 ].composer );
fpurge( stdin );

printf( "Album Name: " );
scanf( "%39s", gDatabase[ gNumDatabaseEntries -1 ].albumName );
fpurge( stdin );

printf( "No. of Tracks: " );
scanf( "%d", &gDatabase[ gNumDatabaseEntries -1 ].trackCount );
fpurge( stdin );

printf( "Sampler? (y/n): " );
scanf( "%c", &yesOrNo );
fpurge( stdin );

gDatabase[ gNumDatabaseEntries -1 ].isSampler = (yesOrNo == 'y' || yesOrNo == 'Y');
}
else if( strcmp( userInput, "LIST" ) == 0)
void DoListCommand()
{
int x = 0;

if( gDatabase == NULL )
{
printf("There are no CDs in the database.\n");
return;
}

while( x < gNumDatabaseEntries )
{
printf( "Artist Name: %s\n", gDatabase[ x ].artist );
printf( "Composer: %s\n", gDatabase[ x ].composer );
printf( "Album Name: %s\n", gDatabase[ x ].albumName );
printf( "No. of Tracks: %d\n", gDatabase[ x ].trackCount );
if( gDatabase[ x ].isSampler )
printf( "\tThis CD is a sampler.\n" );
printf( "\n" ); // Add an empty line for space to the next CD.

x += 1;
}
}
else if( strcmp( userInput, "QUIT" ) ==0)
keepRunning = false; // we're finished
else
printf("ERROR: Unknown command \"%s\"!\n\n", userInput );
}

void DoCleanUp( void )
{
if( gDatabase != NULL ) // We have allocated memory?
{
free( gDatabase );
gDatabase = NULL; // Not really necessary, but good style.
gNumDatabaseEntries = 0;
}
}
Comment 13 by Someone http://www.masters-of-the-void.com/book9.htm#comment13 http://www.masters-of-the-void.com/book9.htm#comment13 Whenever I try to enter any text (ie after "Artist Name:") I get this
[Session started at 2010-03-21 09:04:39 -0700.]
GNU gdb 6.3.50-20050815 (Apple version gdb-967) (Tue Jul 14 02:11:58 UTC 2009)
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i386-apple-darwin".sharedlibrary apply-load-rules all
Attaching to process 31286.
Comment 12 by Uli Kusterer http://www.masters-of-the-void.com/book9.htm#comment12 http://www.masters-of-the-void.com/book9.htm#comment12 Uli Kusterer writes:
Martin, thank you, corrected. Sometimes the server eats backslashes because it's trying to be helpful and keep people from injecting code...
Comment 11 by Ardeshir Sepahsalar http://www.masters-of-the-void.com/book9.htm#comment11 http://www.masters-of-the-void.com/book9.htm#comment11 Ardeshir Sepahsalar writes:
Here is a DoNewCommand and a helper function to check pointers, with some improvements, it lets you create names of artists and albums with spaces in them using getchar() :

int PtrNotOk( void *check ) {

bool status = false;

if (check == NULL) {
printf("Error: Couldn't create entry!\n");
status = true;
return status;
} else {
return status;
}
}

void doNewCommand() {

printf("Ok, lets create a new entry in the database.\n");

char yesOrNo; // this is to check if the entry is Sampler or not.
int c = 0; // array counter, for getchar()
// first create a new array element (or a new array if we don't have one

if (gDB == NULL) {

gDB = malloc( sizeof(struct dbCD) ); // size of 1 database

if ( PtrNotOk(gDB) ) {
return;
}

} else {

struct dbCD* newPtr = NULL;

newPtr = realloc( gDB, (gNumDbEntries+1) * sizeof( struct dbCD ) );

if( PtrNotOk(newPtr) ) {
return;
}

// newPtr is our new ptr, gDB is no longer valid
gDB = newPtr;
}

// make sure we remember we added one more entry

gNumDbEntries += 1;


printf("Enter Artist Name: ");

while((gDB[gNumDbEntries-1].artist[c++] = getchar()) != '\n')
;
fpurge(stdin);
gDB[gNumDbEntries-1].artist[--c] = 0; c=0; // remove the new line


printf("Enter Composer: ");
while((gDB[gNumDbEntries-1].composer[c++] = getchar()) != '\n')
;
fpurge(stdin);
gDB[gNumDbEntries-1].composer[--c] = 0; c=0;

printf("Enter Album Name: ");
while((gDB[gNumDbEntries-1].albumName[c++] = getchar()) != '\n')
;
fpurge(stdin);
gDB[gNumDbEntries-1].albumName[--c] = 0; c=0;

printf("No. of Tracks: ");
scanf("%d", &gDB[ gNumDbEntries-1].tracks ); // get the address of the Int for scanf
fpurge(stdin);

printf("Sampler? (y/n) ");
scanf("%c", &yesOrNo );
fpurge(stdin);

gDB[ gNumDbEntries-1].isSampler = (yesOrNo == 'y' || yesOrNo == 'Y');


}
Comment 10 by Martin Baker http://www.masters-of-the-void.com/book9.htm#comment10 http://www.masters-of-the-void.com/book9.htm#comment10 Missing backslash in DoNewCommand code?

printf( "ERROR: Couldn't create a new entry!n" );
Comment 9 by John http://www.masters-of-the-void.com/book9.htm#comment9 http://www.masters-of-the-void.com/book9.htm#comment9 Hi,

First of all, thanks for writing these tutorials. I've never found other tutorials intuitive to follow, but this definitely helps!

I'm just confused about two points in this chapter:

1. Inside the function DoNewCommand() with this line in particular:

scanf( "%d", &gDatabase[ gNumDatabaseEntries -1 ].trackCount );

is the reason there's a "&" character for trackCount because it's still an integer inside the CDDatabase structure and not a pointer like the character arrays? I just assumed that since I made a pointer to the entire CDDatabase structure that you wouldn't need that "&" character so I guess I'm wrong?

2. My other question is somewhat related to the above, but it deals with the code in the DoListCommand() function and the following lines of code:

printf( "Artist Name: %s\n", gDatabase[ x ].artist );
printf( "Composer: %s\n", gDatabase[ x ].composer );
printf( "Album Name: %s\n", gDatabase[ x ].albumName );
printf( "No. of Tracks: %d\n", gDatabase[ x ].trackCount );

Why isn't there a "*" character in front of the pointers for the artist, compose, and albumName character arrays? I thought it would be written as follows:

printf( "Artist Name: %s\n", *gDatabase[ x ].artist );
printf( "Composer: %s\n", *gDatabase[ x ].composer );
printf( "Album Name: %s\n", *gDatabase[ x ].albumName );
printf( "No. of Tracks: %d\n", gDatabase[ x ].trackCount );

with trackCount not having a "*" in front since it's still a variable within the CDDatabase structure unlike the character arrays inside which are pointers themselves.
Comment 8 by Richard Howell http://www.masters-of-the-void.com/book9.htm#comment8 http://www.masters-of-the-void.com/book9.htm#comment8 I just just down the compiler and restarted it.
The program now works fine, lol.

????
Comment 7 by Richard Howell http://www.masters-of-the-void.com/book9.htm#comment7 http://www.masters-of-the-void.com/book9.htm#comment7 I think I copied the code word for word, and at first it worked fine. But now I get this error, and to be fair, I don't understand it at all.

Is there something wrong with one of the library files?

Internal error occurred while creating dependency graph: _registerUndoObject:: NSUndoManager 0x2016497a0 is in invalid state, must begin a group before registering undo
Comment 6 by tómppu http://www.masters-of-the-void.com/book9.htm#comment6 http://www.masters-of-the-void.com/book9.htm#comment6 Thanks for the great tutorials Uli, some parts have been really hard to comprehend but that problem can be solved by trying harder. Learning new things is never easy, but you have managed to simplify this one and most of all made it flow so its interesting and fun!

This chapter however has one obvious flaw in the sample code;
Artist name, composer or album name can't contain any spaces or at least they're not printed out in the LISTing. One would think that it doesn't matter what goes inside "%39s" since it waits for a string and gets one but apparently it does... Any way to correct this?

Thanks!
Comment 5 by Uli Kusterer http://www.masters-of-the-void.com/book9.htm#comment5 http://www.masters-of-the-void.com/book9.htm#comment5 Uli Kusterer writes:
Ryan, gsoli, I hope the new animations will make re-reading this tutorial much more pleasant and understandable than the old graphics with their forests of arrows. Let me know what you think!
Comment 4 by Uli Kusterer http://www.masters-of-the-void.com/book9.htm#comment4 http://www.masters-of-the-void.com/book9.htm#comment4 Uli Kusterer writes:
stijnschoor, it is definitely possible to do that: There are variants of the functions you already know that work on files instead of the screen. Google for information on the "C standard library", particularly the functions fprintf(), fscanf(), fopen(), fwrite(), fread(), fseek(), ftell() and fclose().
Comment 3 by gsoli http://www.masters-of-the-void.com/book9.htm#comment3 http://www.masters-of-the-void.com/book9.htm#comment3 Very cool! This tutorial clarifies a lot of things for me. I especially enjoyed the explanation on the stack and heap in memory. These last few pages have been a little heavy, so I will have to come back again to try to force these concepts into my stubborn brain. It has been fun. Thanks!
Comment 2 by Ryan Stonebraker http://www.masters-of-the-void.com/book9.htm#comment2 http://www.masters-of-the-void.com/book9.htm#comment2 Ryan Stonebraker writes:
These Last two lesson have been very confusing... but after reading them twice I somewhat get it...
Thanks for the tutorials though!!!
Comment 1 by stijnschoor http://www.masters-of-the-void.com/book9.htm#comment1 http://www.masters-of-the-void.com/book9.htm#comment1 Dear Uli

Thanks for the tutorials, they have been a great help to me.
I am also creating a database(not CD's) and your article have helped me alot. Thanks.
Maybe you can help me with a question about C, in my database program I want the user to edit the data. Is there a way of printing the data from a file(In my case the FILE pointer file) and let the user edit it? I was thinking about some sort of scanf function where there's already some text.

Thank you
Stijn