rewrite c expression without continue and break - c

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.

Related

How to avoid entering strings already present in a list

In this piece of code I'm trying to check if a string (in my case the name of a club) is already entered from standard input. My goal is to avoid entering a name already present in the list, but it doesn't work.
Can someone help me please?
Thanks all.
gets(club[i].name);
if(i != 0){
for(left = 0; left < i; left++){
for(right = i; right > 0; right--){
outcome = strcmp(club[left].name, club[right].name);
if(outcome == 0){
printf("You already entered this team. Pick another one: \n");
gets(club[i].name);
}
}
}
}
i++;
break;
I'm not sure about the algo. (Besides, use fgets instead of gets)
You should compare against [i], not the other values.
This is simpler than the algo left/right:
int ok = 1;
for(int j = 0; j < i && ok ; j++){
ok = strcmp(club[j].name, club[i].name);
}
if ( ! ok) {
// ask again on the same 'i'
}
AFAIU, i is the last item, so j goes from 0 to i-1.
You don't need nested loops, because each input has already been checked against the previous ones. So when a new one comes, you only need to compare it with the previous values.
edit: If n is the number of items (item i is currently being input, but is not always the latest one), use that algo instead
int ok = 1;
for(int j = 0; j < n && ok ; j++){
ok = j == i || strcmp(club[j].name, club[i].name);
}
if ( ! ok) {
// ask again on the same 'i'
}
Just talk about your logic. Except for redundant comparisons, I think you need to reset the value of left and break inner loop.
Following your logic, the code should be:
gets(club[i].name);
if(i != 0){
for(left = 0; left < i; left++){
for(right = i; right > 0; right--){
outcome = strcmp(club[left].name, club[right].name);
if(outcome == 0){
printf("You already entered this team. Pick another one: \n");
gets(club[i].name);
left = 0;
break;
}
}
}
}
i++;
break;

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

Why does my C compiler skip the second scanf?

My Programm looks like this.
int main(){
int maxnote = 0;
int eingabewert;
int n = 0;
int userMarks[200];
ind promark;
printf("Welcome, plese enter your points, -1 to finish.\n");
while (eingabewert != -1){
scanf("%d", &eingabewert);
if(eingabewert < -1){
printf("A student can't have 0 > points.\n");
exit(0);
}
userMarks[counter] = eingabewert;
counter += 1;
}
printf("Please insert, the least pints needed for 6:");
//Second Scanf doesn't work, it stays in a Loop or something like that
scanf(" %d", &maxnote);
for(int i = 0; userMarks[i] != -1; i++){
userMarks[i] = berechneNote(userMarks[i], maxnote);
}
countMarks(userMarks);
notenstats(userMarks);
promark = ((suffmark/counter) * 100);
printStatistic(maxnote, promark);
}
The first Scanf() does it job perfectly and takes the given numbers.
However the second one isn't doing that.
It stays in a Loop and I can't go forward with my code.
What should I do to fix this?
Because you are using eingabewert uninitialized in
while (eingabewert != -1){
Initialize it with
int eingabewert = 0;
And always check the result of scanf
while ((eingabewert != -1) && (scanf("%d", &eingabewert) == 1))
You are also using userMarks uninitialized in
for(int i = 0; userMarks[i] != -1; i++){
In this case (an array) initialize it using
int userMarks[200] = {0};
There is a space in the format specifier in the second scanf. And you should learn how to use a debugger, like gdb. It's a lot faster than posting such a long question on SO.

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

Testing for inequality with while() in 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);
}

Resources