So what exactly DOES display do.....? :(

B

blackneos940

Guest
I got this Block of Code from that book I was told about..... :)

Code:
/*Showchar.c -- prints characters in rows and columns*/

#include <stdio.h>

display(char cr, int lines, int width);

int main()

{
  int ch; /*Character to be printed*/

  int rows, cols; /*Number of rows and columns*/

  printf ("Enter a character and two integers:\n>>> ");

  while ((ch = getchar()) != '\n')

  {

    if (scanf("%d %d", &rows, &cols))

      break;

    display(ch, rows, cols);

    while (getchar() != '\n')

      continue;

    printf ("Enter another character and two integers;\n");

    printf ("Enter a newline to quit.\n");

    }

  printf ("Bye.\n");

  return 0;

}

  display(char cr, int lines, int width)

  {

    int rows, col;

    for (rows = 1; rows <= lines; rows++)

    {

      for (col = 1; col <= width; col++)

        putchar(cr);

      putchar('\n'); /*End line and start a new one*/

  }

}

Um.... Also, I removed all instances of "void", as I was told by someone here that "void" is bad practice or something....... :) It seemed to work fine, and I THINK I get the gist of the Code, but..... If I put 'display ("Hello World!!")', then it doesn't work..... :( Why.......? Thank you for any help guys.... :3
 


First of all, providing your compiler is compliant with at least the c89 ANSI / c90 ISO Standard, void is absolutely valid in the following circumstances:
  • As the return data type if the function is designed NOT to return any data to the calling function, as in: "void display(char cr, int lines, int width)"
  • If the function is not meant to receive any data, or if main() does not need to process any command line data, then you should use void in the parameter list, as in: "int main(void)"
  • Some functions such as malloc() will return a void * as a generic pointer that can be assigned to any pointer variable, and can be passed as a parameter to a function for a similar purpose.
You also have a couple of errors in the code you posted.
Code:
if (scanf("%d %d", &rows, &cols))
Should really be:
Code:
if (scanf("%d %d", &rows, &cols) != 2)

Without the code I added, you break out of the while() loop and nothing gets printed. Also you expect that the user will type the correct input, such as:
Code:
Enter a character and two integers:
>>> A 3 4
but what happens if the user types?
Code:
Enter a character and two integers:
>>> A B C

You need to add some extra code to trap for invalid input, clear the input buffer, and ask the user to re-enter valid data, perhaps by showing the user an example. Also, you should not use fflush() on stdin or any input file. The results are undefined. There is an alternative method. You should look for the solution yourself. If you can't find it, I will tell you! ;^)

It is amazing how many textbooks on The C Programming Language, and how many instructors fail to teach student how to use scanf() properly to insure data is input correctly! Don't worry, you are not alone!!! ;^)
 
Other observations about the code:

In the code:
Code:
  for (rows = 1; rows <= lines; rows++)

  {

    for (col = 1; col <= width; col++)

      putchar(cr);

    putchar('\n'); /*End line and start a new one*/

  }

I would recommend setting the index (rows & col) to 0 instead of 1, and using '<' rather than "<=". In this case it is not a problem, but if processing an array it is too easy to get bit by the "Off by one error"! ;^)

Plus, for all if(), while() , and for() statements, I recommend using braces even if there is only one statement to be executed by the control, or loop statement. It is more clear to the programmer when writing code, the maintainer later, and if debugging is needed, exactly which statements are part of the control or loop statement.

Revised code:
Code:
  for (rows = 0; rows < lines; rows++)
  {
      for (col = 0; col < width; col++)
      {
          putchar(cr);
      }

      putchar('\n'); /*End line and start a new one*/
  }

There are a few more comments I could make, but these are the most important.
 
First of all, providing your compiler is compliant with at least the c89 ANSI / c90 ISO Standard, void is absolutely valid in the following circumstances:
  • As the return data type if the function is designed NOT to return any data to the calling function, as in: "void display(char cr, int lines, int width)"
  • If the function is not meant to receive any data, or if main() does not need to process any command line data, then you should use void in the parameter list, as in: "int main(void)"
  • Some functions such as malloc() will return a void * as a generic pointer that can be assigned to any pointer variable, and can be passed as a parameter to a function for a similar purpose.
You also have a couple of errors in the code you posted.
Code:
if (scanf("%d %d", &rows, &cols))
Should really be:
Code:
if (scanf("%d %d", &rows, &cols) != 2)

Without the code I added, you break out of the while() loop and nothing gets printed. Also you expect that the user will type the correct input, such as:
Code:
Enter a character and two integers:
>>> A 3 4
but what happens if the user types?
Code:
Enter a character and two integers:
>>> A B C

You need to add some extra code to trap for invalid input, clear the input buffer, and ask the user to re-enter valid data, perhaps by showing the user an example. Also, you should not use fflush() on stdin or any input file. The results are undefined. There is an alternative method. You should look for the solution yourself. If you can't find it, I will tell you! ;^)

It is amazing how many textbooks on The C Programming Language, and how many instructors fail to teach student how to use scanf() properly to insure data is input correctly! Don't worry, you are not alone!!! ;^)

Oh..... :) Ok!..... :D So "void" CAN be used..... I had assumed it was old and outdated....... :) Also, I didn't even THINK about those little kinks..... :( You sure would make a good Hacker, good sir..... :3 Okay!..... I'll apply the advice you gave me..... :D
 
Other observations about the code:

In the code:
Code:
  for (rows = 1; rows <= lines; rows++)

  {

    for (col = 1; col <= width; col++)

      putchar(cr);

    putchar('\n'); /*End line and start a new one*/

  }

I would recommend setting the index (rows & col) to 0 instead of 1, and using '<' rather than "<=". In this case it is not a problem, but if processing an array it is too easy to get bit by the "Off by one error"! ;^)

Plus, for all if(), while() , and for() statements, I recommend using braces even if there is only one statement to be executed by the control, or loop statement. It is more clear to the programmer when writing code, the maintainer later, and if debugging is needed, exactly which statements are part of the control or loop statement.

Revised code:
Code:
  for (rows = 0; rows < lines; rows++)
  {
      for (col = 0; col < width; col++)
      {
          putchar(cr);
      }

      putchar('\n'); /*End line and start a new one*/
  }

There are a few more comments I could make, but these are the most important.
So I should use Brackets more.....? Ok!..... :) But, what IS the "Off-by-one error".....? :) I read about it in a book about Hacking, once..... :) Thanks for all the advice, good sir..... :3
 
"Off by One" error

A OBOE, is either a for or while loop using one less or one more iterations than you should, or attempting to access an element in an array, outside the legal range.

In any array, the subscripts start at 0 through the number of elements minus 1. You should not attempt to access data before the start, or after the end of the array.

In the following code, the correct range would be 0 - 4.

The following code works correctly:
Code:
#include <stdio.h>
#define COUNT 5

int main(void)
{
    int ary[] = {10, 20, 30, 40, 50};
    int i;

    for (i = 0; i < COUNT; i++)
    {
        printf("ary[%d] == %d\n", i, ary[i]);
    }

    return 0;
}

Correct Output:
Code:
ary[0] == 10
ary[1] == 20
ary[2] == 30
ary[3] == 40
ary[4] == 50

If I change the for() loop to:
Code:
for (i = 1; i <= COUNT; i++)

INCORRECT OUTPUT:
Code:
ary[1] == 20
ary[2] == 30
ary[3] == 40
ary[4] == 50
ary[5] == 32764

You don't know what "32764" represents! It may be a garbage value, or legitimate part of some other data. It is bad enough to read the data, but worse if you alter any data outside of the range of the array!

This is a common error for beginners, but can bite professionals as well!
 
"Off by One" error

A OBOE, is either a for or while loop using one less or one more iterations than you should, or attempting to access an element in an array, outside the legal range.

In any array, the subscripts start at 0 through the number of elements minus 1. You should not attempt to access data before the start, or after the end of the array.

In the following code, the correct range would be 0 - 4.

The following code works correctly:
Code:
#include <stdio.h>
#define COUNT 5

int main(void)
{
    int ary[] = {10, 20, 30, 40, 50};
    int i;

    for (i = 0; i < COUNT; i++)
    {
        printf("ary[%d] == %d\n", i, ary[i]);
    }

    return 0;
}

Correct Output:
Code:
ary[0] == 10
ary[1] == 20
ary[2] == 30
ary[3] == 40
ary[4] == 50

If I change the for() loop to:
Code:
for (i = 1; i <= COUNT; i++)

INCORRECT OUTPUT:
Code:
ary[1] == 20
ary[2] == 30
ary[3] == 40
ary[4] == 50
ary[5] == 32764

You don't know what "32764" represents! It may be a garbage value, or legitimate part of some other data. It is bad enough to read the data, but worse if you alter any data outside of the range of the array!

This is a common error for beginners, but can bite professionals as well!
Wow.....! :O I had an IDEA of what an "OBOE" was, and had even read about it..... :) But I had trouble thinking about just HOW it would be written..... :) Thanks a lot, good sir!..... ^^ Hey, did you know that if you Jailbreak a PS3, you can put Linux on it.....? :3
 

Members online


Top