Menu

An introduction to C programming

Dan
2007-12-10
2012-09-26
  • Dan

    Dan - 2007-12-10

    I have no training in software development but i decided i would like to learn a bit about C/C++.

    I started off by getting Dev-C++ 4.9.9.2 and i'm working my way through the tutorial named like the subject of this post.

    I've run into trouble with the example under the topic heading Functions and Prototypes. There were a few little things wrong with the code and i assume (as with the previous examples) these are put in to assist the learning process by improving problem solving skills.

    I managed to get correct most of the problems but i still get one bug i cant understand and therefore cant correct.

    The code is supposed to ask if the user wants to continue (y/n) and proceed according to the response the problem is that every second time the user is prompted for a response the program doesnt wait for a keystroke and appears to automatically enter a 'new line' character.

    I have mucked around with the code a little in an attempt to expose the cause of my problem but i think it is still essentially the same as in the help files.

    This program is intended to run in a dos window.
    [CODE]

    include <cstdlib>

    include <iostream>

    include <ctime>

    using namespace std;

    void showone();
    void showtwo();
    void showthree();
    void showfour();
    void showfive();
    void showsix();
    void blines(int n);
    int randm(int n);
    int draw();
    char getresp();

    main()
    {
    int ans = getresp();
    while(ans == 1)
    {
    draw();
    ans = getresp();
    }
    blines(2);
    system("PAUSE");
    return EXIT_SUCCESS;
    }

    char getresp()
    {
    char res;
    printf("Throw y/n ?");
    scanf("%c",&res);
    printf("\nresponse is >%c<\n",res);
    if (res == 'y')return 1;
    else return 2;
    }

    int randm(int n)
    {
    srand((unsigned)time(NULL));
    int t = rand()%n + 1;
    return t;
    }

    int draw()
    {
    int r;
    r = randm(6);
    blines(2);
    if (r==1) showone();
    if (r==2) showtwo();
    if (r==3) showthree();
    if (r==4) showfour();
    if (r==5) showfive();
    if (r==6) showsix();
    blines(2);
    }

    void blines(int n)
    {
    int i;

    for(i=1 ; i&lt;=n ; ++i) printf(&quot;\n&quot;);
    

    }

    void showone()
    {
    printf("\n * \n");
    }

    void showtwo()
    {
    printf(" * \n\n");
    printf(" * \n");
    }

    void showthree()
    {
    printf(" * \n");
    printf(" * \n");
    printf(" *\n");
    }

    void showfour()
    {
    printf(" * \n\n");
    printf(" *
    \n");
    }

    void showfive()
    {
    printf(" * \n");
    printf(" * \n");
    printf(" *
    \n");
    }

    void showsix()
    {
    int i;
    for(i=1 ; i<=3 ; ++i) printf(" * * \n");
    }

    [/CODE]

    Any assistance would be appreciated

    :)

     
    • cpns

      cpns - 2007-12-11

      >> I found the tutorial under help in the program i mentioned (Dev-C++ 4.9.9.2)
      Unfortunately amonges all teh resources you might have chosen, that is amongst the worse. Ignore it completely. The mistakes are genuine mistakes, not 'features' designed to test you. If you want to learn C++ (and I would recommend it over C - From Bjarne Stroustrup's FAQ: http://www.research.att.com/~bs/bs_faq.html#prerequisite )

      The " PLEASE READ BEFORE POSTING A QUESTION" thread has some recommendations.

      >> [...]and i got the header info by following the menu path 'file' 'new'
      >> 'project' 'console app' in the same prog.
      When you do that, there is an option to select the language. If you select C rather than C++, you will get a more appropriate 'template' for C code. Be aware that these are intended as starter code, not a definitive "you must do it this way". You are free to delete all the template code and use your own.

      >> i thought this must be a good starting point
      Exactly the opposite.

      >> to be fair the original code was using getchar() not scanf().
      The same problem occurs.

      >> Your solution to my problem had occurred to me but i
      >> would never have guessed it is the best solution!
      It may not be. It is at least portable. I would suggest however that if you use this construct a lot, you wrap the the whole scanf() and buffer flush code into a single function that simply returns the character - you only have to code ugly solutions once! You may see fflush(stdin) suggested; this is not portable, fflush() is not defined for input streams in the ISO standard, it is defined by the Microsoft however library used by MinGW/GCC. It certainly does not work if using the GNU C library. Solutions in C++ for istreams are simpler.

      Clifford

       
    • cpns

      cpns - 2007-12-10

      Since "An introduction to C programming" might refer to any number of tutorials, it would be a good idea to post a link. The name alone does not really identify what resource you are using.

      I doubt that this was "put in to assist the learning process by improving problem solving skills", but rather speaks to the probably quality of the resource you are using.

      The problem is this:

      When you use scanf() with the %c format specifier, you are asking for a single character to be assigned to the supplied variable, but because input from stdin is 'line oriented' you have to enter at least two keystrokes, the character to be assigned plus <newline>. The <newline> is a character too, and remains buffered but unused (because you only asked for one character from the buffer). So when you next ask for a charcter, the <newline> is supplied, and because it is a <newline> the buffer contains a complete line, so the scanf() call does not block.

      One solution:

      printf("Throw y/n ?");
      scanf("%c",&res);
      while( res != '\n' && getchar() != '\n' ){//do nothing}

      Now if the user presses just <newline>, it will fall through and in your code will behave as if 'n' were pressed. If the user enters any other character followed by newline, the character will be assigned to res, and the <newline> will be flushed by the getchar() call. If the user enters any number of characters before pressing <newline> the first will be assigned to res, and all others and the <newline> will be discarded by the getchar() being called in the loop.

      Note that the rules regarding the && operator mean that if (res != '\n') is false (i.e. res contains <newline>) the getchar() is never called (the left operand is not evaluated if the right is false because the whole expression will then always be false). If all that is just too arcane then it can be re-written thus:

      if( res != '\n' )
      {
      while( getchar() != '\n' ){ // do nothing }
      }

      This means that you are not constantly re-evaluating the loop-invariant expression (res never changes in the loop), which is generally a good thing, but is in fact irrelevant in this case - loop efficiency is not generally an issue when processing user input because the user input is so much slower and entirely non-deterministic in any case.

      When you've fixed that, you might want to handle the user answering in upper case ;-)

      Clifford

       
      • cpns

        cpns - 2007-12-10

        For "probably quality" read "probable quality".

        I took a closer look at your code and it obviously requires C++ compilation due to teh using declaration and the C++ headers included, but is otherwise C code, and more critically is not even valid C++ code. In C++ it is illegal to declare main() (or any function in fact) with an implicit return type. i.e. you must have:

        int main()
        {
        ...
        }

        not

        main()
        {
        ...
        }

        Most bizarrely you have included <iostream> but are not using iostreams, wheras you are using stdio but have not included <stdio.h>. It is working more by luck than judgement, probably because <iostream> indirectly includes <stdio.h> (or (<cstdio> if you like).

        It seems to me that if you are going to learn C you should learn just C, not a C-like subset of C++. To that end you should use C compilation rather than C++ compilation. However I would also recommend learning C++ rather than C, and as C++ code this leaves much to be desired - it is not even a good example of C code either for that matter. The Draw() function for example would be better implemented as a switch, since you are testing r for all possible values when only one can ever be true. Another alternative is to use r to index and array of function pointers - but that is a little advanced perhaps, and in terms of generated code will not be much different from using a switch.

        If this code is indicative of the quality of the tutorial rather than the manner in which you 'fixed' the tutorial code, I suggest that you reconsider your sources of information. If the issues I have raised are related to ways in which you have 'fixed' the code, I would suggest that you need to reconsider your assumptions about what the tutorial is presenting, stop mixing C and C++ and when you find a fault with the code don't just assume the author is testing you, it is much more likely that he has screwed up. Of course these are rash assumptions since you have not made it clear what tutorial we are talking about. I find it odd that you would take so much trouble to identify the name of the tutorial without making it unambiguous what material we were discussing. Even an author's name would be good.

        Clifford

         
    • Dan

      Dan - 2007-12-10

      Hi Clifford,

      Thanks for taking the time to look at this.

      I found the tutorial under help in the program i mentioned (Dev-C++ 4.9.9.2) and i got the header info by following the menu path 'file' 'new' 'project' 'console app' in the same prog.

      I had noticed the examples i was looking at were different to other examples of C++ i had found and i was guessing this was C not C++ (hence the tutorial name), i thought this must be a good starting point and the lessons would give me a good foundation :).

      Like i said i did make some changes to the code (most likely the parts that offended you most) and to be fair the original code was using getchar() not scanf().

      Your solution to my problem had occurred to me but i would never have guessed it is the best solution!

      Thanks again for your input,

      Dan

       

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.