figuring out integer comparison in C - c

I'm just wondering how does boundary checking works in the following case.
#include <stdio.h>
#include <stdint.h>
int main(void)
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
for (int x = 0; x < 3; x++) {
printf("%d < %d < %d is %d\n", i, x, j, i < x < j);
}
}
}
return 0;
}
I tried right-to-left/left-to-right precedence but it doesn't seem to work. (not too sure about it though, maybe it does?)
I think this is undefined behaviour and using && would probably be easier than figuring this out but I'm quite interested in how the logic behind this works. Would appreciate if anyone could help explain this or point me towards the right direction
edit: Thanks for all the help! got the answer I needed. This must seem completely trivial to all of you but it really made many things I thought about in the past few days clicked. Really appreciate the time you guys took to help me out. Thanks again!

i < x < j is perfectly well-defined, but it doesn't do what you think it does.
It's equivalent to (i < x) < j, due to the associativity of <.
But (i < x) is either 0 or 1, as that's how the relational operators are defined in C.
So, for example, if j is greater than 1, then i < x < j is always 1.
Consider writing i < x && x < j instead.

Related

C - Pointer Arithmetic causing problems as opposed to standard [] way

I'm new to C and learning it for a class right now. We are currently working on a little project and we are supposed to use pointer arithmetic to access arrays as opposed to the standard [] way.
For some reason, I can use it just fine on the first loop (see code) but when I use it in the second, it doesn't produce the same outcome as if I were to use the standard [] way.
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int num = *(*array+i)+j;
//Irrelevant code
}
}
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int num = array[j][i]; // Error comes if I do *(*array+j)+i;
//Irrelevant code
}
}
I don't know if I am missing something here but why would calling the array using pointer arithmetic be different between the 2 loops?
The equivalence between subscripts and pointer notation is:
a[i] == *(a + i)
You are using (*a + i) in place of the correct *(a + i).
I believe your first set of loops should read:
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
int spot = *(*(board+i)+j);
for (int k = j + 1; k < size; k++) {
if (spot == *(*(board + i) + k) && spot > 0) {
return 0;
}
}
}
}
However, since you've not provided an MCVE (Minimal, Complete, Verifiable Example
— or MRE or whatever name SO now uses)
or an
SSCCE (Short, Self-Contained, Correct Example
— the same idea by a different name), I can't easily test the code.
Also, now you know why it is better to use the explicit subscript notation; it is a lot harder to get it wrong.

Beginning C Program

I was working though some beginning problem sets with Harvard's online CS50 class. I got the problem to work correctly but I was wondering if there would possibly be a cleaner or better way to get the program to work.
The goal of the program is to print a right-aligned pyramid comprised of hash-tags and space characters. Any guidance in regards to style or tricks would be very welcome.
/* Creating the mario program, whose goal is to create a
* pyramid by accepting input from the user to get the
* height then aligning the pyrimid to the right.
*
*/
#include <stdio.h>
#include <cs50.h>
int main(void)
{
// get user input and set to variable
printf("Height: ");
int height = GetInt();
int i, j, k;
for(i = 1 ; i < height; i++)
{
// create n-1 spaces
for(k = (height - 2); k > (i-1); k--)
{
printf("%c", ' ');
}
// create n+1 hash tags
for(j = 0; j < (i+1); j++)
{
printf("#");
}
printf("\n");
}
return 0;
}
I'm assuming by cleaner you mean "spiffy and fancyer".
This looks spiffy to me:
#include <stdio.h>
#include <cs50.h>
int main(void) {
// get user input and set to variable
printf("Height: ");
int height = GetInt();
int hm2 = height - 2;
int j, k;
for(int i = 1 ; i < height; i++) {
// create n-1 spaces
for(k = hm2; k > (i-1); k--)
printf("%c", ' ');
// create n+1 hash tags
for(j = 0; j < (i+1); j++)
printf("#");
printf("\n");
}
return 0;
}
However, don't get too caught up in making your code fancy. Although it's nice if you're working with others, or yourself really. Your example looked fine.
Now, optimization-wise, that's something to worry about. Just remember that too much optimization can potentially break your program.
For everyone's consideration: this is what "all style and no readability" looks like :)
i = 0;
while (i++ < height*height)
printf ("%c%s", (i-1)/height < height-(i-1)%height-1 ? ' ' : '#',
i % height ? "" : "\n");
It is nigh on impossible to see what the code does without running it. If there is to be a follow-up exercise, this is hard to re-write to form, say, an even-sided pyramid. I'd probably throw this away and start again with the basics, before concatenating it again into a little monster such as this.
(later) Ever so slightly more neat to put the i++ at the end, so two times (i-1) gets traded for a slightly more complicated end-of-line test:
i = 0;
do
printf ("%c%s", i/height < height-i%height-1 ? ' ' : '#',
i % height==height-1 ? "\n" : "");
while (++i < height*height);
I think by cleaner and better way you mean to be a perfect shaped right angled triangle pyramid.
For this you should do as
Change
printf("Height: ");
to
printf("Height: \n\n");
and
for(i = 1 ; i < height; i++)
to
for(i = 0 ; i < height; i++)
And see the sample output.
Here's a suggestion:
#include <stdio.h>
#include <cs50.h>
int main(void) {
//initialize variables
int height, hm2, j, k, i;
printf("Height: \n");
// Get user input
height = GetInt();
hm2 = height - 1;
for(i = 0; i < height; i++) {
// create n spaces
for(k = hm2; k > i; k--)
printf("%c", ' ');
// create n+1 hash tags
for(j = 0; j < i+1; j++)
printf("#");
printf("\n");
}
return 0;
}
Result if the user entered a 5 for the height:
Height:
#
##
###
####
#####
A couple things I considered with this version of the code:
-In C, it's good practice to declare all variables separately from giving them a value and assign values later. Some compilers may bring up this error if you to declare and assign a value in a for loop: "error: ‘for’ loop initial declarations are only allowed in C99 mode". These changes are considered with what I have provided.
//initialize variables
int height, hm2, j, k, i;
-I added a newline here
printf("Height: \n");
-Instead of hm2 = height - 2 I changed it to:
hm2 = height - 1;
-First loop, now we give i a value and set it to 0 to meet the other changes that were made:
for(i = 0; i < height; i++) {
-For the loop creating n spaces I changed it to:
for(k = hm2; k > i; k--)
-Finally removed parenthesis (no need in this case) in last for loop:
for(j = 0; j < i+1; j++)
Cheers

How to remove characters from console output in C

Code1:
#include<stdio.h>
int main()
{
unsigned short i, j, k;
for (i = 0; i < 2; i++)
{
k = i * 4 + 4;
for (j = k - 4; j < k; j++)
printf("%hu ", j);
putchar('\n');
}
return 0;
}
Output of Code1:
0 1 2 3
4 5 6 7
Remarks of Code1:
Space after 3 and 7
Newline after 7 (Stackoverflow has removed it)
Code2:
#include<stdio.h>
int main()
{
unsigned short i, j, k;
for (i = 0; i < 2; i++)
{
k = i * 4 + 4;
for (j = k - 4; j < k; j++)
{
printf("%hu", j);
if (j + 1 != k) putchar(' ');
}
if (i + 1 != 2) putchar('\n');
}
return 0;
}
Output of Code2:
0 1 2 3
4 5 6 7
Remarks of Code2:
No space after 3 and 7
No newline after 7
Additional remark of Code2:
The problem of Code2 is that the algorithm always compares two values in the if blocks and so Code2 is not efficient. I want to use Code1 and change these:
Code3
#include<stdio.h>
int main()
{
unsigned short i, j, k;
for (i = 0; i < 2; i++)
{
k = i * 4 + 4;
for (j = k - 4; j < k; j++)
printf("%hu ", j);
printf("\b\n");
}
putchar('\b');
return 0;
}
These do not show the same output of Code2 because \b does not erase anything.
My question:
Is there any standard way to do so what I've tried in Code3?
Remark of my question:
I have searched the internet but have not determined the solution.
Edit the question if it is not clear.
Edit: I don't know why my question is not useful or constructive. Though the above is an arbitrary small example, but performance might be an issue when processing very large amount of data. I thought that the way of removing character from console output might improve performance and there might be a specific way to do so. That's why I've asked the question. I could write the following codes in the answers. Now I've known via comments that removing character from console output is not possible because it is implementation dependent.
The usual approach to this is to treat either the first or the last printf as a special case (outside of the loop):
for(ii=0; ii<2; ii++) {
jj = 0;
printf("%d", jj); // first number printed without space.
for(jj=1; jj<4; jj++) {
printf(" %d", jj); // include the space before the number printed
}
if(ii<2-1) printf("\n");
}
Obviously I simplified how the loops are constructed and what is printed - for simplicity. You could make the first printf statement
printf("\n%d", jj);
then you have a newline at the start of your output (often a good thing) and then you don't need the if statement later - you just don't have a newline printed at the end of the line (because it will be printed at the start...)
There are marginally more efficient ways of doing this that would involve no if statements at all - but these all come at the expense of less readable code. For example, here is a "no loop unrolling and no additional if statements" version of the code:
http://codepad.org/01qPPtee
#include <stdio.h>
int main(void) {
int ii, jj;
ii = 0;
while(1) {
jj = 0;
while(1) {
printf("%d", jj); // include the space before the number printed
jj++;
if(jj<4) printf("."); else break;
}
ii++;
if(ii<2) printf("*\n"); else break;
}
return 0;
}
Output:
0.1.2.3*
0.1.2.3
Basically I have taken the functionality of the for loop and made it explicit; I also use a . rather than a and "*\n" rather than "\n" to show in the printout that things behave as expected.
It does what you asked without extra evaluation of the condition. Is it more readable? Not really...
If it really bothers you, you can unroll your loops a little so that you treat the last item as a special case:
#include<stdio.h>
int main()
{
unsigned short i, j, k;
for (i = 0; i < 1; i++)
{
k = i * 4 + 4;
for (j = k - 4; j < k - 1; j++)
{
printf("%hu ", j);
}
printf("%hu\n", j);
}
k = i * 4 + 4;
for (j = k - 4; j < k - 1; j++)
{
printf("%hu ", j);
}
printf("%hu", j);
return 0;
}
#include <stdio.h>
int main(){
unsigned short num = 0, to=8;
while(num < to){
printf("%hu", num++);
if(num < to)
putchar(num % 4 == 0 ? '\n' : ' ');
}
#if 0
do{
printf("%hu", num++);
}while(num < to && putchar(num % 4 == 0 ? '\n' : ' '));
#endif
return 0 ;
}
Well, to try to answer your question, here's how I would do it:
for (i = k = 0; i < 2; i++){
if (i > 0) printf("\n");
for (j = 0; j < 4; j++, k++){
if (j > 0) printf(" ");
printf("%d", k);
}
}
I do it this way because I want to be sure every line but the first starts with a \n, and every item is separated by a space from the one before it.
Also, I do not want the row and column position to be intimately tied to the content of what is being printed.
In terms of performance, keep in mind that these if statements cost about 1 cycle, while each character printed costs at least hundreds if not thousands. printf goes through many layers of system calls to interpret its format string, build a buffer, send the buffer to the system I/O routines, which then cause repainting and scrolling of the console window. Get the idea?
DO NOT WORRY about performance unless you know you have a problem.
Then, don't guess. Use a diagnostic. Here's what I do.

for loop in C/C++

I have for loop doubt that I need to ask .
once i saw in coding something like
for(i = 0; i<10; i+)
My doubt is why &when in for loop we use say i+ or i- rather than i++ or i--
Thanks in advance
It won't work, doesn't the compiler return an error if you do? ( or atleast a warning.. )
Just use ++i or i++
Using i+ instead of i++ should not work. As I think you know, i++ increases the value of i by one. When the compiler sees i+, it is expecting something after the +, which causes it to not compile.
The line in question is not valid C
for(i = 0; i<10; i+)
Some valid, equivalent (between themselves) options are
for(i = 0; i < 10; i++)
for(i = 0; i < 10; ++i)
for(i = 0; i < 10; i += 1)
for(i = 0; i < 10; ) { /*...*/ i++; }
You cannot use i+ or i- because if doesn’t work i.e doesn’t increase or decrease value of i for increment you have may use i++,++i,i+=1,i=i+1 and for decrement you can use these by changing sign to negtive

Fixing a broken loop by changing exactly one character

Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
I found a site with some complicated C puzzles. Right now I'm dealing with this:
The following is a piece of C code, whose intention was to print a minus sign 20 times. But you can notice that, it doesn't work.
#include <stdio.h>
int main()
{
int i;
int n = 20;
for( i = 0; i < n; i-- )
printf("-");
return 0;
}
Well fixing the above code is straight-forward. To make the problem interesting, you have to fix the above code, by changing exactly one character. There are three known solutions. See if you can get all those three.
I cannot figure out how to solve. I know that it can be fixed by changing -- to ++, but I can't figure out what single character to change to make it work.
Here is one solution:
for( i = 0; -i < n; i-- )
printf("-");
Here is a second one, thanks to Mark for helping me!
for( i = 0; i + n; i-- )
printf("-");
And Mark also had the third one which is
for( i = 0; i < n; n-- )
printf("-");
Change i-- to n-- is another.
Okay - Gab made the fix, so I removed the other solution. He wins!
Third answer:
for( i = 0; i + n; i-- )
printf("-");
Thanks to Gab Royer for inspiration.
Explanation: Eventually , i + n will result in -20 + 20 = 0 which is false.
for( i = 0; i < n; n-- )
printf("-");
Changed i-- to n--
Here's one of them, I think:
for( i = 0; i < n; n-- )
The comparison in the for loop can be any expression - you can negate i.
for (i = 0; -i < n ; i--)
Solution 1
#include <stdio.h>
int main()
{
int i;
int n = 20;
for( i = 0; i < n; n-- ) // Change i-- to n--
printf("-");
return 0;
}
Solution 2
#include <stdio.h>
int main()
{
int i;
int n = 20;
for( i = 0; -i < n; i-- ) // Compare to -i
printf("-");
return 0;
}
Haven't figured a third.
Here is another one:
#include <stdio.h>
int main()
{
int i;
int n = -20; //make n negative
for( i = 0; i < n; i-- )
printf("-");
return 0;
}

Resources