Hi All :mrgreen: ,
was mucking about with a small programme I have which makes a triangle pattern when entering in a number. It uses nested For loops.

I now want to create the same thing using functions as im only just beginning to learn the C language. I have started it but get One error. Maybe some nice person could suggest a few things ? :)

Heres the Nested For loop code

#include <stdio.h>
#include <conio.h>
void triangle(int n);
int main(void)
{
int rowLength;
int starCount;
int rowHeight;
printf("\n Enter a number to display a triangle: ");
scanf("%d", &rowHeight);
void triangle(int n);
for (rowLength = 1; rowLength <= rowHeight; ++rowLength)
{
    printf("\n");
    for (starCount = 1  ; starCount <= rowLength; ++starCount)
    printf("*");
}
printf("\n");
getche();
}

and here is my attempt which isn't finished and need help with using Functions

#include <stdio.h>
#include <conio.h>
void triangle(int n);
int main(void)
{
int rowLength;
int rowHeight;
printf("\n Enter a number to display a triangle: ");
scanf("%d", &rowHeight);
 
 for (rowLength = 1; rowLength <= rowHeight; ++rowLength)
 {
  printf("\n");
 }
  return rowHeight;
}
void triangle(int n, int starCount, int rowLength)
{ 
    for (starCount = 1 ; starCount <= rowLength; ++starCount)
    printf("*");
 
 return starCount;
printf("\n");
getche();
}

Hi All :mrgreen: ,
was mucking about with a small programme I have which makes a triangle pattern when entering in a number. It uses nested For loops.

I now want to create the same thing using functions as im only just beginning to learn the C language. I have started it but get One error. Maybe some nice person could suggest a few things ? :)

Only one? There are somewhere around 500 errors possible. Compiler errors. Runtime errors. Logic errors. Can you be a little less vague? What's the error? Where does it occur?

A few guidelines:

1. Don't use non standard functions ( getche( ) ) and non standard headers ( conio.h ) since they make your code non portable ( i.e. your code won't compile on compilers other than the one which you are currently using)

2. The main concept behind the use of functions is that a task is delegated to it by the main program or the driver program. The main program or the calling function just expects the function to do the required task for it. How the task is achieved is the function's lookout.

3. If you go out to extend this concept, we can divide the program in roughly two parts -- the input accepting stage and the computation stage.

4. The input gathering stage takes place in your main loop i.e. the entry point of your program. So what remains is the computation part.

5. The computation part can be seperated out from the main program by providing it exactly the amount of data which it requires for performing the computation, which in this case is "rowheight".

6. So create a function which accepts the "rowheight" from the main program, performs the computations on it (in this case rendering the triangle) and returns to the main( ) function after performing its job.

A skeleton:

void render_triangle( int height )
{
     int row_length = 0 ; // initialize your variables to prevent bugs.
     int star_count = 0 ;

     // write the same way you had previously written assuming it was
    // working. Run two for loops.
}

In case of more doubts, repost if necessary.

Ah yes sorry, Im using MS Visaul C++ and the error i get is :

(1) Programming\tfgh-----.cpp(30) : error C2562: 'triangle' : 'void' function returning a value - this points to the line " return starCount;
"

(2) Programming\tfgh-----.cpp(24) : see declaration of 'triangle'

This points to the line "void triangle(int n, int starCount, int rowLength)"

Im quite sure this is not the problem to the programme, thanks for helping anythng else I haven't said please let me know and I shall give you the details :D

(1) Programming\tfgh-----.cpp(30) : error C2562: 'triangle' : 'void' function returning a value - this points to the line " return starCount;

You are trying to return value from a function whose return type has been declared void. Why would you want to return the starcount from your function if it is already achieving the purpose of drawing out the tirangle ?

(2) Programming\tfgh-----.cpp(24) : see declaration of 'triangle'
This points to the line "void triangle(int n, int starCount, int rowLength)"

Ditto here too. You have given the prototype of your function "triangle" as one taking an integer and returning nothing i.e. void. So why define your function with 2 extra parameters as "void triangle ( int n, int starcount, int rowlength )"

Read my previous post in which I have already given you the guidelines to solving the problem.

Thanks for all your replies, you have been really helpful, For some reason I still cant get the function to work, I did what you said but I think I have messed up somewhere, I Have spent all morning on it and still no luck. The first part works fine with the triangle newlines (\n) but thats it.

Any more help welcome

Have played around with it so much im possitive its completely wrong.
anyways here it is:

#include <stdio.h>
void triangle(int n);
int main(void)
{
int rowLength = 0;
int rowHeight = 0;
printf("\n Enter a number to display a triangle: ");
scanf("%d", &rowHeight);
 
 for (rowLength = 1; rowLength <= rowHeight; ++rowLength)
 {
  printf("\n");
 }
  return rowHeight;
}
void render_triangle( int height )
{
     int row_length = 0 ; 
     int star_count = 0 ;
 
     for (row_length = 1; row_length <= height; ++row_length)
  {
  printf("\n");
  }
  for (star_count = 1  ; star_count <= row_length; ++star_count)
   { 
   printf("*");
   {
}
 
}

the error i get is :
Programming\testagain.cpp(39) : fatal error C1004: unexpected end of file found

Also, If I make it as nested For on the second part, I get no errors but when I run it again only the newlines work (\n)

your missing one closing curly-bracket. Just add a } at the bottom of your code and : viola! This problem can be solved by using indention. Just search daniweb for it, there are plenty of examples.

But...That your program compiles does not mean it works as you expect. There are quite a few errors in it. For example:
- You declare void triangle(int n); . But your function is called render_triangle .
- Why does main return rowHeight?
- Where do you call your function?
- and there are a few thing wrong with the function too...

Try fixing some of these things and come back for help if you get stuck.

Edited 5 Years Ago by Nick Evan: n/a

Nothing reallly happens, I get the same thing, the first bit works but nothing is displayed, the cursor is correctly placed after pressing enter though (I.e I enter 5 and press enter, the cursor is 5 newlines down afterwards)

First of all, here is your code indented with some comments:

#include <stdio>

//void triangle(int n); // function prototype does not match the declaration. should be:
void render_triangle(int height); // or: void render_triangle(int n);

int main()
{
    int rowLength = 0;
    int rowHeight = 0;
    printf("\n Enter a number to display a triangle: ");
    scanf("%d", &rowHeight);
 
    for (rowLength = 1; rowLength <= rowHeight; ++rowLength)
    {
        printf("\n");
    }

//    return rowHeight; // why return rowHeight from main? should be:
    return 0; // always!!!
}

void render_triangle(int height)
{
    int row_length = 0 ; 
    int star_count = 0 ;
 
    for (row_length = 1; row_length <= height; ++row_length)
    {
        printf("\n");
    }

    for (star_count = 1  ; star_count <= row_length; ++star_count)
    { 
        printf("*");
    {
}

// } // one too many brackets, indenting will fix clear these mishaps up

And second, you need to think where and why you are calling the render_triangle function. You havn't called it from anywhere in main

Yah, that's exactly what I said...

@80s: please reread my previous post carefully.

Inside your function, you should use nested loops: an outerloop for rows and an innerloop for printing stars.

Regards Niek

Code so far

#include <stdio.h>
void triangle(int n);
 
int main(void)
 
{ int rowLength = 0;
 int rowHeight = 0;
 
printf("\n Enter a number to display a triangle: ");
scanf("%d", &rowHeight);
 
 for (rowLength = 1; rowLength <= rowHeight; ++rowLength)
    {
     printf("\n");
    }
     return 0;
}
 
void triangle(int n)
 
{    int row_length = 0 ; 
     int star_count = 0 ;
 
     for (row_length = 1; row_length <= n; ++row_length)
   {
      printf("\n");
 
         for (star_count = 1  ; star_count <= row_length; ++star_count)
        {
          printf("*");
        }
   }
}

What problem(s) are in the function ?

thanks for the help guys !

You're still not calling it.

int main(void)

{ int rowLength = 0;
int rowHeight = 0;

printf("\n Enter a number to display a triangle: ");
scanf("%d", &rowHeight);

for (rowLength = 1; rowLength <= rowHeight; ++rowLength)
    {
     printf("\n");
    }
     return 0;
}

Replace the piece marked in red with: triangle(rowHeight) Then it should give you some output. I have to go now, someone else will help you with further problems!

Regards Niek

What problem(s) are in the function ?

None. It looks okay except you don't actually call the function. :) You could also work on your formatting a bit. Consistency is the key.

#include <stdio.h>

void triangle(int n);

int main(void)
{
  int rowHeight = 0;

  printf("\n Enter a number to display a triangle: ");
  scanf("%d", &rowHeight);

  triangle( rowHeight );

  return 0;
}

void triangle(int n)
{
  int row_length = 0; 
  int star_count = 0;

  for (row_length = 1; row_length <= n; ++row_length)
  {
    printf("\n");

    for (star_count = 1; star_count <= row_length; ++star_count)
    {
      printf("*");
    }
  }
}

Hey thanks alot Niek, that last bit was the main problem all the way through. Thanks for that.

@ 80s

Here's my try at it.

/*
 *  triangle.c
 *  based on a version of a program that 80s posted at
 *  http://www.daniweb.com.
 *  He wrote:
 *  "Hi all :),
 *  was mucking about with a small programme I have which makes a triangle pattern when entering
 *  in a number. It uses nested For loops."
 *
 */
 

 #include <stdio.h>
 
 void show_triangle(int row_height); /* prototype of a function */

int main(void)
{
    
    int answer_choice;  /* for user selection of height */
    
    printf("\tEnter a number to display a triangle: "); /* invite the user to select a number */
    scanf("%d", &answer_choice);    /* read the user input from keyboard */
    putchar('\n');      /* extra return character for neat format */
 
    show_triangle(answer_choice); /* call of the function that displays the triangle pattern */
    
    fflush(stdin);      /* clears the standard input (keyboard) of any character left by any function */
    getchar();          /* pause the program until the user input any character in this case ENTER */
   return(0);
    
    
}

 /**************************************************
*    void show_triangle()
*   acept a integer parameter.
*   returns nothing.
*   displays a triangle patterns made of "*"
***************************************************/
void show_triangle(int row_height)
{
    int height_counter = 0;     /* index the height in the first loop */
    int length_counter = 0;     /* index the length of "*" in the second loop */
     
    
    for (height_counter = 1 ; height_counter <= row_height; height_counter++) /* stops when height_counter
    is more that the parameter recibed (row_height) */
    {
        for(length_counter = 1; length_counter <= height_counter; length_counter++) /* prints "*" in rows */
            printf("*");
    printf("\n"); /* after each sucessful row of "*" */
    }     
    
}

Hey, 80s, since both of us are learning functions, look what happens when I throw at it a new function named spacing. It reverses the direction that the triangle points to.

#include <stdio.h>

void triangle(int n);
void spacing(int height);

int main(void)
{
  int rowHeight = 0;

  printf("\n Enter a number to display a triangle: ");
  scanf("%d", &rowHeight);

  triangle( rowHeight );

  fflush(stdin);
  getchar();

  return 0;
}

void triangle(int n)
{
  int row_length = 0;
  int star_count = 0;

  for (row_length = 1; row_length <= n; row_length++)
  {
    printf("\n");
    spacing(n - row_length);   /* call to the function that displays spaces */

    for (star_count = 1; star_count <= row_length; star_count++)
      printf("*");
  }
  
}

/* ************************************************
 *
 *   spacing()
 *   parameters:
 *       int height --> accept the numbers of rows
 *   returns: 0
 *
 ************************************************/
void spacing(int height)
{
    int i;

    for (i = height; i > 0 ; i--)
        printf(" ");
}

A few points to be noted Aia :

  • * spacing()
    * parameters:
    * int height --> accept the numbers of rows
    * returns: 0

    I hope you do realize that something returning 0 is not equivalent to something returning void. 0 is after all a number, which in the end amounts to something whereas void is just void and has a special meaning, it just doesn't exist. Hence you should write returns : void and not the incorrect one returns: 0 .

  • The behaviour of the function fflush is undefined on the input stream i.e. stdin . Read this. And for accepting user input in a relatively safe way, see here.

Hope that helped, bye.

@~s.o.s~
Thank you. Your correction is appreciated
@WaltP
Thank you also for your input.

I didn't know it was bad. I always use it to ensure that getchar() (to pause the program) is not going to read any thing left behind by any scanf() or any other function used. I read the linked reference, but I'm not clear why it is so bad except that it depends of the compiler to work properly.
What choice do I have if I still use scanf() until I learn something different?. Is fflush(stdout) as bad?

@~s.o.s~
Thank you. Your correction is appreciated
@WaltP
Thank you also for your input.

You're welcome... ;)

I didn't know it was bad. I always use it to ensure that getchar() (to pause the program) is not going to read any thing left behind by any scanf() or any other function used. I read the linked reference, but I'm not clear why it is so bad except that it depends of the compiler to work properly.

Because it depends on the compiler to work properly. Let's assume you keep using fflush(stdin) because it seems to work for you. Then when you get a job you're using a compiler it doesn't work with. How long are you going to spend debugging your code wondering why someting that's always worked is no longer working? You'll most likely not even check that line because "it's always worked before".

What choice do I have if I still use scanf() until I learn something different?. Is fflush(stdout) as bad?

Use a combination of fgets() and sscanf() . Or use the code listed in that link to clear the buffer.

I always use it to ensure that getchar() (to pause the program) is not going to read any thing left behind by any scanf() or any other function used.

That's what most people use it for, but not all compilers support that behaviour. All you're really doing is reading extra characters on a line from the stream and throwing them away, and that's easy to do without using a compiler extension.

void flush( FILE *is )
{
  int ch;

  do {
    ch = getchar();
  while( ch != EOF && ch != '\n' );
}

I read the linked reference, but I'm not clear why it is so bad except that it depends of the compiler to work properly.

It's not really that bad if your compiler supports it. People get a little crazy with stuff like this, and you shouldn't worry too much about it. The problem is twofold.

  1. fflush is defined as writing unwritten characters to an output device from an output stream. Using it on an input stream doesn't make sense.
  2. The language standard says that using anything but an output stream with fflush is undefined.

The last part is what gets people in a stink. The language standard is the defining document for C, and if it says something is broken, it's broken. And 'undefined' means seriously broken. ;)

You can use fflush( stdin ) as long as your compiler supports it. If you plan on compiling your code with another compiler, you could be invoking undefined behavior accidentally, and that's a really bad thing because there's no such thing as a little undefined behaviour. If any part of your program is undefined, the whole program is undefined and that means it could do anything. Including wipe your hard drive or send obscene emails to your boss. :lol:

In my opinion, it's okay to use fflush( stdin ) as long as you put it in a portability module and make sure to change it when you move the code to another compiler. A portability module is basically just a bunch of wrapper functions that do nonstandard stuff that has to be changed when you move the code. Something like this.

void port_flush()
{
  fflush( stdin );
}

Then you make calls to port_flush() everywhere you would use fflush( stdin ) . When you need to move to a compiler that doesn't allow fflush( stdin ) , you change the body of port_flush() to something the compiler does support. That way you get the benefits of a compiler extension without the problems of changing umpteen uses of it. You just change one use and the umpteen other uses are automatically updated.

Is fflush(stdout) as bad?

fflush( stdout ) is completely different. It's a correct use of fflush() that writes any unwritten characters to the output device. One good way to use it is with user prompts that don't go to a new line.

printf( "Please enter something: " );
fflush( stdout );
fgets( something, sizeof something, stdin );

On some systems, if you don't flush stdout then the fgets() will happen before the prompt shows up, and the user won't know what to type. You flush a stream when you want to make sure that any output is written right away. Otherwise you have to wait until either the stream is full or a '\n' character is printed. Both of those things automatically flush the stream.

Comments
This helped me to understand

In short, not to bother yourself with non standard things untill you get enough understanding of how things work under the hood or the full implication of using non standard functions or untill you become expert at writing wrapper modules as per Mr. Ravalon...:D

For the time being just stay clear of non standard things, and the knowledge of what is non standard will automatically come to you.

@~s.o.s~
You wrote to me:

The behaviour of the function fflush is undefined on the input stream i.e. stdin. Read this. And for accepting user input in a relatively safe way, see here.

following the first link, a portion of it says:

Your best bet, and I know this is beyond beginners so it's something to look forward to, you need to read a character buffer and parse the input yourself. There's only so much intelligence a canned C/C++ function can have. Until you can do this, you won't easily be able to create bulletproof input. Sorry.

Now I'm intrigued by the part that says "you need to read a character buffer and parse the input yourself".

Could you shed some light on what it means so I can google or find out more about how to do this?. I want to lear how parse is done.

Here I will asssume that you know what parse in this particular context means. (walking through the character buffer)

Now I'm intrigued by the part that says "you need to read a character buffer and parse the input yourself"

It simply means accept or read the input from the user or from an opened file stream in a character array (known as a character buffer ) , and then define your own rules what you want to do with the pulled in contents or define how you want to interpret the gathered input.

The great thing about character buffers is that they can be used to accept any kind of input (almost anything) from the user in the form of string (C style strings aka null terminated strings) which you can then parse to treat it the way you want. For example if you are expecting a number from the user, just accept the input from the user in the form of string in a character buffer, check each character individually if it is a digit or not using isdigit( ) and then define your own logic as to what you want to do when you encounter a non digit character.

I would highly recommend you to see the excellent tutorials by Mr. Dave Sinkula on how to stay away from bad programming practices and safely accept the input from the user.

This article has been dead for over six months. Start a new discussion instead.