Testing for inequality with while() in C - c

I am new to C programming. I want to use a while loop to check for the number 500.00 in a line of the 'grid' matrix and to go to the next line if it's not there. For this purpose I wrote this program, but unfortunately it doesn't show any results and I don't know what the problem is.
The program that I have written is here:
for(i=0;i<12;i++){
c=0;
for (j=0;j<26;j++){
while(grid[i][j]!=500.00 && c<=ncmax );
c++;
}
printf("%d \n \n",c);
}
I changed the while loop to
while(&grid[i][j]!=500.00 && c<=ncmax );
but it shows these errors
error C2440: '!=' : cannot convert from 'double' to 'float *'
error C2446: '!=' : no conversion from 'double' to 'float *'
What should I do with this problem? In general, am i able to use the while loop like this?
If you need to see the whole program please let me know.

You have a while loop that doesn't do anything, and I suspect it's redundant as well. Look at it carefully; note how it checks for something, but if that something is not found, it doesn't do anything to change the state of affairs. Also look at your semi-colon; that's basically the body of your loop now.
I suspect you want to actually put the check inside your second for-statement or turn that for-statement into a while loop.

I don't understand your while. Don't you want a if instead?
for(i=0;i<12;i++) {
c=0;
for (j=0;j<26;j++) {
if(grid[i][j]!=500.00 && c<=ncmax) {
c++;
} else {
printf("%d \n \n",c);
}
}
}
But I think you could go for something simpler:
for(i=0;i<12;i++) {
for (j=0;j<26;j++) {
if(grid[i][j]==500.00) {
printf("%d %d \n \n",i , j);
}
}
}
EDIT:
I just noticed that in the first program, c and j have the same value. You could simplify to:
for(i=0;i<12;i++) {
c=0;
while(c<26 && c<=ncmax && grid[i][c]!=500.00) {
c++;
}
printf("%d \n \n",c);
}
The output should be the list of c. It is equals to the minimum of 26 or ncmax+1 or the index of the value 500.00 in the line i.
PS: If you know the value of ncmax, you could simplify the condition.

Let's take a closer look at what your code is doing, and then what I think you want it to do. I've changed the whitespace and indenting to make it more readable.
for (i = 0; i < 12; i++) { /* each column */
c = 0;
for (j = 0; j < 26; j++) { /* each row in this column */
while(grid[i][j] != 500.00 && c <= ncmax)
; /* this is the body of the while loop: do nothing */
c++;
}
printf("%d \n \n",c);
}
Since the body of the while loop does nothing, then if both conditions are true when entering the loop, it will continue to loop forever. You have probably already discovered this.
If your goal is to count the number of values in each column that are equal to 500.0, but stop counting if you reach a maximum number, consider the following approach.
for (i = 0; i < 12; i++) { /* each column */
c = 0;
for (j = 0; j < 26 && c <= ncmax; j++) { /* each row */
if (grid[i][j] == 500.0)
c++;
}
print("%d\n\n", c);
}
By the way, you need to be careful about comparing a float or double for equality. It's better to use closeness.
if (abs(grid[i][j] - 500.0) < EPSILON)
c++; /* value is "close enough" */
EDIT Fix minor indenting typo. Populate body of last code block.
EDIT #2 If the goal is to find where the 500.0 occurs in each column, then the inner loop can be changed to a while loop as follows, while eliminating a variable.
for (i = 0; i < 12; i++) { /* each column */
j = 0;
while (j < 26 && grid[i][j] != 500.0)
j++; /* each row this column, or until 500.0 */
if (j == 26)
print("ERROR: sentinel missing in column %d\n", i)
else
print("%d\n\n", j);
}

Related

Can't I get the output in the image more easily with the help of a nested for loop in C?

int i,j,k;
int sayi=1;
for(i=1; i<=sayi; i+=2){
printf("%d",i);
printf("a");
printf("%d",i+2);
printf("a");
printf("%d",i+4);
printf("a");
printf("\n");
for(j=1; j<=sayi; j+=2)
printf("%d",i);
printf("a");
printf("%d",i+2);
printf("a");
printf("%d",i+4);
printf("\n");
for(k=1; k<=sayi; k+=2)
printf("%d",i);
printf("a");
printf("%d",i+2);
printf("a");
printf("\n");
printf("%d",i);
printf("a");
printf("%d",i+2);
printf("\n");
printf("%d",i);
printf("a");
printf("\n");
printf("%d",i);
}
I need to add the letter 'a' between the numbers as the numbers move in the form of 1-3-5 consecutively. I'm trying to get the output on the screen with nested for loops. But I think it's much shorter bit path than my method how can I do it?
You are already using nested for loops. Unfortunately, you aren't using them correctly.
for(j=1; j<=sayi; j+=2)
for(k=1; k<=sayi; k+=2)
These are both nested within the "for(i=1; i<=sayi; i+=2)" because of your brackets, { and }. These inner loops only have one line within them because you aren't using brackets to define where they start and end, so the compiler's rules automatically defaults to them consisting of only the one valid line of code following the loop.
None of the 3 loops you have in your example are actually running as loops because you aren't incrementing the "sayi" variable and it being 1. When you assign "i", "j", and "k" to 1 also, and compare that to "sayi" with a "less than or equal" comparison, they run because it's true, but then when you increment the loop variables by 2, they become 3 and the "less than or equal to" comparison fails, so the loop is only run once.
In order to shorten this, you'll need to learn quite a few things:
The if statement is a major piece of this. https://www.cprogramming.com/tutorial/c/lesson2.html
How loops actually work. https://www.freecodecamp.org/news/for-loops-in-c/
Mathematical, assignment, and conditional operators. https://www.programiz.com/c-programming/c-operators
The links I gave are just suggested starting points. There's more to learn than just that. I don't have any connection to those sites or people putting them out. They are simply the best of the first search results I looked at.
Here's my version of the code you are trying to write.
int start = 6;
for (int i = start; i > 0; i--)
{
for (int j = 1; j <= i; j++)
{
if (j % 2 == 1)
{
printf("%d", j);
}
else
{
printf("a");
}
}
printf("\n");
}
To be certain, this can be reduced further, but I think this is a good enough starting point for you.
This should work. I put in some comments explaining it.
#include <stdio.h>
int main() {
//up to what number do you want it to go
int n = 5;
for (int i = n; i > 0; i--) { //loops over every line you need to print with i being the length of that line minus 1. I starts at n and ends at 0
for (int j = 1; j <= i; j++) { // loops over every number in that particular line, starting from 1 up to i.
if (j % 2) { //if j is even it prints 'a', otherwise it prints the number
printf("%d", j);
} else {
printf("a");
}
}
printf("\n");
}
}

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;
}

Terminate an array input taking when input is -1 without using break?

I am taking input in an array of length 100 using scanf in a loop. After 20 numbers, if I enter -1, I want the loop to exit, i.e finish taking input and continue with the rest of the program. I am doing something like this
for(i=0;i<100;i++)
{
scanf("%d", &input[i]);
if(input[i] == -1)
{
break;
}
}
I heard, it is bad practice to use break statements even though this code works perfectly fine. So I was wondering what is a more efficient way to end the loop when -1 is entered. I tried
for(i=0;scanf("%d",&input[i])!=-1;i++)
also
fori(i=0;i<100;i++){
do
{scanf("%d", &input[i]);
}while(input[i]!=-1
}
Neither of these don't work
The second expression of the for loop is a free-form boolean expression. In this case you could add your condition there. However in this case it wouldn't look exactly nice. For example
for(i=0; i < 100 && (i < 1 || input[i - 1] != -1); i++)
{
scanf("%d", &input[i]);
}
I.e. if we have already input one value, check the value and that must be inequal to -1 for the loop to continue
Another would be to use a synthetic flag variable:
int loop_again = 1;
for (i = 0; loop_again && i < 100; i++) {
scanf("%d", &input[i]);
if(input[i] == -1)
{
loop_again = 0;
}
}
All in all, these both look way uglier than just using the break statement for the very thing that it was invented for.
Note that you also should check the return value of scanf itself!
it is bad practice to use break statements
As Ancient Greeks said, "Pan Metron Ariston", which means that everything that is used with balance is great. This applies here too, and your code as is, is good to go. The only thing to be worried about is not checking the return value of scanf().
Now if you really insist on changing your approach, then please refer to Haapala's answer, we got there first.
You can use a while loop and check for -1 in the input in the loop conditional. Note that you should always check the value returned by scanf(). In the posted code, non-numeric input results in no value being stored in input[]; this may lead to undefined behavior later if the code attempts to use an indeterminate value.
Here is an example. Note that the loop conditional first checks whether the array index has grown too large, then checks the return value from scanf() to be sure that a number was entered, then checks to see if -1 was entered. In the case of non-numeric input, the loop is terminated.
#include <stdio.h>
#define INPUT_SZ 100
int main(void)
{
int input[INPUT_SZ];
size_t i = 0;
while (i < INPUT_SZ && scanf("%d", &input[i]) == 1 && input[i] != -1) {
++i;
}
puts("You entered:");
for (size_t j = 0; j < i; j++) {
printf("%d\n", input[j]);
}
return 0;
}
Sample interaction:
2 4 6 8 -1
You entered:
2
4
6
8
You can simply change the value of counter variable to max, then it'll automatically come out of loop.
#include<stdio.h>
#define MAX 10
int main()
{
int ar[MAX], i, count;
for(i=0; i<MAX; i++)
{
scanf("%d", &ar[i]);
if(ar[i]==-1)
{
count=i--; //this is your new MAX. Not mandatory but will be useful if you need to access array elements
i=MAX;
}
}
//printing array
for(i=0; i<count; i++)
{
printf("Element %d: %d\t", i+1, ar[i]);
}
return 0;
}
Hope this helps.
Use a do-while loop
int i=0;
do{
if(scanf("%d", &input[i++]) != 1)
{
if(i>0)
--i; // Decrementing i if an integer is not provided
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) // Wasting the buffer
;
}
}while(input[i-1] != -1 && i<=99);

Printing Word Length Histogram in C

Okay so I'm using Kernighan and Ritchie's "The C Programming Language" and I'm on exercise 1.13 and I can't seem to get this right. My program seems to not be printing much. The problem is as follows:
Exercise 1-13. Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with
the bars horizontal; a vertical orientation is more challenging.
Besides the creation of variables, here's my pseudocode for reading the input and storing what I want to store in the array.
Create an array -- in this case, my array is of size 21 (21 elements, from 0 to 20) all assigned a value of 0 initially. It has 21 elements because I'm not going to use words that have more than 20 characters. I realize this is weird given no words have zero characters.
Begin counting characters in input.
If I encounter a space, tab, or newline character (i.e., this means the first word ended), stop.
Depending on how many characters the word had, increment that particular position in the array (i.e., if the word had two characters add 1 to the element at position 2 in the array).
Increment the wordCounter variable -- this variable as it's name indicates keeps track of the number of words that have been "read" in the input.
Continue doing this to each word until EOF is reached.
Here's my pseudocode for printing the histogram (horizontally).
For the first position, print the value stored in the first position of the array (i.e., 0) using tick marks |
Do this for every element in the array.
Here's my code:
#include <stdio.h>
#define SIZEOFWORDSOFLENGTH 21
int main() {
int wordsOfLength[SIZEOFWORDSOFLENGTH];
int c, i, j;
int lengthCounter = 0;
/*Initializing all array elements to 0.*/
for (i = 0; i < SIZEOFWORDSOFLENGTH; i++)
wordsOfLength[i] = 0;
/*Going through the input and counting.*/
while ((c = getchar()) != EOF) {
++lengthCounter;
if (c == ' ' || c == '\t' || c == '\n') {
++wordsOfLength[lengthCounter - 1];
lengthCounter = 0;
}
}
for (i = 0; i < SIZZEOFWORDSOFLENGTH; i++) {
printf("Words of Length %d: ", i);
/*The third argument of the following for loop was previously j = j*/
for (j = 0; j < SIZEOFWORDSOFLENGTH; j++) {
while (j < wordsOfLength[i]) {
printf("|");
/*Was previously j++ instead of break*/
break;
}
}
printf("\n");
}
}
I debugged it by hand but I can't seem to find the problem. Maybe something really simple is going over my head. Also, I know this question has been asked before but I'm not trying to find a solution for the actual problem, I think my pseudocode is right if not somewhat right, I just want to know what's wrong with my code and maybe learn something. Thank you in advance.
As indicated in Ji-Young Park's answer, the reading loop has problems because it uses negative indexes into the array wordsOfLength. I would keep life simple and have wordsOfLength[i] store the number of words of length i, though it effectively wastes wordsOfLength[0]. I would use the macros from <ctype.h> to spot word boundaries, and I'd keep a record of whether I was in a word or not. You get credit for using int c.
int inword = 0;
while ((c = getchar()) != EOF)
{
if (!isspace(c))
lengthCounter++;
else if (inword)
{
wordsOfLength[lengthCounter]++;
lengthCounter = 0;
inword = 0;
}
}
if (inword)
wordsOfLength[lengthCounter]++;
This code is not bamboozled by leading white space in the file. If you think there's any risk of reading 'antidisestablishmentarianism' (28) or 'floccinaucinihilipilification' (29) or other grotesquely long words, you should check on lengthCounter before blindly using it as an index, either dropping overlong words from the count or mapping them all to '20+ characters' class.
Your final triple loop is quite problematic too — it is currently:
for (i = 0; i < SIZZEOFWORDSOFLENGTH; i++) {
printf("Words of Length %d: ", i);
/*The third argument of the following for loop was previously j = j*/
for (j = 0; j < SIZEOFWORDSOFLENGTH; j++) {
while (j < wordsOfLength[i]) {
printf("|");
/*Was previously j++ instead of break*/
break;
}
}
printf("\n");
}
Under my scheme, I'd start with i = 1, but that isn't a major issue. I'd ensure that the first printf() printed for 2 digits to align the output for the counts of words of lengths 10-20.
The inner for loop should be constrained by wordsOfLength[i] rather than SIZEOFWORDSOFLENGTH, and the while loop is redundant (not least because you break it on the first iteration each time). You just need simple nested for loops:
for (i = 1; i < SIZZEOFWORDSOFLENGTH; i++)
{
printf("Words of Length %2d: ", i);
for (j = 0; j < wordsOfLength[i]; j++)
printf("|");
printf("\n");
}
The only issue now is if the maximum value in wordsOfLength is too long for comfort (for example, you've read the entire works of Shakespeare, so some of the words appear thousands of times).
you don't need to substract '1' from lengthCounter in
++wordsOfLength[lengthCounter - '1'];
It should be
++wordsOfLength[lengthCounter];

rewrite c expression without continue and break

In a school exercise (on paper) i've this question:
5) rewrite the code without using continue and break:
for (i = 0; i < N; i++) {
scanf("give me an int %d", & a);
if (a < 0) {
continue;
}
if (a == 0) {
break;
}
/* elaborate positive int */
}
I'm thinking about this:
for(i=0;i<N;i++){
scanf("give me an int %d",&a");
if(a==0){return -1; //??i dont know how to exit}
if(a<0){
do{
scanf("give me an int %d",&a");
if(a==0){return -1; //??i dont know how to exit}
}while(!(a<0))
}
/* elaborate positive int */
}
but, I'm actually not able to do this.. can you help me? thanks :)
Might not be what your teacher wants but that's actually the easiest way:
a = INT_MAX;
for(i = 0; i < N && a != 0; i++) {
scanf("give me an int %d", &a);
if(a > 0) {
/* elaborate positive int */
}
}
The reason for not using return is that you just want to exit/restart the loop. The function could contain more stuff that should not be skipped.
And that scanf call looks wrong.. do you really want to enter "give me an int .." everytime?
for(i = 0; i < N && a != 0; i++)
{
scanf("give me an int %d",&a");
if(a>0)
{ /*do stuff*/ }
}
if(a==0) i--; //As noted by Daniel Fischer
Not going to give you full code, but:
remember you can add conditions inside the clause of the for statement. (hint: move the breaking condition there to terminate the loop)
does the continue actually do anything in your example?
In this specific case, not much needs to be done. Since a < 0 and a == 0 are mutually exclusive conditions, an if-else-if statement could be used as follows:
for (i = 0; i < N; i++)
{
scanf("give me and int %d", &a);
if (a < 0)
// Do something or nothing here, but this skips the rest of the loop
// body just like continue would.
else if (a == 0)
i = N; // This satisfies the loop condition, so it won't loop again
// just like break would.
}
This is not a general solution, but it should give you the proper behavior in this case.

Resources