Multiplication table - C - c

I want to display multiplication table which will look like this:
1 2 3 4 5 6 7 8
1 1x1=1
2 1x2=2 2x2=4
3 1x3=3 2x3=6 3x3=9
4 1x4=4 2x4=8 3x4=12 4x4=16
5 1x5=5 2x5=10 3x5=15 4x5=20 5x5=25
6 1x6=6 2x6=12 3x6=18 4x6=24 5x6=30 6x6=36
7 1x7=7 2x7=14 3x7=21 4x7=28 5x7=35 6x7=42 7x7=49
8 1x8=8 2x8=16 3x8=24 4x8=32 5x8=40 6x8=48 7x8=56 8x8=64
So far I have something like this:
#include <stdio.h>
int main()
{
int n, i;
scanf("%d", &n);
int row,col;
if(n<1 || n>9)
{
printf("input error");
return 0;
}
for (row=0; row<=n;row++){
if(row==0)
{
for(i=1; i<=n; i++)
{
printf("\t%d", i);
}
}
for(col=0; col<=row;col++)
{
if(col==0 && row>0)
printf("%d\t", row);
if(row>=1 && col!=0)
printf("%dx%d=%d\t", col, row, col*row);
}
if(row!=n)
printf("\n");
}
return 0;
}
I think it displays the table properly, but the code looks sloppy and I'm sure it can be done in a much cleaner way. Any suggestions?

I'd unroll the first pass through each of the loops that displays the row & column headers:
#include <stdio.h>
int main()
{
int n, i;
scanf("%d", &n);
int row,col;
if(n<1 || n>9)
{
printf("input error");
return 0;
}
for(i=1; i<=n; i++)
{
printf("\t%d", i);
}
printf ("\n");
for (row=1; row<=n;row++){
printf("%d\t", row);
for(col=1; col<=row;col++)
{
printf("%dx%d=%d\t", col, row, col*row);
}
if (row!=n)
printf("\n");
}
return 0;
}

Most of what makes your code look sloppy is simply bad style. Here are a few tips based on what is generally considered good style and best practice:
Print a prompt whenever your program is getting input from the user
Put all variable declarations together at the top of the main function
Use parenthesis to make the order of operations clear, especially when using the && and || operators
Make error messages clear
return a negative value to indicate an error
Put a space on both sides of binary operators (i.e. "n < 1" as opposed to "n<1")
Put a space after commas when declaring multiple variables
Put a space after semi-colons in for loop conditions
The following is generally considered a good-style for loop:
for (condition) {
...
}
The following is generally considered a good-style if statement
if (condition) {
...
}
Use comments to explain your code and increase readability
Use indentation to show code grouping
Aside from all of these things, your program also does not print a newline after the very last row (row n) due to the very final if statement. This causes the user's command-line prompt to be displayed on the same line as the last row printed by your program, which is probably not desirable.
Applying all of these things to your code gives the following result:
#include <stdio.h>
int main()
{
// all variables declared together, at the top of main
int n, i;
int row, col; // space after comma
printf("Enter multiplication table size: "); // prompt
scanf("%d", &n);
// better-style if statement
if ((n < 1) || (n > 9)) { // parenthesis make the order of operations clearer
// clearer error message, with a newline at the end
printf("Error: table size must be at least 1 and not greater than 9\n");
return -1; // return a negative value to indicate an error
}
// better-style for loop
for (row = 0; row <= n; row++) { // spaces around binary operators, space after semi-colons
// better-style if, indented also
if (row == 0) {
// better-style for, indented
for (i = 1; i <= n; i++) { // spacing
printf("\t%d", i); // indented
}
}
// better-style for
for (col = 0; col <= row; col++) { // spacing, indentation
if ((col == 0) && (row>0)) // parenthesis, spacing, indentation
printf("%d\t", row); // indentation
if ((row >= 1) && (col != 0)) // parenthesis, spacing, indentation
printf("%dx%d=%d\t", col, row, col * row); // indentation, spacing
}
// surrounding if statement removed, so a newline is printed after every row, including the last one
printf("\n");
}
return 0;
}
Note that I mainly used comments to explain the changes I made to your code, whereas you would want to use them to explain the functionality.

Related

How to break a while loop when it is false to a certain condition

I was trying to make a program where if I enter an integer, the program would find out the bigger number and subtract it by the smaller number. This part, I got it.
The problem is, the infinite loop part.
I tried to get type in two integers keep on printing with the while loop, and break when at least one character is typed in.
For example, if I type in 2 #, it would break.
But I couldn't find the write place to get the break; within the code and therefore whenever I enter a character it would keep on creating an infinite loop.
Is there any way to create a break in this code? I humbly ask for advice...
The following is the code which I couldn't put the break
(By the way, the reason I did the condition in while as sizeof(i)==4 || sizeof(j)==4 was to make it so it would only enter an integer, since the size of an integer is 4)
int main()
{
int i, j;
int result;
while (sizeof(i)==4 || sizeof(j)==4){
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i){
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
The bottom code is the one I tried to put break but failed (it kept creating an infinite loop)...
int main()
{
int i, j;
int result;
while (sizeof(i)==4 || sizeof(j)==4){
if (sizeof(i) == 4 || sizeof(j) == 4) {
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
else
break;
}
return 0;
}
and here's a code where I got rid of the sizeof and used while(1), though there wasn't much change in the fact that the break didn't work...
int main()
{
int i, j;
int result;
while (1){
printf("type in two integers : ");
scanf("%d %d", &i, &j);
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
You can't use sizeof(i) to do run-time checks! This is a compile-time constant that, in your case (32-bit integers) will always evaluate to 4.
In order to check that two valid integers have been given, you can check the return value of the scanf function (it gives the number of fields successfully scanned):
#include <stdio.h>
int main()
{
int i, j;
int result;
while (1) {
printf("type in two integers : ");
if (scanf("%d %d", &i, &j) != 2) break; // Break here if we didn't get two integers
if (i < j) {
result = j - i;
}
else if (j < i) {
result = i - j;
}
printf("%d\n", result);
}
return 0;
}
Feel free to ask fir further clarification and/or explanation.
Drop the whole concept of endless loop with break inside if.
Make a condition for the loop based on the return value of scanf(), that is practically what it is designed for.
#include <stdio.h>
int main()
{
/* always init everything */
int i=0, j=0;
int result=0;
printf("type in two integers : ");
while (2==scanf("%d %d", &i, &j))
{
if (i < j) {
result = j - i;
}
else /* removed second if, to have a meaningful result for i==j */
{
result = i - j;
}
printf("%d\n", result);
printf("type in two integers : ");
}
return 0;
}
I'd probably actually use do {...} while (...) with a variable storing the return value of scanf()for being used in the loop condition. I'd consider it more elegant for not having to copy the print, but I kept it closer to your code structure.
More comments on your code:
as explained in comments, sizeof() works differently than you seem to think; it is static and does not change at runtime and hence cannot be used in a loop condition
with while (sizeof(i)==4 || sizeof(j)==4){if (sizeof(i) == 4 || sizeof(j) == 4){/* a */} else {/* b */}, b cannot ever be reached, because the conditions of while and if are identical
check the possible outcomes of the if conditions inside the loop, you are leaving the one with i==j undefined and return an uninitialised value
always init all variables as a habit
for a good MRE include the include lines
On your request, here is a proposal for the do-while alternative:
#include <stdio.h>
int main()
{
/* always init everything */
int i=0, j=0;
int result=0;
int iScanned=0;
do
{
printf("type in two integers : ");
iScanned=scanf("%d %d", &i, &j); /* keep the return value for loop */
if (i < j) {
result = j - i;
}
else /* removed second if, to have a meaningful result for i==j */
{
result = i - j;
}
if(2==iScanned) printf("%d\n", result); /* if to avoid awkward last output */
} while (2==iScanned);
return 0;
}

Array pointer while loop input

I am trying to write a program to check for duplicate input from a programmable handheld barcode scanner, I am programming it to be able to scan 2000 barcodes.
I am new to c Programming, I am trying to take an input and put it into the array and increase the pointer to the next with every loop.
Example: int Array [10];
I want to scanf() into Array location 0 on the first loop then increment by 1 location to location 2 etc every time the while loops runs. Please help, your help is much appreciated.
#include <stdio.h>
int main ()
{
int i,j,k=1,arr[2000],ArrSize=2000;
//Welcome message
printf("Welcome to Yamato Transport (S) Pte. Ltd.\n");
printf("Barcode checker Ver 1.0\n");
while (k>=2000,k++)
{
//Scanner Input
for(i=0;i<ArrSize;i++)
{
scanf("%d",&arr[i]);
}
//Duplicate Logic
printf("Duplicate Barcodes: ");
for(i=0; i<ArrSize; i++)
{
for(j=i+1;j<ArrSize;j++)
{
if(arr[i]==arr[j])
{
printf("%d\n",arr[i]);
}
}
}
//Remove single duplicate
//Clear Screen
}
return 0;
}
The first problem with your code is this:
int i,j,k=1,...
...
while (k>=2000,k++)
^^^^^^
ups...
This will give the warning "left-hand operand of comma expression has no effect" which actually means that the line is the same as:
while (k++)
That will keep looping until you have integer overflow (which is undefined behavior). So you don't want to do that.
Since you initialize k to 1, I assume that you wanted to do:
while (k++ < 2000)
Now let's assume that you want:
while (k++ < 2000) // Will loop approx 2000 times
{
//Scanner Input
for(i=0; i< ArrSize; i++) // Will loop 2000 times
{
scanf("%d",&arr[i]);
}
So in the end your program calls scanf 2000 x 2000 = 4.000.000 times. Is that what you want? The purpose of the outer while is unclear.
Your program first reads 2000 integers and afterwards it seems you want to remove duplicates. That's a bad approach as you may end you doing a lot of memory move whenever you need to remove a duplicate element from the array.
A better approach is to check whether a newly scanned value is a duplicate before inserting it in the array. That could look something like:
for(i=0; i < ArrSize; )
{
int tmp;
if (scanf("%d", &tmp) != 1)
{
// Input error
exit(1);
}
// Check if tmp is already in the array
int duplicate = 0;
for (int j = 0; j < i; ++j)
{
if (tmp == arr[j])
{
duplicate = 1;
break;
}
}
if (duplicate)
{
printf("dup found\n");
}
else
{
arr[i] = tmp;
++i;
}
}
This should give you ArrSize unique elements.
Notice: In order to check if something is a duplicate, you'll need to scan through the array from start to the current number of elements. To improve performance you could consider another approach, e.g. a sorted tree, hash tables, etc so that check for duplicates can be done much faster. This gets more important as the number of array elements increase.
So half the problem is solved, I am still not sure how do I increase the pointer to the next position so on the next loop it will store another barcode number which will then be passed to the duplicate checker for checking then repeat the loop for the next scan.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i,j,k=1,arr[2000],counter=1;
//Welcome message
printf("Welcome to Yamato Transport (S) Pte. Ltd.\n");
printf("Barcode checker Ver 1.0\n");
while (k++ < 2000) // Will loop approx 2000 times
{
//Scanner Input
printf("Scan barcode\n");
for(i=0; i< counter; i++) // Will loop 1 time
{
scanf("%d",&arr[i]);
}
//check for duplicates
for(i=0; i < counter; )
{
int tmp;
if (scanf("%d", &tmp) != 1)
{
// Input error
exit(1);
}
// Check if tmp is already in the array
int duplicate = 0;
for (int j = 0; j < i; ++j)
{
if (tmp == arr[j])
{
duplicate = 1;
break;
}
}
if (duplicate)
{
printf("Duplicate Barcode\n");
}
else
{
arr[i] = tmp;
++i;
}
}
}
return 0;
}

Why is scanf() being skipped over in this nested for loop in language C?

I am writing a program for class that asks users to enter a the size of a 2D array and then has the user enter the values for the array. This is the code I have so far:
#include <stdio.h>
int main(void)
{
// Setup
int N, M;
int row = 0, col = 0;
printf("\n");
printf("This program counts occurences of digits 0 through 9 in an NxM array.\n");
printf("Enter the size of the array (Row Column): ");
scanf(" %d %d", &N, &M);
int array[N][M];
// Array Input
for (row = 0; row < N; row++)
{
printf("Enter row %d: ", row);
for (col = 0; col < M; col++);
{
scanf(" %d", &array[row][col]);
}
}
printf("\n");
return 0;
}
The issue that I am having when the program is compiled and the information is entered, the second and all following scanf() statements are skipped over or the whole second for loop is skipped over after the first line is entered. Here is an example of entered input:
This program counts occurences of digits 0 through 9 in an NxM array.
Enter the size of the array (Row Column): 2 6
Enter row 0: 0 1 2 3 4 5
Enter row 1:
And then the program ends entirely. I really have no idea why its being skipped over. I have tried altering how many spaces are in the scanf() statement but no matter what I change the same issue occurs. I am unsure if I am missing some stupid mistake I have made or if there is a bigger problem. I am pretty new at coding.
You just have a stray semicolon. Try changing
for (col = 0; col < M; col++);
{
to:
for (col = 0; col < M; col++)
{
A for introduces a statement which controls the very next statement, which could be a simple statement ending with a semicolon, another control statement, or a compound statement using { braces }. In your code, the semicolon on the same line as the for keyword counts as an empty statement that has no effect. So that code will just increment the loop variable the appropriate number of times, and only after that move on to the next part.
Make sure you enable compiler warnings. (Both gcc and clang provide clear warnings that this code might not do what you meant.)
for (col = 0; col < M; col++);
This is what you wrote inside the nest for loop. But the ";" simply means the end of code line and it will just run the for loop M times without doing anything.
Change it to
for (col = 0; col < M; col++)

Printing an odd hash inverted triangle in C

I am trying to print out an inverted hash triangle.
./upside_down_oddnumber
###########
#######
###
My work so far -
int main(void) {
int row, column;
int size;
printf("Enter size: ");
scanf("%d", &size);
row = 1;
while (row <= size) {
column = 1;
while (column <= size) {
if (row == (4 * size) -1 || row == column) {
printf("#");
} else {
printf(" ");
}
column++;
}
printf("\n");
row++;
}
return 0;
}
Currently it is printing a diagonal line sideways and I should use the equation 4n-1. How should I proceed from here? Any help will be greatly appreciated!!
Thanks :)
Start by examining the arithmetics behind the problem:
4*size-1 is the length of the top row of #, i.e. the width of your printout
Each row has an offset of spaces
The number of spaces starts at zero for the initial row, and increases by 2
These three observations should be enough to construct a program. Start row and column numbers at zero for consistency. Each row should be width characters long. Decide which character to print using this formula:
if (column >= offset && column < width-offset) {
printf("#");
} else {
printf(" ");
}
Demo.
The problem is your if statement.
The first section row == (4 * size) -1 is never going to be true, because the row will never be bigger then size, so 4*size will always be bigger then row and thus the statement will never give true.
The second section row == column will of course give you the line.
You should rethink your algorithm.
Or you could do
for(i=size; i>0; --i)
{
for(j=0; j<(4*size-1 - (4*i-1))/2; ++j)
{
printf(" ");
}
for(j=0; j<4*i-1; ++j)
{
printf("%c", '#');
}
printf("\n");
}
(4*size-1 - (4*i-1))/2 will give the number of spaces that must be printed at the start of each line.
After printing the required number of spaces, the #s are printed out.
You could also use
printf("%*s", (4*size-1 - (4*i-1))/2, "");
instead of the loop to print the spaces.
The * in %*s is used to specify the width of the string to be printed.

Making rectangle based on input

input
6 6 4
output
######
#....#
#....#
#....#
#....#
######
input
7 7 4
output
#######
#.....#
#.....#
#.....#
#.....#
#.....#
#######
This is the code I have so far.
#include <stdio.h>
int main()
{
int width;
int breadth;
scanf("%d", &width);
scanf("%d", &breadth);
if (width == 1 && breadth == 1)
{printf ("#\n");}
else{
for(int i = 0; i<breadth; i++){
for(int j = 0; j<width;j++)
{
{printf("#");}
}
printf("\n");}
}
return 0;}
Does anyone know how to replace the non boundary area with "."?
ps:there is no need to worry about the third input, it does not affect the shape of rectangles since its just going to be used next task.
I am guessing that I could perhaps change my for loops but I ran out of ideas at this point.
It would be greatly appreciated if someone could help me return identical output from above.
Thank you.
You want to replace non-boundary area with ".". To achieve that you need a condition that satisfies your boundary.
#include <stdio.h>
int main()
{
int width;
int breadth;
scanf("%d", &width);
scanf("%d", &breadth);
if (width == 1 && breadth == 1)
{printf ("#\n");}
else{
for(int i = 0; i<breadth; i++){
for(int j = 0; j<width;j++)
{
if(i==0||j==0)
printf("#");
else if(i==(breadth-1)||j==(width-1))
printf("#");
else
printf(".");
}
printf("\n");}
}
return 0;
}
Hope this works. Let me know if it does not or any problem is there.
Here is the working code.
You were almost there. You need the condition statement to check the boundary..
Please see the line that checks the boundary
#include <stdio.h>
int main()
{
int width;
int breadth;
scanf("%d %d", &width, &breadth);
if (width == 1 && breadth == 1)
printf ("#\n");
else
{
for(int i = 0; i<breadth; i++)
{
for(int j = 0; j<width;j++)
//Check for boundary.
if( j == 0 || j == width - 1 || i == 0 || i == breadth - 1 )
printf("#");
else
printf(".");
printf("\n");
}
}
return 0;
}
You should use counters. For example, one counter should be refering to which line you're printing and another one the column you're printing on.
If the line counter is 0, print all the line as '#' cause it's going to be the upper boundary line
(this creates -> #######)
Else If the line counter is same as the height of the shape, then it's the finishing border line
(#######)
Else if it's >0, print the first character as '#', then print '.' until another counter reaches the width of the shape -1 (for example in 7 7 that would be 5 (since 0 also counts)) and then another '#'
(#.....#)
I think this is enough help for you to get it done by yourself, should you require further assistance tho, just ask.
I have check it by gcc ,it works.Please see the notes in codeļ¼š
int main()
{
int width;
int breadth;
scanf("%d",&width);
scanf("%d",&breadth);
for(int i = 0; i < width; i++){
for(int j = 0; j < breadth; j++ ){
//first line and last line
if((i == 0)||i == (width - 1)){
printf("#");
//first column and last column
}else if((j == 0)||(j == (breadth -1))){
printf("#");
//other case
}else{
printf(".");
}
}
printf("\n");
}
return 0;
}
Using conditions as suggested by other answers is the ideal way but if that is unclear, you can break down the printing into smaller loops as
for (i=0; i<width; i++) // prints the first line
printf("#"); //
printf("\n"); //
for (j=0; j<breadth-2; j++){ // prints middle breadth-2 lines
printf("#"); // prints the starting hash in middle lines
for (i=0; i<width-2; i++) // prints the '.'s
printf(".");
printf("#\n"); // prints the last hash in middle lines
}
for (i=0; i<width; i++) // prints the last line
printf("#"); //
printf("\n"); //
Although not very efficient, the logic is very easy to understand.
Let me know if further explanation is required.
Edit: Actually after writing this answer I later realized that this code will infact be faster than the ones with branches. Since we have split the iteration domains ourselves, there are no branches. This reduces any chance of branch prediction failing, which would certainly happen in the solution with if conditions since the condition is true for small cases. Ofcourse it wouldn't matter for small iterations like 6x6, but just putting the thought out there.

Resources