Page 1 of 2

Completely stumped

Posted: Tue Jul 29, 2003 1:18 pm
by Kon-Tiki
I was making a program to figure a few things out (concept of the program came from my brother), but I'm already stuck in the beginning. I'm trying to use functions, but can't call them in the main part.
This's the source:

Code: Select all

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

void condition(char seat, char pos, char object) {
  printf("Toilet seat is %c and you are %c. There is %c on the seat. \n", seat, pos, object);
}

void input(char seat, char pos, char object) {
  scanf("What do you want to do? \n", &seat, &pos, &object);
}

int main()
{
char seat[10];
char pos[10];
char object [10];

  call(input);
  call(condition);

return 0;
}
This program should ask what the user wants to do (like putting the toilet seat up, peeing, sitting, shitting, etc.) and give the result of the actions in one line. I think it's best to use functions for this, because otherwise I have to retype everything to an infinite amount.

-Kon-Tiki-

Re:Completely stumped

Posted: Tue Jul 29, 2003 2:47 pm
by ark
You don't call functions like that, and I'm not sure but I don't believe that's how scanf works either...although don't quote me on that (don't really use it very much).

You don't need both iostream.h and stdio.h usually. There are a number of problems with this program. Here's a version that should work (I tested it with Visual C++):

Code: Select all

// #include <iostream.h> -- don't need this
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

// these parameters need to be character pointers
void condition(char* seat, char* pos, char* object)
{
    // %c prints out 1 character -- you want %s, which
    // prints out an entire string
    printf("Toilet seat is %s and you are %s. "
           "There is %s on the seat. \n", seat, pos, object);
}

void input(char* seat, char* pos, char* object)
{
    // this works on Visual C++ 6.0
    printf("What do you want to do?\n");
    
    // don't think this is especially good practice
    // (it's not very fault-tolerant), but it works
    // if you do the input right
    scanf("%s", seat);
    scanf("%s", pos);
    scanf("%s", object);
}

int main()
{
    char seat[10];
    char pos[10];
    char object [10];

    // the seat, pos, and object here are not the
    // same seat, pos, and object that are in the
    // input function
    input(seat, pos, object);
    // same goes for the condition function
    condition(seat, pos, object);

    return 0;
}

Re:Completely stumped

Posted: Tue Jul 29, 2003 3:05 pm
by Kon-Tiki
So what I need to do is change the chars to strings and that I forgot that the function's... well... a function.

Man, do I need alot of practice before those things're obvious.

Another question has arisen: why does everybody place those stars after char?

-Kon-Tiki-

Re:Completely stumped

Posted: Tue Jul 29, 2003 3:36 pm
by Tim
They're not just for decoration :).

A * in a type name signifies that the variable is a pointer. So a char* is a pointer to a char. Actually, char* is a sort of special case. A char* points to the first character of a string; the rest of the string comes after that first character, and the string is terminated with a nul (zero) character.

You really do need to get a book on C. Please tell me you're going to do this! It's painful watching you learn via a web message board.

Re:Completely stumped

Posted: Tue Jul 29, 2003 4:38 pm
by Kon-Tiki
Ok, that works now, but the output gives weird ascii-codes. This's with converting and reconverting, IIRC, but dunno how to go against it. Oh well, I'll follow Tim's advice and start reading from the moment I know that I won't waste my time on the book I have. Maybe I'll be able to figure it out then.

-Kon-Tiki-

Re:Completely stumped

Posted: Tue Jul 29, 2003 6:20 pm
by Schol-R-LEA
I have to concur with Tim. It is clear from your posting that already know VB 6 (and not VB .NET, which changes some things you tried to use), and it is understandable that you'd try to apply what you learned from VB as you try to learn C. However, that languages are quite different from each other, moreso in fact than it would seem at first sight. It goes well beyond just the curly braces .

The goof news is that C is a much smaller and simpler language than VB is; the bad news is, it is considerably harder and more demanding of careful coding and thoughtful design (at least at first; as you dig deeper into each, the irregularities and limitations of VB quickly bog you down, just at about the point where C is really taking flight). It may take a while to unlearn VB before you can really learn C (but at least should be easier than unlearning Applesoft BASIC was for me). A few of the differences between C and VB 6:
  • C does not have a separate concept of 'procedures' as opposed to functions; all subroutines in C can return a value (unless they are defined as type [tt]void[/tt], as explained below), and most do. The function definition and call syntaxes are always the same regardless of how the function is used. (You should note that VB.NET has gone to this approach as well, eliminating the special-case subroutine syntax which caused so many headaches).
  • C allows you to compile parts of a program seperately; that is, you can call functions from outside of the current source file, even without the source code for the function you're calling. In order to do this, you need to use a function prototype that gives the name of the function and lists what kind of arguments it takes.
  • Header files in C are lists of functions prototypes and data structure declarations which can be automagically inserted in to a source file with the [tt]#include[/tt] directive. Headers which are in the standard include path are marked with angle brackets around their names; headers which are in the local path are marked with double quotes.
  • Standard C has a large number of built-in operators
    • the arithmetic operators [tt]+[/tt], [tt]-[/tt], [tt]*[/tt], [tt]/[/tt], [tt]%[/tt] (modulo, sort of like a remainder), [tt]++[/tt] (increment), and [tt]--[/tt] (decrement);
    • the logical operators [tt]![/tt] (not), [tt]<[/tt], [tt]>[/tt], [tt]<=[/tt], [tt]=>[/tt], [tt]&&[/tt] (and), [tt]||[/tt] (or)
    • the bitwise operators [tt]~[/tt] (not), [tt]&[/tt] (and), [tt]|[/tt] (or), [tt]^[/tt] (exclusive or), [tt]<<[/tt] (shift left) and [tt]>>[/tt] (shift right) (see reply #3 in this thread for an explanation of what the bitwise operators do)
    • The assignment operator [tt]=[/tt];
    • the accumulator operators [tt]+=[/tt], [tt]-=[/tt], [tt]*=[/tt], [tt]/=[/tt], etc., one for each arithmetic, logical and bitwise operator;
    • the equivalence operator [tt]==[/tt];
    • the pointer operators, [tt]&[/tt], [tt]*[/tt];
    • the structure member operators [tt].[/tt] and [tt]->[/tt];
    • the seperator operator [tt],[/tt] (comma), used primarily in [tt]for[/tt] expressions;
    • the conditional operator [tt]?[/tt]..[tt]:[/tt] (similar to IIF() in VB, but less dangerous);
    but relatively few expressions ([tt]if[/tt], [tt]for[/tt], [tt]while[/tt], [tt]do[/tt]..[tt]while[/tt], [tt]switch[/tt], [tt]sizeof[/tt], [tt]break[/tt], [tt]continue[/tt] and [tt]goto[/tt]).
  • All other operations are actually provided by library functions: printf(), scanf(), fscanf(), putc(), pow(), abs(), and the other common functions are all part of the standard library, not part of the core language itself. You can even replace them with you own versions, if you want. Only those functions which a program actually uses get linked into the final program - there is no large runtime library needed as in older versions of VB.

Re:Completely stumped

Posted: Tue Jul 29, 2003 6:21 pm
by Schol-R-LEA
To continue:
  • Standard C has only nine built in types: [tt]char[/tt], [tt]short int[/tt] (or just [tt]short[/tt]), [tt]int[/tt], [tt]long int[/tt] (or just [tt]long[/tt]), [tt]float[/tt], [tt]double[/tt], [tt]long double[/tt], [tt]bool[/tt], and [tt]void[/tt]. The integer types ([tt]short[/tt], [tt]int[/tt], and [tt]long[/tt]) and [tt]char[/tt] can also take the modifiers [tt]signed[/tt] or [tt]unsigned[/tt], to indicate whther they should have negative numbers or not. Type [tt]void[/tt] is a special type indicating that a function has no return value.
  • Any of the basic types can be used to declare an array. An array in C is simply a block of memory [tt]n * sizeof(type)[/tt], where n is the number of elements in the array; multidimensional arrays simply multiply the array subscripts automatically. Array subscripting always begins with 0 (that is, for array [tt]int foo[10][/tt], the elements would be numbered 0, 1, ... 8, 9). Using just the name of the array gives you the first element in the array (so that [tt]foo == foo[[0]][/tt]). C does no bounds checking on arrays, so it is possible (and altegether too easy) to 'walk off the end' of an array and possibly mangle other data.
  • Any basic type also has a pointer type. A pointer is a special kind of variable that holds the value of a memory address; so, if you have

    Code: Select all

    int i;
    int *p;
    
    i = 42;
    p = &i;  // the ampersand means 'return this variables address' 
    


    and [tt]i[/tt] is at memory address 0x02F2E, the [tt]p == 0x02F2E[/tt], and [tt]*p == 42[/tt]. The ampersand is called the reference operator, and the asterisk is called the dereference operator or access operator. This is a very powerful tool, but also the source of many difficult to find bugs.
  • There is no built-in string type in C; by convention, C uses zero-delimited char arrays (that is, an array of char as long or longer than the string, with the end of the actual string marked by the ASCII null character, [tt]\00[/tt], and manipulated with char pointers. This is one of the easier areas in C to get confused with, so don't try to grasp it all at once.
  • More complex data structures can be built up using [tt]struct[/tt]s, which are similar to User Defined Types in VB but are much more heavily used. It is possible to build data types for nearly any needed data structure using structs.
  • C does not have any standard collection types, though it is fairly easy to implement them using structs. C++ has several different types of collections, but they are library classes, not part of the core language.
  • C doe not have a variant type; all C variables are typed. It is possible to get some of the effect of variants using void pointers, but it is much more complicated than the equivalent in VB.
  • It is possible to define new data types using the typedef command; types defined in this way can, for the most part, be used jsut the same as any other type in C.
  • In C, dynamic memory management is done explicitly by the programmer; any heap memory that is needed beyond what is declared at compile time has to allocated using malloc() or similar standard functions, and then released with free() when it is finished with. Like pointers (which are used to work with the allocated memory), this is a very powerful tool but a very tricky one to use correctly.
If what I've just explained to you doesn't make sense to you, then drop everything and get a book on C; until you have grasped at least three quarters of these ideas, you'll be wandering in the dark as far as C is concerned.

Most, but not all, of this also applies to C++, which is a great deal more complicated a language and not at all for beginners.

<crank>
As usual, I'd recommend taking a look at Scheme or Python before going to C; they are much easier to learn and use, and are sufficiently different from both C and Visual Basic that they should break you of any ingrained habits, allowing you to approach C with the classic Zen "beginner's mind" ;). If you can get Assembly Language Step by Step, then learning assembly first wouldn't be a bad idea, either.
</crank>

Comments and corrections are welcome, as always.

Re:Completely stumped

Posted: Tue Jul 29, 2003 7:25 pm
by Schol-R-LEA
Kon-Tiki wrote: Ok, that works now, but the output gives weird ascii-codes. This's with converting and reconverting, IIRC, but dunno how to go against it. Oh well, I'll follow Tim's advice and start reading from the moment I know that I won't waste my time on the book I have. Maybe I'll be able to figure it out then.
The specific problem is in the code Joel wrote for calling the functions:

Code: Select all

    input(seat, pos, object);
    // same goes for the condition function
    condition(seat, pos, object);
This should be:

Code: Select all

    input(&seat, &pos, &object);
    // same goes for the condition function
    condition(&seat, &pos, &object);
The reason for this is that in main(), seat[], pos[], and object[] are defined as 10 element arrays; since an array is not a pointer, per se, but an identifier for a block of memory, you need to use & to get the addresses of the arrays. Otherwise, the arguments passed to input() and condition() will be the ASCII values of the first four elements of each array (assuming 32-bit addressing), not the pointers to the arrays as expected.

This is a common mistake, and no real fault of Joel's; this is one of the hardest parts of C to understand, especially if you don't know the underlying assembly language, and even then it is an easy mistake to make (since it is more typical for c-strings to be handled through pointers anway). HTH, but if you don't get it, don't stress over it too much just yet.

BTW, this also will help understand scanf(): it takes a format string, followed by an arbitrary number of pointers (it can do this because of the particular way that C pushes arguments onto the stack; for now, don't worry about how it works too much yet). It reads the format string, which tells it the number and type of arguments; it then uses the pointers to put the scanned values into the variables which they point to. As you may have noticed, this is a rather error-prone approach, but used carefully can be quite effective.

Re:Completely stumped

Posted: Tue Jul 29, 2003 8:07 pm
by ark
in C++ you can write the code exactly as I wrote it and it works fine. As I said, I tested it in Visual C++ prior to copying and pasting it directly to the board. Putting the address-of operator in front of the array names prevents the program from compiling.

Code: Select all

char seat[10];

// this is valid
char* p1 = seat;
// so is this
char* p2 = &seat[0];

// this is not
char* p3 = &seat;

// although I'm not really sure why it wouldn't be
// since the following expression is true

reinterpret_cast<void*>(seat) ==
reinterpret_cast<void*>(&seat);

// Visual C++ considers &seat to be an expression
// of type char (*)[10] -- which it considers distinct
// from char*

Re:Completely stumped

Posted: Tue Jul 29, 2003 8:14 pm
by ark
incidentally, the union in C should allow you to have something like the variant in VB (and I believe that is how variants are actually implemented)

Re:Completely stumped

Posted: Tue Jul 29, 2003 8:29 pm
by ark
what kind of output are you getting exactly Kon-Tiki? If you can, paste it on the board...if you're running Windows 2000 or XP you should be able to copy the output directly from the console window. If you've got Windows 9x, you should be able to copy the output like this (from the Command Prompt):

[tt]yourprogram.exe > output.txt[/tt]

If you do that, then all of the output from your program will be written to the file output.txt, and you can then copy and paste it. You'll have to trust that your program is running, though, because you won't see your "What do you want to do?" prompt. Of course, you should also let us know what exactly you typed. If one of your strings is greater than 9 characters, it will start overwriting memory, because as Schol-R-Lea mentioned, C arrays are not bounds-checked (but that bit about [tt]foo == foo[[0]][/tt] is not correct).

Re:Completely stumped

Posted: Tue Jul 29, 2003 11:12 pm
by Schol-R-LEA
Joel wrote: in C++ you can write the code exactly as I wrote it and it works fine. As I said, I tested it in Visual C++ prior to copying and pasting it directly to the board. Putting the address-of operator in front of the array names prevents the program from compiling.
Interesting. You were right; I tested your code under Dev-C++, and it worked as written, while adding the address-of operator does indeed cause a compile error. I'll have to check my references and see what I've misunderstood. Thank you for pointing this out.

Re:Completely stumped

Posted: Wed Jul 30, 2003 12:43 am
by beyond infinity lazy
that's the c++ reference operator which saves the explicit passing of pointers like you have to do in c.

Just rename the file from foo.c to foo.cpp and the compiler will treat it as c++ program. As the usual c includes are valid in c++, you won't encounter problems with that.

Re:Completely stumped

Posted: Wed Jul 30, 2003 1:40 am
by Schol-R-LEA
Actually, I checked my copy of Practical C Programming (I don't have a copy of K&R right now - it's one of those books which seems to walk away on its own when you aren't looking - or I would have refered to it), which states:
C provides a shorthand for dealing with arrays. Rather than writing:

[tt]array_ptr = &array[[0]];[/tt]

we can write

[tt]array_ptr = array;[/tt]

C blurs the distinction between pointers and arrays by treating them in the same manner in many cases. Here we use the variable [tt]array[/tt] as a pointer, and C automatically does the necessary conversion.
So apparently, while I was right about how array identifiers differ from pointers to arrays (I think), I had misunderstood the actual behavior in code. I'll chalk it up to a learning experience. Again, Joel, thank you for pointing my mistake out.

Oh, and out of curiosity I checked whether gcc still supports the old "reverse subscripting" trick - things like 2[foo + i] instead of foo[2 + i] - and it worked without a burp. Not particularly relevant, but interesting.

Unfortunately, this means that Kon-Tiki's problems aren't from the language differences - it would behave the same under C or C++.

Re:Completely stumped

Posted: Wed Jul 30, 2003 4:41 am
by distantvoices
lay it in chains and have the bibliothekar (UGH---ieeeek) watch for it. maybe it stays longer with you then. and take care of not to enter the l-room without lots of twine.

may the rincewind be with you

ad reverse subscripting: I wonder and learn. they didn't tell me in that c course years ago that this exixts. I wouldn't have considered such things like 2[foo+i] correct before.