How to stop infinite looping the output? - c

I have code with a function that returns the biggest digit from a number. The requirement is to enter numbers until something that is not a number is entered. When something that isn't a number is entered, the program is supposed to stop, but in my case it just starts an infinite loop that prints the last result that the function returned. Here is the code:
#include <stdio.h>
int maxDigit(int n){
int temp = n, maxDig = 0;
while(temp){
int digit = temp % 10;
if(digit > maxDig){
maxDig = digit;
}
temp /= 10;
}
return maxDig;
}
int main()
{
int n = 1, broj;
while(n){
if(scanf("%d", &broj));
printf("%d\n", maxDigit(broj));
}
return 0;
}
What might be the problem?

You can look at the return value of scanf to see if you read a valid integer, and you can use break to terminate your loop. The n variable in your main function just had a constant value so I got rid of it, and cleaned up the function in a few other ways. Here is my resulting code:
...
int main() {
while (1) {
int input;
if (scanf("%d", &input) != 1) { break; }
printf("%d\n", maxDigit(input));
}
}

Related

How to create a function in C that prompts the user for positive integers only and call it in the main function?

This is my code. I failed to use the break keyword after the printf function in order to break out of the loop. When I enter a negative number or zero, it doesn't prompt me again to re-enter.
#include <stdio.h>
#include <cs50.h>
int get_positive_int(void);
int main (void)
{
get_positive_int();
}
int get_positive_int(void)
{
int i;
i = get_int("Integer: ");
while (true)
{
if (i<1)
{
return i;
}
else
{
printf("%i", i);
}
}
}
The algorithm in the function get_positive_int() is wrong:
You need to place i = get_int("Integer: "); inside of the while loop.
Your if condition:
if (i < 1)
is wrong as that would return i if i is a negative integer or 0. If you want to return i when i is a positive integer or 0 you should use if(i >= 0).
Note that you can also place:
if (i == INT_MAX)
{
// optional error handling.
return INT_MAX;
}
after the call to maintain the occurrence of a read error. But if you want to only return INT_MAX then, you do not need to do so and can omit it since this would fit to the conditional statement ``if(i >= 0)` and its body.
The code is then:
int get_positive_int(void)
{
int i;
while (true)
{
i = get_int("Integer: ");
if (i == INT_MAX)
{
// optional error handling.
return INT_MAX;
}
else if (i >= 0)
{
return i;
}
printf("%i", i);
}
}
Side note: If you don´t want to count 0 as positive integer, you need to have i >= 1 as the condition of the if statement.
As you said in the comments you only want to continue if i is a positive integer and exit if i is a negative characters or 0:
void get_positive_int(void)
{
int i;
while (true)
{
i = get_int("Integer: ");
if (i < 1)
{
return;
}
printf("%i\n", i);
}
}
Note that in this case, the return type of get_positive_int shall be void instead of int and it should omit to return i as it is not necessary to return any value from the function.

scanf confusion with type error

I just make a program to guess some random pairs in an array,if guess right, delete this pair.
I met a problem that I can only type integer number.Everytime I tried to type like * ,the program will crash. I use a condition like:
if (scanf("%d",&temp)==1)
to try to fix my problem, but it really does'nt work.
here is my code and please give me some help:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int r[4]; //random
int s[8]; //store
char c[8]; //cover
int g[8]; //guess
int i;
int round=0;
int left = 4;
int point = 0;
int clear_index[2];
int temp;
// generate random number
for (i=0;i<4;i++)
{
r[i] = (rand()%10)+1;
s[i] = r[i];
s[i+4] = r[i];
}
// show the default number
printf("[show] ");
for (i=0;i<8;i++)
{
printf("%d ",s[i]);
c[i] = '*';
}
printf("\n");
while(left>0)
{
// print left
printf("[cover] ");
for (i=0;i<8;i++)
printf("%c ",c[i]);
printf("\n");
//guess
printf("[guess] ");
for(i=0;i<8;i++)
{
if (scanf("%d",&temp)==1)
g[i] = temp;
if (g[i] == s[i])
{
printf("v\n");
clear_index[point] = i;
point++;
}
}
if (point == 2)
{
for (i=0;i<2;i++)
c[clear_index[i]]=' ';
left-=1;
point = 0;
}
round+=1;
//left-=1;
}
printf("you won in %d round",round);
}
You get the segmentation fault, because, in case, you did not enter an integer, scanf will not return 1, and then, using g[i] will invoke undefined behavior.
FWIW, g is a local automatic array variable, and unless initialized explicitly, will have indeterminate value. Attempt to read the value will invoke the UB.
Solution:
Always initialize the local variables.
In case scanf() fails, you need to eat up the invalid input using some loop like while (getchar != '\n'); before you proceed to take the next input.
You are reading a number but the user can place a digit. To prevent this you can use the function atoi() from the library stdlib.h. It converts a string to a integer, if the integer is just number digits, it'll convert it to a integer. If it is a character it will return 0. So you just need to prevent the occurrence of a 0 after the atoi() function is called.

Check vowels occurence in a string

This is the problem I'm trying to solve:
Input:
First line contains N, the size of the string.
Second line contains the letters (only lowercase).
Output:
Print YES if all vowels are found in the string, NO otherwise.
Constraints:
The size of the string will not be greater than 10,000. 1 ≤ N ≤ 10000
The following code I wrote is always showing NO.
#include <stdio.h>
#include<conio.h>
int main()
{
int a,b,c=0,d=0,e=0,f=0,g=0,i;
char string[10000];
scanf("%d",&a);
scanf("%s",string);
for(i=0;i<a;a++)
{
if(string[i]==('a'))
c=1;
if(string[i]==('e'))
d=1;
if(string[i]==('i'))
e=1;
if(string[i]==('o'))
f=1;
if(string[i]==('u'))
g=1;
}
if((c==1)&&(d==1)&&(e==1)&&(f==1)&&(g==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Here is an infinite loop that causes a problem:
for(i=0;i<a;a++)
You should increment i, instead of a (length of a string). If you fix this one char in loop statement, the program will run well at all. Anyway, I changed your code a bit to be more readable. Take a look if you want, just for your information, sir:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int len, a=0, e=0, i=0, o=0, u=0, it;
char string[10000];
scanf("%d", &len);
scanf("%s", string);
for(it=0;it<len;it++)
{
if(string[it]=='a') a = 1;
else if(string[it]=='e') e = 1;
else if(string[it]=='i') i = 1;
else if(string[it]=='o') o = 1;
else if(string[it]=='u') u = 1;
}
if(a && e && i && o && u) printf("YES\n");
else printf("NO\n");
system("PAUSE");
return 0;
}
I assume you are running your program under Windows, so instead of conio's getch() try to use system("PAUSE") or just even better way to do this (for both Windows for UNIX): getchar()
I've renamed all of your variables, but otherwise left the code the same.
#include <stdio.h>
#include<conio.h>
int main()
{
int foundA = 0, foundE = 0, foundI = 0, foundO = 0, foundU = 0;
int i, length;
char string[10000];
scanf("%d", &length);
scanf("%s", string);
for(i=0; i<length; length++)
{
if(string[i]==('a'))
foundA=1;
else if(string[i]==('e'))
foundE=1;
else if(string[i]==('i'))
foundI=1;
else if(string[i]==('o'))
foundO=1;
else if(string[i]==('u'))
foundU=1;
}
if((foundA==1)&&(foundE==1)&&(foundI==1)&&(foundO==1)&&(foundU==1))
printf("YES");
else
printf("NO");
return 0;
getch ();
}
Looking the the for-loop condition for(i=0; i<length; length++), I think it's pretty clear what's wrong. Instead of incrementing the counter, you're incrementing the length of the string. Eventually, the counter overflows to a negative number, and the loop terminates without ever looking at a character besides the first one. The lesson here is to name your variables properly.
If you want to be picky, then signed integer overflow is undefined behavior, but for most systems, INT_MAX + 1 will be INT_MIN.
This program can be done in more simpler way other as below.
#include <stdio.h>
#include<conio.h>
int main()
{
int i, flag = 0;
char string[10000], *ptr;
char cmp[] = "aeiou";
printf("Please enter string = " );
scanf("%s", string);
i = 0;
while(cmp[i])
{
ptr = string;
while(*ptr)
{
if(cmp[i] == *ptr)
break;
ptr++;
}
if(*ptr != cmp[i++])
{
flag = 1;
break;
}
}
if(flag == 1)
printf("NO");
else
printf("YES");
}
In this program I have used just one flag instead of 5 flags. Always try to write simple code rather then using unnecessary variable and flags.

How to show the digits which were repeated in c?

The question is that show the digits which were repeated in C.
So I wrote this:
#include<stdio.h>
#include<stdbool.h>
int main(void){
bool number[10] = { false };
int digit;
long n;
printf("Enter a number: ");
scanf("%ld", &n);
printf("Repeated digit(s): ");
while (n > 0)
{
digit = n % 10;
if (number[digit] == true)
{
printf("%d ", digit);
}
number[digit] = true;
n /= 10;
}
return 0;
}
But it will show the repeated digits again and again
(ex. input: 55544 output: 455)
I revised it:
#include<stdio.h>
int main(void){
int number[10] = { 0 };
int digit;
long n;
printf("Enter a number: ");
scanf("%ld", &n);
printf("Repeated digit(s): ");
while (n > 0)
{
digit = n % 10;
if (number[digit] == 1)
{
printf("%d ", digit);
number[digit] = 2;
}
else if (number[digit] == 2)
break;
else number[digit] = 1;
n /= 10;
}
return 0;
}
It works!
However, I want to know how to do if I need to use boolean (true false), or some more efficient way?
To make your first version work, you'll need to keep track of two things:
Have you already seen this digit? (To detect duplicates)
Have you already printed it out? (To only output duplicates once)
So something like:
bool seen[10] = { false };
bool output[10] = { false };
// [...]
digit = ...;
if (seen[digit]) {
if (output[digit])) {
// duplicate, but we already printed it
} else {
// need to print it and set output to true
}
} else {
// set seen to true
}
(Once you've got that working, you can simplify the ifs. Only one is needed if you combine the two tests.)
Your second version is nearly there, but too complex. All you need to do is:
Add one to the counter for that digit every time you see it
Print the number only if the counter is exactly two.
digit = ...;
counter[digit]++;
if (counter[digit] == 2) {
// this is the second time we see this digit
// so print it out
}
n = ...;
Side benefit is that you get the count for each digit at the end.
Your second version code is not correct. You should yourself figured it out where are you wrong. You can try the below code to print the repeated elements.
#include<stdio.h>
int main(void){
int number[10] = { 0 };
int digit;
long n;
printf("Enter a number: ");
scanf("%ld", &n);
printf("Repeated digit(s): ");
while (n > 0)
{
digit = n % 10;
if (number[digit] > 0)
{
number[digit]++;;
}
else if (number[digit] ==0 )
number[digit] = 1;
n /= 10;
}
int i=0;
for(;i<10; i++){
if(number[i]>0)
printf("%d ", i);
}
return 0;
}
In case you want to print the repeated element using bool array (first version) then it will print the elements number of times elements occur-1 times and in reverse order because you are detaching the digits from the end of number , as you are seeing in your first version code output. In case you want to print only once then you have to use int array as in above code.
It is probably much easier to handle all the input as strings:
#include <stdio.h>
#include <string.h>
int main (void) {
char str[256] = { 0 }; /* string to read */
char rep[256] = { 0 }; /* string to hold repeated digits */
int ri = 0; /* repeated digit index */
char *p = str; /* pointer to use with str */
printf ("\nEnter a number: ");
scanf ("%[^\n]s", str);
while (*p) /* for every character in string */
{
if (*(p + 1) && strchr (p + 1, *p)) /* test if remaining chars match */
if (!strchr(rep, *p)) /* test if already marked as dup */
rep[ri++] = *p; /* if not add it to string */
p++; /* increment pointer to next char */
}
printf ("\n Repeated digit(s): %s\n\n", rep);
return 0;
}
Note: you can also add a further test to limit to digits only with if (*p >= '0' && *p <= '9')
output:
$./bin/dupdigits
Enter a number: 1112223334566
Repeated digit(s): 1236
Error is here
if (number[digit] == true)
should be
if (number[digit] == false)
Eclipse + CDT plugin + stepping debug - help you next time
As everyone has given the solution: You can achieve this using the counting sort see here. Time complexity of solution will be O(n) and space complexity will be O(n+k) where k is the range in number.
However you can achieve the same by taking the XOR operation of each element with other and in case you got a XOR b as zero then its means the repeated number. But, the time complexity will be: O(n^2).
#include <stdio.h>
#define SIZE 10
main()
{
int num[SIZE] = {2,1,5,4,7,1,4,2,8,0};
int i=0, j=0;
for (i=0; i< SIZE; i++ ){
for (j=i+1; j< SIZE; j++){
if((num[i]^num[j]) == 0){
printf("Repeated element: %d\n", num[i]);
break;
}
}
}
}

Decimal to Binary conversion using recursion with while loop

my binary conversion doesn't work after it recurs a second time, it seems to work only during the first time through. The purpose of the is have a user input a number to convert to Hex, Octal, and brinary from a integer and keep on asking and converting until the user inputs 0. Please help!
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
long toBinary(int);
int main(void) {
int number = 0;
long bnum;
int zero = 0;
while(number != zero) {
puts("\nPlease enter a number you would like to convert to");
puts("\nHexadecimal, octal, and binary: ");
scanf("%d", &number);
if(number != zero) {
printf("\nThe Hexadecimal format is: %x", number);
printf("\nThe Octal format is: %o", number);
bnum = toBinary(number);
printf("\nThe binary format is: %ld\n", bnum);
}
else {
puts("\nI'm sorry you have to enter a number greater than 0.\n");
puts("\nOr have enter an invalid entry.");
}
}
return 0;
}
long toBinary(int number) {
static long bnum, remainder, factor = 1;
int long two = 2;
int ten = 10;
if(number != 0) {
remainder = number % two;
bnum = bnum + remainder * factor;
factor = factor * ten;
toBinary(number / 2);
}
return bnum;
}
You just need a function to convert an integer to its binary representation.
Assuming the int is 32 bits then this should work:
#include <stdio.h>
int main()
{
char str[33];
str[32] = 0;
int x = 13, loop;
for (loop = 31; loop >= 0; --loop) {
str[loop] = (x & 1) ? '1' : '0';
x = x >> 1;
}
printf("As %s\n", str);
return 0;
}
You can make this into a function, read x etc...
EDIT
For octal/hex - printf will do this for you
EDIT
Here goes recursively
#include <stdio.h>
void PrintBinary(int n, int x) {
if (n > 0) {
PrintBinary(n - 1, x >> 1);
}
printf("%c",(x & 1) ? '1' : '0');
}
int main()
{
PrintBinary(32,12);
return 0;
}
First of all I am surprised it even works once. Firstly, your while condition is while number does not equal zero. But right off the bat, number equals 0 and zero equals 0. Therefore the while should never run. If you want to keep this condition for the main loop, change it to a do-while loop: do { //code } while (number != zero);. This will run the code at least once, then check if the inputted number doesn't equal zero. That brings me to the next issue; your scanf for number is scanning for a double and placing it in a regular integer memory spot. Quick fix: scanf("%i",&number);. Also I am finding some functions called puts.. I find it best to keep with one printing function, printf. Now, I am finding afew errors in your toBinary function, but if it works than I guess it works. These are all the errors i could find, I hope this helped. But for future reference there is no need to declare a variable for a const number like 2 or 10 at this level.
#include <stdint.h>
char* toBinary(int32_t number, int index){
static char bin[32+1] = {0}, *ret;
if(index == 32){
memset(bin, '0', 32);
return toBinary(number, 31);
} else if(number & (1<<index))
bin[31-index] = '1';
if(index)
(void)toBinary(number, index-1);
else
for(ret = bin; *ret == '0';++ret);
return ret;
}
...
int number = -1;
...
printf("\nThe binary format is: %s\n", toBinary(number, 32));

Resources