Related
I have written a program that should be rather simple but on execution, it is not giving the wanted results. Even when debugging the program, I guess I found the error (getting stuck in the first if condition) but I'm not able to solve it (my inexperience perhaps). Anyways, this program, which should have been frugal, took 3 days whereas I expected it to take mere hours. Please help me with guiding me where I'm going wrong and how to solve it.
Here is the code
/*WAP to read pre entered no. of ints. consider only +ve and print the pythagorean triplets in them.*/
#include <stdio.h>
int main(){
int c,p,pp,count=0,a;
printf("How many entries to accept?\n");
scanf("%d",&a);
printf("Enter the nos.\n");
for (int i = 0; i < a; i++)
{
scanf("%d",&c);
if (c<0) //skip -ve nos.
{
continue;
}
if (count==0)
{
pp=c;
count++;
}
else if (count==1)
{
p=c;
count++;
}
else if ((pp*pp)+(p*p)==(c*c)) //Tracking count not necesarry after first three
{
printf("Pythagorean triplet found\n");
printf("%d %d %d",pp,p,c);
pp=p;
p=c;
}
}
return 0;
}
The main objective is to first scan a no. to signify the inputs to be read. Then scan the inputs, separated by a space or enter, in a loop which will only accept the no. of inputs stated before. It should neglect any -ve entries. It should print out the Pythagorean triplet if it encounters one, in a consecutive manner i.e. the triplet should appear one after the other & not randomly. We have to do the task without using arrays.
sample input is (you can consider any)(all given through the terminal)
(no. of entries)
6
1 -1 3 4 -4 5
(Here it will ignore -1 & -4)
expected output will be
Pythagorean triplet found
3 4 5
I am still learning so sorry for the elaborate program.
Thank you in advance.
since I cant see the input file I dont know if the values are sorted, since we need to identify which is the hypotenuse, makes it a bit more fiddly.
Also not clear what 'skip negatives' means. Does it mean
that we might see 3 -6 4 5 and say 'yes 3,4,5' is a triple
that we might see 3 -4 5 and say yes 3 4 5
or that we might see 3 -4 5 and simply ignore the whole set
I have assumed the first one
#include <stdio.h>
int main() {
printf("How many entries to accept?\n");
int a;
if (scanf("%d", &a) != 1) {
printf("bad input\n");
return (-1);
}
printf("Enter the nos.\n");
for (int i = 0; i < a; i++)
{
int sides[3] = { 0 };
int max = 0; // longest side length -> hypot
for (int j = 0; j < 3; j++)
{
int c;
if (scanf("%d", &c) != 1) {
printf("bad input\n");
return (-1);
}
if (c < 0) //skip -ve nos.
j--; // try again
else {
if (c > max) {
max = c;
}
sides[j] = c;
}
}
int hyp = max * max; // hypotenuse squared
int adjTot = 0; // adj sides squared total
for (int j = 0; j < 3; j++)
{
if (sides[j] == max)
continue;
adjTot += sides[j] * sides[j];
}
if (adjTot == hyp)
printf("%d %d %d is py\n", sides[0], sides[1], sides[2]);
else
printf("%d %d %d isnt py\n", sides[0], sides[1], sides[2]);
}
return 0;
}
Since you say you are reading from a file it just exits if there is non numeric data
I am new to C so I am having a little difficulty!
I want to take an integer input from the user and add 7 to each of the digit in the input. All of that works, but the digits are printing in the reverse order.
How do i make the digits print in the correct order? I checked other similar questions on Stack overflow but it does not seem to work. Thanks in advance!
int main(void)
{
int numToEncrypt;
printf("Please input a 4-digit number you wish to encrypt: ");
scanf("%d", &numToEncrypt);
while (numToEncrypt > 0)
{
int digit = numToEncrypt % 10;
// do something with digit
digit = (digit + 7)%10;
numToEncrypt /= 10;
printf("number is: %d \n",digit);
}
}
)
Converting the string input to an integer and back is pointless. Just work with the data as a string. eg:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int c;
if( getenv("V") ) {
printf("Please input the number you wish to encrypt: ");
fflush(stdout);
}
while( (c = getchar()) != EOF ) {
if( isspace(c) ) {
fflush(stdout);
} else if( isdigit(c) ) {
c = '0' + (c - '0' + 7) % 10;
} else {
fprintf(stderr, "Invalid input: %c", c);
return EXIT_FAILURE;
}
putchar(c);
}
}
Note that a huge advantage of doing this is that it is easy to work with ten million digit integers. You will not be able to do that using scanf to convert the string into an integer.
One way is using a variable to specify which digit to process.
#include <stdio.h>
int main(void)
{
int numToEncrypt;
int delta = 1000; // for 4-digit number
printf("Please input a 4-digit number you wish to encrypt: ");
scanf("%d", &numToEncrypt);
while (delta > 0)
{
int digit = (numToEncrypt / delta) % 10;
// do something with digit
digit = (digit + 7)%10;
delta /= 10;
printf("number is: %d \n",digit);
}
}
As this is homework, you could use recursion:
#include <stdio.h>
void print_recursive(int num)
{
// print leading digits
if (num>9)
{
print_recursive(num/10);
}
// print last digits
printf("number is: %d\n", (num+7)%10);
}
int main(void)
{
int number;
printf("Please input a 4-digit number you wish to encrypt: ");
scanf(" %d", &number); // note: You should check the return value!
print_recursive(number);
}
It is not limited to 4 digits.
For a simple program like this, one usually does not bother with a lot of design. However, it is also beneficial to practice software design on simple problems like this, since the knowledge extends to more complicated programs. This is an application of divide and conquer (as a problem solving strategy, not the computer algorithm). The idea being that smaller problems are simpler than larger ones.
In this case, you consider encapsulating the work of "encrypting" to a function, and have the function return the encrypted value. We'll just implement a stub for now, and fill it in later.
int encryptBy7(int input) {
int output = 0;
return output;
}
In addition, we can encapsulate the work of "printing" to a function. And, this is your actual question, if we think about it critically.
void printDigitByDigit(int num, const char *msg) {
printf("stub\n");
}
So your main program would look like:
int main(void) {
int numToEncrypt;
int numEncrypted;
printf("Please input a 4-digit number you wish to encrypt: ");
scanf("%d", &numToEncrypt);
numEncrypted = encryptBy7(numToEncrypt);
printDigitByDigit(numEncrypted, "number is");
return 0;
}
So, your algorithm to encrypt seems to work, so let's just code that up in a way that it stores it as a number.
int encryptBy7(int input) {
int output = 0;
int pow10 = 1;
/* Original program didn't deal with 0 */
if (input == 0) return 0;
while (input > 0) {
int digit = input % 10;
// do something with digit
digit = (digit + 7)%10;
input /= 10;
// build output
output += digit * pow10;
pow10 *= 10;
}
return output;
}
So, now we get to the meat of your question, which is about how to print out the digits starting with the most significant digit. If we see how we built up the output in the previous function, we can reverse the same process of looking at the powers of 10 to find the most significant digit, and then work backwards from there.
void printDigitByDigit(int input, const char *msg) {
int pow10 = 1;
int x = input;
// Find the position of the most significant digit
while (x > 10) {
pow10 *= 10;
x /= 10;
}
// Divide by the input appropriate power of 10 to
// find and print the corresponding digit
while (pow10 > 0) {
int digit = (input / pow10) % 10;
printf("%s: %d\n", msg, digit);
pow10 /= 10;
}
}
Of course, you are free to choose to try to do this as a single program inside of main as you had originally attempted, and the result would probably be a shorter program. I'll leave that as an exercise. However, I would argue that breaking up the program into tasks will provide you more benefit in the long run, and itself is a problem solving tool. Each function becomes easier to think about, and thus an easier problem to solve.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I wrote a simple program to find greatest among three numbers. But it seems that I wrote it in a way that makes it slightly confusing - hard to understand. What would be the way to improve this program to make it better at expressing its purpose and operation, and to remove the obvious repetition?
main()
{
int a,b,c;
printf("Enter three numbers: ");
scanf("%d %d %d",&a,&b,&c);
if (a==b && b==c)
printf("all are equal....:)");
else if(a>b)
{
if(a>c)
printf("%d is greatest among all",a);
else
printf("%d is greatest among all",c);
}
else
{
if(b>c)
printf("%d is the greatest among all",b);
else
printf("%d is the greatest among all",c);
}
getch();
}
#include <stdio.h>
int max(int a, int b)
{
return (a > b) ? a : b;
}
int main(void)
{
int a, b, c;
printf("Enter three number: ");
scanf("%d %d %d", &a, &b, &c);
if ((a == b) && (b == c))
{
printf("all are equal.");
}
else
{
printf("%d is the greatest among all", max(a, max(b, c)));
}
return 0;
}
I'd like to offer an example of the development process that could lead to figuring it out. I've linked relevant documentation to fill in the likely gaps in knowledge, and attempted to explain what led me to that documentation. Variants of such thought process are common among developers, yet the process is regrettably often not explained in educational settings, and must be acquired by "sweat and tears". I figure: let's shed some light on it!
A decent reference to the C language and standard library is https://en.cppreference.com/w/c (yes, it's cppreference, but it's not just for C++!).
The clarity of this program matters, and it certainly could be improved.
But people also interpret efficiency to mean speed. But: The speed of this particular program is irrelevant. The slowest element is the human, by more than 6 orders of magnitude vs. the machine. If you wished for this code to be faster when e.g. working on a large array of triples of numbers, then you could edit the question and instead provide an example that works through a big array of triples. As it stands, the program could be written in a shell script file and you wouldn't be able to tell the difference. It's a good idea to optimize what matters - and maintainability often matters more than raw performance :)
Output Skeleton
You only need to print the largest number - so let's start with a way to print it, and assume that the selection of the largest number, and the detection whether they are all equal, has been taken care of:
#include <stdio.h>
int main() {
char all_equal;
int max;
// to be done
if (all_equal) printf("All numbers are equal.\n");
else printf("%d is the greatest among the numbers entered.\n", max);
}
Thus, we have a skeleton for the output of the program. That's our goal. It helps to start with the goal expressed in the language of the problem domain - here in C - for it can focus and guide the implementation. We know exactly where we're going now: we have to get the input, and then process it to obtain the max value, and the all_equal predicate (a boolean: zero means falseness, anything else means truth).
We could actually turn this goal into a functional program by providing some "fake" data. Such data could be called test data, or mock data, depending on who you ask :)
#include <stdio.h>
int main() {
char all_equal = 0;
int max = 10;
if (all_equal) printf("All numbers are equal to %d.\n", max);
else printf("%d is the greatest among the numbers entered.\n", max);
}
We can run this, then change all_equal to 1 and see how the output is changed. So - we have some idea about what results should be fed into the output section of the program.
Processing
Getting the input from the user is on the opposite end of the goal, so let's work on something that builds up directly on the goal: let's compute those all_equal and max values! The processing code should replace the mock char all_equal = 0; int max = 10; section.
First, we need some numbers - we'll use mock data again, and from them we need to select the largest number:
int numbers[3] = {-50, 1, 30}; // mock data
char all_equal = 0; // mock data
int max = numbers[0];
for (int i = 1; i < 3; i++) {
if (numbers[i] > max) max = numbers[i];
}
Modern compilers will usually unroll this loop, and the resulting code will be very compact. The i loop variable won't even appear in the output, I'd expect.
We can foresee a potential for mistakes: if we ever decide to change the quantity of numbers, we can easily miss a place where such quantity is hardcoded (here as the literal 3). It'd be good to factor it out:
#define N 3
int numbers[N] = {-50, 1, 30}; // mock data
char all_equal = 0; // mock data
int max = numbers[0];
for (int i = 1; i < N; i++) {
if (numbers[i] > max) max = numbers[i];
}
You'll run into such #define-heavy code. It has its place back when C compilers were poor at optimizing code. Those times are now thankfully well over, but people continue doing this - without quite understanding why it is that they do it.
For numeric constants, it's usually unnecessary and counterproductive: the preprocessor does string substitution, so it has no idea what the code it modifies actually means. Preprocessor definitions "pollute" the global context - they leak out from wherever we define them, unless we explicitly #undef-ine them (How many people do that? You'll find that not many do.)
Instead, let's express it as a constant. We try:
const int N = 3;
int numbers[N];
But: this doesn't compile on some compilers. Huh? We read up on array declarations, and it seems that iff variable-length arrays (VLAs) are not supported by our compiler, then the number of elements must be a [constant expression][constexpr]. C doesn't consider a const int to be a constant expression (how silly, I know!). We have to kludge a bit, and use an enumeration constant to get the constant expression we need:
enum { N = 3 };
int numbers[N] = {-50, 1, 30}; // mock data
char all_equal = 0; // mock data
int max = numbers[0];
for (int i = 1; i < n; i++) {
if (numbers[i] > max) max = numbers[i];
}
We start by assigning the value of the first number in the list (index 0!) to max. Then we loop over subsequent numbers (starting with index 1!), compare each to the maximum, and update the maximum if a number happens to be greater than the maximum.
That's half of the goal: we got max, but we also need all_equal! The check for quality can be done in the same loop as the selection of the maximum (greatest number), thus:
enum { N = 3 };
int numbers[N] = {-50, 1, 30}; // mock data
char all_equal = 1;
int max = numbers[0];
for (int i = 1; i < N; i++) {
all_equal = all_equal && numbers[i] == max;
if (numbers[i] > max) max = numbers[i];
}
// here we have valid all_equal and max
We start with the assumption that the numbers are all equal (all_equal = 1). Then, for each subsequent number (indices 1 onwards), we check if the number is equal to the maximum, and we use a logical conjunction (logical and - &&) to update the all_equal proposition. Proposition is what we call a boolean: simply a statement that can be either true (here: non-zero) of false (zero). The conjunction applied repeatedly to all_equal has the effect of a one-way valve: once all_equal goes false, it will stay false.
Logicians would state it as ∀ p ∈ ℙ : (false ∧ p) = false. Read: for all ℙropositions p, false and p is false.
We merge this into our skeleton, and get a slightly more useful program. It still uses mock data, but it performs all the "interesting" parts of the problem.
#include <stdio.h>
int main() {
enum { N = 3 };
int numbers[N] = {-50, 1, 30}; // mock data
char all_equal = 1;
int max = numbers[0];
for (int i = 1; i < N; i++) {
all_equal = all_equal && numbers[i] == max;
if (numbers[i] > max) max = numbers[i];
}
if (all_equal) printf("All numbers are equal.\n");
else printf("%d is the greatest among the numbers entered.\n", max);
}
We can run this code, tweak the mock data, and verify that it appears to do what we want it to! Yay!
Input
Finally, we should get those numbers from the user, to get rid of the final bit of mock data:
#include <stdio.h>
int main() {
enum { N = 3 };
int numbers[N];
printf("Enter %d numbers:\n", N);
for (int i = 0; i < N; i++) scanf("%d", &numbers[i]);
char all_equal = 1;
int max = numbers[0];
for (int i = 1; i < N; i++) {
all_equal = all_equal && numbers[i] == max;
if (numbers[i] > max) max = numbers[i];
}
if (all_equal) printf("All numbers are equal.\n");
else printf("%d is the greatest among the numbers entered.\n", max);
}
We run it, and hey! It seems to work! This program is equivalent to the one you wrote. But. There's always a "but".
Handling Invalid Input
Software testing now begins in earnest. We "play" some more with the program (we "exercise" it), and notice that the program doesn't react any differently when a non-number is entered. It sometimes seems to ignore the invalid number and still provide sensible result based on other, correct, numbers, but sometimes it just spits out a random value. Random value - hmm. Could perhaps one of the numbers be uninitialized?
We read the documentation of scanf() and notice that it won't modify its output argument if it fails! Thus the program has undefined behavior: here it results in "random" output.
Reading on, we find that the return value of scanf() can be used to check if it was successful. We'd like to handle invalid input and provide some feedback:
int main() {
enum { N = 3 };
int numbers[N];
printf("Enter %d numbers.\n", N);
for (int i = 0; i < N; /*empty!*/) {
printf("#%d: ", i+1);
if (scanf("%d", &numbers[i]) != 1)
printf("Sorry, invalid input. Try again.\n");
else
i++;
}
...
}
We [try again][run4], and the program goes into an infinite loop as soon as invalid input is provided. Hmm. Something weird is going on. We read up on the issue of parsing user input in C, and realize that scanf() alone won't work correctly if any input errors are present, since the input remains in the input buffer - it will keep "tripping" subsequent scanf's. We must remove that input before retrying.
To find a function that may do that, we read up on the C input/output library and find the getchar() function. We use it:
int main() {
enum { N = 3 };
int numbers[N];
printf("Enter %d numbers.\n", N);
for (int i = 0; i < N; /*empty*/) {
printf("#%d: ", i+1);
if (scanf("%d", &numbers[i]) != 1) {
printf("Sorry, invalid input. Try again.\n");
char c;
while ((c = getchar()) != '\n'); // remove input until end of line
} else
i++;
}
...
}
We try it again, and things seem to work. But! We can do something else: let's try closing the input stream (^Z,Enter on Windows, ^D on Unix). The program goes into an infinite loop - again.
Aha! End of input - EOF! We must explicitly handle the EOF (end of file/read error) condition, and the best we can do then is to stop the program. How? We read up about C program utilities, and find a perfect function that would abort the program: abort(). Program utilities are utilities that used to manage "other" tasks that a program might do - tasks that don't fall under other categories (are not I/O, math, etc.).
#include <stdlib.h> // added for abort()
int main() {
enum { N = 3 };
int numbers[N];
printf("Enter %d numbers.\n", N);
for (int i = 0; i < N; /*empty*/) {
int c;
printf("#%d: ", i);
c = scanf("%d", &numbers[i]);
if (c == EOF) abort();
if (c != 1) {
printf("Sorry, invalid input. Try again.\n");
while ((c = getchar()) != EOF && c != '\n');
if (c == EOF) abort();
} else
i++;
}
...
}
We try yet again, and this time things really seem to work fine. No matter what we throw at the program, it behaves reasonably: if the input is still available, it asks the user to enter the number again. If the input won't be available anymore (EOF indicates that), we abort().
In even more deviousness, we try to surround the numbers with spaces and tabs in our input - after all, it's just whitespace, and to a human it'd look like valid input in spite of the spaces. We try it, and no problem: scanf() seems to do the "right thing". Hah. But why? We read into the scanf() documentation, and discover that [emphasis mine]:
All conversion specifiers other than [, c, and n consume and discard
all leading whitespace characters (determined as if by calling
isspace) before attempting to parse the input. These consumed
characters do not count towards the specified maximum field width.
Complete Program
We now got all the pieces. Put them together, and the complete program is:
#include <stdio.h>
#include <stdlib.h>
int main() {
enum { N = 3 };
int numbers[N];
printf("Enter %d numbers.\n", N);
for (int i = 0; i < N; /*empty*/) {
printf("#%d: ", i+1);
int c = scanf("%d", &numbers[i]);
if (c == EOF) abort();
if (c != 1) {
printf("Sorry, invalid input. Try again.\n");
while ((c = getchar()) != EOF && c != '\n');
if (c == EOF) abort();
} else
i++;
}
char all_equal = 1;
int max = numbers[0];
for (int i = 1; i < N; i++) {
all_equal = all_equal && numbers[i] == max;
if (numbers[i] > max) max = numbers[i];
}
if (all_equal) printf("All numbers are equal.\n");
else printf("%d is the greatest among the numbers entered.\n", max);
}
Try it out!.
Useful Refactoring
This works fine, but the input processing dominates over main, and seems to obscure the data processing and output. Let's factor out the input, to clearly expose the part of the program that does "real work".
We decide to factor out the following function:
void read_numbers(int *dst, int count);
This function would read a given count of numbers into the dst array. We think a bit about the function and decide that a zero or negative count doesn't make sense: why would someone call read_numbers if they didn't want to get any input?
We read up on error handling in C, and discover that assert() seems a good candidate to make sure that the function was not called with incorrect parameters, due to a programming bug. Note that assert() must not be used to detect invalid program input!!. It is only meant to aid in finding program bugs, i.e. the mistakes of the developer of the program, not mistakes of the user. If user input had to be checked, it has to be done explicitly using e.g. the conditional statement (if), or a custom function that checks the input - but never assert!
Note how assert is used:
It tells you, the human reader of the program, that at the given point in the program, count must be greater than zero. It helps reasoning about the subsequent code.
The compiler generates the code that checks the asserted condition, and aborts if it doesn't hold (is false). The checks usually are only performed in the debug build of the program, and are not performed in the release version.
To keep the program flow clear, we forward-declare read_numbers(), use it in main(), and define (implement) the function last, so that it doesn't obscure things:
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
void read_numbers(int *dst, int count);
int main() {
enum { N = 3 };
int numbers[N];
read_numbers(numbers, N);
char all_equal = 1;
int max = numbers[0];
for (int i = 1; i < N; i++) {
all_equal = all_equal && numbers[i] == max;
if (numbers[i] > max) max = numbers[i];
}
if (all_equal) printf("All numbers are equal.\n");
else printf("%d is the greatest among the numbers entered.\n", max);
}
void read_numbers(int *dst, int count) {
assert(count > 0);
printf("Enter %d numbers.\n", count);
for (int i = 0; i < count; /*empty*/) {
printf("#%d: ", i+1);
int c = scanf("%d", &dst[i]);
if (c == EOF) abort();
if (c != 1) {
printf("Sorry, invalid input. Try again.\n");
while ((c = getchar()) != EOF && c != '\n');
if (c == EOF) abort();
} else
i++;
}
}
You can try this program out in onlinegdb.com - just click this link!
In my opinion, main() looks very clear now. The input function stands on its own and can be analyzed in isolation: note how it's a pure function, and has no global state. Its output only acts on the arguments passed in. There are no global variables! There shouldn't ever be, really.
That's where I'd stop. We have a clear program that handles both valid and invalid input.
Moar Refactoring !!111!!
But you could say: how about we factor out data processing and final output as well? We can do that, sure. Yet, in a simple program like ours, it perhaps will slightly obscure what's going on. But at least let's see how it could look then, play with it and decide for ourselves :)
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char all_equal; // true if all numbers were equal
int max; // the greatest number
} Result;
void read_numbers(int *dst, int count);
Result find_greatest(int *numbers, int count);
void output_result(const Result *r);
int main() {
enum { N = 3 };
int numbers[N];
read_numbers(numbers, N);
const Result r = find_greatest(numbers, N);
output_result(&r);
}
void read_numbers(int *dst, int count) {
assert(count > 0);
printf("Enter %d numbers.\n", count);
for (int i = 0; i < count; /*empty*/) {
printf("#%d: ", i+1);
int c = scanf("%d", &dst[i]);
if (c == EOF) abort();
if (c != 1) {
printf("Sorry, invalid input. Try again.\n");
while ((c = getchar()) != EOF && c != '\n');
if (c == EOF) abort();
} else
i++;
}
}
Result find_greatest(int *numbers, int count) {
assert(count > 0);
Result r = {.all_equal = 1, .max = numbers[0]};
for (int i = 1; i < count; i++) {
r.all_equal = r.all_equal && numbers[i] == r.max;
if (numbers[i] > r.max) r.max = numbers[i];
}
return r;
}
void output_result(const Result *r) {
if (r->all_equal) printf("All numbers are equal.\n");
else printf("%d is the greatest among the numbers entered.\n", r->max);
}
Note how the Result local variable is initialized using struct initialization with designated initializers:
Result r = {.all_equal = 1, .max = numbers[0]};
If you needed to perform the initialization independently of the declaration of the variable, you would wish to use compound literals - a lesser known, but very important notational shortcut in modern C:
Result r;
// some intervening code
r = (Result){.all_equal = 1, .max = numbers[0]};
or perhaps:
void function(Result r);
void example(void) {
function((Result){.all_equal = 1, .max = numbers[0]});
}
Your code is fine; in fact, Bentley, McIlroy, Engineering a sort function, 1993, realised by, among others, BSD qsort, employs the same sort of mechanism in the inner loop for finding the median of three values. Except,
If all values are the same, it doesn't, "find the greatest among three numbers," but rather short-circuits and finds how many times the maximal value occurs, (three.) This is a separate problem.
It generally pays to separate one's logic from the output.
I've taken your code and put it in a function, stripped the output, and stripped of the equality.
#include <assert.h>
static int hi3(const int a, const int b, const int c) {
/* Same as `return a > b ? a > c ? a : c : b > c ? b : c;`. */
if(a > b) {
if(a > c) {
return a;
} else {
return c;
}
} else {
if(b > c) {
return b;
} else {
return c;
}
}
}
int main(void) {
/* Permutations of 3 distinct values. */
assert(hi3(1, 2, 3) == 3
&& hi3(1, 3, 2) == 3
&& hi3(2, 1, 3) == 3
&& hi3(2, 3, 1) == 3
&& hi3(3, 1, 2) == 3
&& hi3(3, 2, 1) == 3);
/* Permutation of 2 distinct values. */
assert(hi3(1, 2, 2) == 2
&& hi3(2, 1, 2) == 2
&& hi3(2, 2, 1) == 2);
assert(hi3(1, 1, 2) == 2
&& hi3(1, 2, 1) == 2
&& hi3(2, 1, 1) == 2);
/* All the same value. */
assert(hi3(1, 1, 1) == 1);
return 0;
}
Your code tests all the combinations of relative magnitudes successfully.
Im trying to create a program that has 2 options, view and compute. Right now im trying to figure how to turn my array where i will input my values into a function, so i can go in and out several times to store the values. I also want to view to be a function where i can view the values several times.
i've managed to get the computing part to work in my main, now i need to turn it into a function. Secondly how do i create a second function to view it?
My code is a bit mess please bear with me.
#include <stdio.h>
#define LENGTH 10
int enterMeasurements();
int main(void)
{
char input;
int nrMeasurements=0;
int arrayTable[LENGTH] = {0};
//main menu
do
{
char input;
printf("\nMeasurement tool 1.0\n");
printf("V for (View)\n");
printf("E for (Enter Values)\n");
printf("C for (Compute Values)\n");
printf("R for (Reset Values)\n");
printf("Q for (Quit)\n");
printf("\nEnter input: ");
scanf(" %c", &input);
if(input == 'v' || input == 'V')
{
// function to print array values
printf("[ ]\n");
}
else if(input == 'e' || input == 'E')
{
// enter values here
nrMeasurements = enterMeasurements(arrayTable,nrMeasurements); // my function for entering values
}
else if (input == 'c' || input == 'C')
{
// enter function to calc min, max and avg and prints it.
printf("[ min max avg ]\n");
}
else if (input == 'r' || input == 'R')
{
// enter function that erase the entire array.
printf("[ erase array ]\n");
}
}
while (input !='q' && input != 'Q');
return 0;
}
int enterMeasurements()
{
int enterMeasurements(int arrayTable[], int nrMeasurements)
{
int i;
for (i = 0; i < LENGTH; i++)
{
printf("Enter Measurement #%i (or 0): ", i+1);
scanf("%d", &arrayTable[i]);
if (arrayTable[i] == 0 )
break;
}
return i;
}
To help you get started (you should really read a beginners book on the subject) I will show you the printArray function.
First of all the printArray function needs to know the actual array to print. it also needs to know the number of elements in the array. This can be accomplished in two ways: Global variables (which no-one is really recommending) or with function arguments.
You first need to tell the compiler that the function takes arguments:
void printArray(int *array, size_t numElements)
The above line tells the compiler that the printArray function takes two arguments: One which is called array and is a pointer to int (arrays "decays" to pointers to their first element when passed to functions), and one argument that is named numElements and is of type size_t (which is a good type for sizes and number of elements and similar things). The function is declared to return nothing with the void keyword.
The declared arguments can then be used inside the function like any other variables in the scope of the function, and are in fact just like any other local variable defined inside the function. So you can then use them like e.g.
void printArray(int *array, size_t numElements)
{
for (size_t i = 0; i < numElements; ++i)
{
printf("array[%d] = %d\n", i, array[i]);
}
}
To call this function you need to pass the array and the number of elements, much like you pass arguments to any other function like scanf or printf:
printArray(arrayTable, i);
Note that the function doesn't return anything, which means you can't use it in printf, or any other expression that expects a value.
You should of course also make your forward function prototype declaration match the actual function definition.
Alex, continuing from your last comment, to display a menu that will allow you to add values to your array, delete values from your array and view the array (along with the max, min and average of the values), can do something similar to the following. Note: the command line isn't a windowed user interface, so your menu operations are more like a printed receipt of your transactions with it. (you can do nice text windows and stationary menus, but that generally requires an text library, such as ncurses which is well beyond the scope of your question.
As explained in the comment, your basic approach is simply to create a loop that repeats continually. It will display your menu and allow you to enter your selection from a list, e.g.:
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection:
After the user enters the selection, to make the comparison easier, the user's input in converted to lower-case. Also note, that the input is read as a string using fgets (a line-oriented input function) which makes taking user input much easier than having to worry about whether the '\n' remains in the input buffer (stdin) just waiting to cause problems for your next input. (you can use the scanf family of functions, but YOU are the one responsible for accounting for each character entered by the user (and emptying the input buffer).
Reading input with fgets will read up to and including the '\n', so their is no chance of the '\n' being left unread in stdin. Also note that fgets will read a string or characters, where you are only interested in the first. That is easily handled simply by referencing the first character in the buffer. (e.g. if you are reading user-input into a buffer called buf, you can simply use buf[0] to access the first character, or simply *buf for that matter)
After the user input is read, the first character is passed to a switch statement, where each case of the statement is compared against the first character. If the character matches a case, then the actions associated with that case are taken, ending with the break (you can read about fall-through processing if the break is omitted on your own)
As mentioned in the comment, if you simply need to break out of one loop, then break is all you need. However here, your switch statement is inside the loop. A single break will only get you out of the switch but not the outside for loop. To break out of nested loops, use the goto statement. (you could also add more variables and set some type of exit flag, but why? This is what the goto was meant to do. (there are some cases where a flag is equally good as well)
In each case within the switch, you are free to call whatever code is needed to handle that menu selection. You will note we simply call short helper functions from within the switch to print the array, insert values, remove values, etc. You can put all the code in the switch if you like, it just rapidly become unreadable.
Putting that altogether, you can do something like the following:
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
enum { MAXN = 64 }; /* constant - max numbers of vals & chars */
void showmenu ();
void prnarray (int *a, int n);
int addvalue (int *a, int n, int newval);
int delvalue (int *a, int n, int index);
int minvalue (int *a, int n);
int maxvalue (int *a, int n);
int sumvalues (int *a, int n);
int main (void) {
int vals[MAXN] = { 21, 18, 32, 3, 9, 6, 16 }, /* the array */
n = 7;
for (;;) { /* loop until user quits or cancels, e.g. ctrl+d */
showmenu(); /* show the menu */
char buf[MAXN] = "";
fgets (buf, MAXN, stdin); /* read user input */
/* convert to lower-case for comparison of all entries */
switch (tolower (buf[0])) { /* 1st char is entry */
case 'v' : prnarray(vals, n);
break;
case 'i' : printf ("\n enter the new value: ");
if (fgets (buf, MAXN, stdin) &&
isdigit (buf[0])) {
n = addvalue (vals, n, atoi (buf));
}
break;
case 'd' : printf ("\n enter the index to delete: ");
if (fgets (buf, MAXN, stdin) &&
isdigit (buf[0])) {
n = delvalue (vals, n, atoi (buf));
}
break;
case 'n' : printf ("\n Mininum of '%d' values is : %d\n",
n, minvalue (vals, n));
break;
case 'x' : printf ("\n Maxinum of '%d' values is : %d\n",
n, maxvalue (vals, n));
break;
case 'a' : printf ("\n Average of '%d' values is : %.2lf\n",
n, (double)sumvalues (vals, n)/n);
break;
case 's' : printf ("\n Sum of '%d' values is : %d\n",
n, sumvalues (vals, n));
break;
case 'q' : printf (" that's all folks...\n");
goto done;
default : if (!buf[0]) { /* check for manual EOF */
putchar ('\n'); /* tidy up */
goto done;
}
fprintf (stderr, "error: invalid selection.\n");
}
}
done:; /* goto label - breaking 'for' and 'switch' */
return 0;
}
void showmenu ()
{
fprintf(stderr, "\n ======== Program Menu =========\n\n"
" V) View the Array.\n"
" I) Insert New Value.\n"
" D) Delete Existing Value.\n"
" N) Display Minimum Value.\n"
" X) Display Maximum Value.\n"
" A) Display Average of Values.\n"
" S) Display Sum of Values.\n"
"\n"
" Q) Quit.\n"
"\n"
" Selection: ");
}
void prnarray (int *a, int n)
{
int i;
printf ("\n there are '%d' values in the array:\n\n", n);
for (i = 0; i < n; i++)
printf (" array[%2d] : %d\n", i, a[i]);
}
int addvalue (int *a, int n, int newval)
{
if (n == MAXN) {
fprintf (stderr, "error: all '%d' values filled.\n", n);
return n;
}
a[n++] = newval;
return n;
}
int delvalue (int *a, int n, int index)
{
if (index < 0 || index > n - 1) {
fprintf (stderr, "error: index out of range.\n");
return n;
}
int i;
for (i = index + 1; i < n; i++)
a[i-1] = a[i];
a[i] = 0;
return --n;
}
int minvalue (int *a, int n)
{
int i, min = INT_MAX;
for (i = 0; i < n; i++)
if (a[i] < min)
min = a[i];
return min;
}
int maxvalue (int *a, int n)
{
int i, max = INT_MIN;
for (i = 0; i < n; i++)
if (a[i] > max)
max = a[i];
return max;
}
int sumvalues (int *a, int n)
{
int i, sum = 0;
for (i = 0; i < n; i++)
sum += a[i];
return sum;
}
(note: there are always additional validation checks you can add to test whether you have read all the input the user provided, etc.. But given the crux of your question I'll leave that learning to you)
Example Use/Output
$ ./bin/menusimple
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection: v
there are '7' values in the array:
array[ 0] : 21
array[ 1] : 18
array[ 2] : 32
array[ 3] : 3
array[ 4] : 9
array[ 5] : 6
array[ 6] : 16
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection: i
enter the new value: 77
======== Program Menu =========
V) View the Array.
I) Insert New Value.
D) Delete Existing Value.
N) Display Minimum Value.
X) Display Maximum Value.
A) Display Average of Values.
S) Display Sum of Values.
Q) Quit.
Selection: v
there are '8' values in the array:
array[ 0] : 21
array[ 1] : 18
array[ 2] : 32
array[ 3] : 3
array[ 4] : 9
array[ 5] : 6
array[ 6] : 16
array[ 7] : 77
Look things over and let me know if you have any questions. Also, as you are just learning, make sure you are compiling your code with compiler warnings enabled and that you don't consider your code reliable until it compiles without warning. That means you should be compiling with at least the -Wall -Wextra flags set. If you are using gcc and the command line, then it would be:
gcc -Wall -Wextra -O2 -o simplemenu simplemenu.c
To compile the code in simplemenu.c into an executable named simplemenu with the -O2 optimizations applied. If you are really wanting to eliminate all warnings, add -pedantic as well. For codeblock or other IDE, look through the compiler menu options, they all provide a place to input all of the options you would like. Good luck with your code.
Procedural Approach Without Functions & Input With scanf
OK, now that we know how far we need to backup, let's look at rewriting the code in a bare minimum, top-down approach without using functions and taking user input with scanf (which will cause you more grief, especially taking mixed character and numeric input, but it can be done, if you account for the '\n' left in stdin)
First a note about taking input with scanf. When you ask for user input, like with the menu selection, and the user enters V and presses Enter, the input buffer stdin contains "V\n" (the '\n' as the result of pressing Enter). When you then use scanf to read a character (e.g. char sel; scanf ("%c", &sel);) the 'V' is taken from stdin and stored in sel leaving '\n' in stdin. If you then attempt to read another character (e.g. char nextch; scanf ("%c", &nextch);) it will appear that scanf has skipped reading nextch because it never allow you to enter a value. What has actually happened is scanf ("%c", &nextch); has read the '\n' that remained in stdin as your next character and is quite content with the value of 0xa (10 decimal) in nextch.
You must always account for the '\n' when using scanf. You have two options, 1) leave a space before the conversion specifier (e.g. scanf (" %c", &nextch); or 2) use the assignment suppression operator '*' (e.g. scanf ("%c%*c", &nextch);), the second %*c telling scanf to read and discard the following character without adding the conversion to the match count (which is the integer value returned by scanf). Which brings up the most important point of all, always check the return of scanf. (otherwise, you have no clue whether you have an actual value to work with or just garbage) I will leave the reading of man scanf to you for further details on the effect of the space before the conversion specifier, and the assignment suppression operator.
The return for scanf (the match count) is the number of successful conversions performed based on the number of conversion specifiers contained within the format string (e.g. scanf (" %c %d", &somechar, &someint); contains 2 conversion specifiers %c and %d, so the return for scanf after successful conversion of both would be 2. If a matching or conversion failure occurs, the return will be less than 2 and if an error condition is encountered reading from the stream (stdin in this case) EOF is returned (generally a value of -1) All of this, and more, is why scanf is NOT the preferred method for taking user input in C. (that being said, it is what most tutorials, and most teachers, make the poor choice to expose new C programmers to without an understanding of the pitfalls)
With that out of the way, if you work through the example below, you will see that I have simply moved the code from the functions to within the if ... else if ... else framework. (look at the one-to-one relationship from where I call functions from the switch in the first example and the code below) This should also show why breaking the code up into logical functions, improves readability and improves code re-use. Compare the use of the switch statement with the if ... else if ... else daisy chain. Both are fine, but to me, the switch is more easily readable at a glance.
You should make sure you understand both versions as they are both basic entry level approaches to using C. Take your time going through each and if you have questions that you cannot answer by consulting one of the references provided in the tag-wiki link, just ask.
#include <stdio.h>
#include <stdlib.h> /* for atoi */
#include <limits.h> /* for INT_MIN/INT_MAX */
enum { MAXN = 64 }; /* constant - max numbers of vals & chars */
int main (void) {
int vals[MAXN] = { 21, 18, 32, 3, 9, 6, 16 }, /* the array */
n = 7;
for (;;) {
char c;
/* show the menu */
fprintf(stderr, "\n ======== Program Menu =========\n\n"
" V) View the Array.\n"
" I) Insert New Value.\n"
" D) Delete Existing Value.\n"
" N) Display Minimum Value.\n"
" X) Display Maximum Value.\n"
" S) Display Sum of Values.\n"
" A) Display Average of Values.\n"
"\n"
" Q) Quit.\n"
"\n"
" Selection: ");
/* read selection (inside of if is OK), check EOF or quit */
if (scanf (" %c", &c) == EOF || c == 'q' || c == 'Q') {
printf ("\n that's all folks...\n");
break;
}
if (c == 'v' || c == 'V') { /* view array code */
printf ("\n there are '%d' values in the array:\n\n", n);
int i;
for (i = 0; i < n; i++)
printf (" array[%2d] : %d\n", i, vals[i]);
}
else if (c == 'i' || c == 'I') { /* insert value code */
if (n == MAXN) {
fprintf (stderr, "error: all '%d' values filled.\n", n);
continue;
}
int newval = 0;
printf ("\n enter the new value: ");
if (scanf (" %d", &newval) == 1) {
vals[n] = newval;
n++;
}
else
fprintf (stderr, "error: invalid input.\n");
}
else if (c == 'd' || c == 'D') { /* delete value code */
int i, index = 0;
printf ("\n enter the index to delete: ");
if (scanf (" %d", &index) != 1) {
fprintf (stderr, "error: invalid input.\n");
continue;
}
if (index < 0 || index > n - 1) {
fprintf (stderr, "error: index out of range.\n");
continue;
}
for (i = index + 1; i < n; i++)
vals[i-1] = vals[i];
vals[i] = 0;
n--;
}
else if (c == 'n' || c == 'N') { /* display minimum code */
int i, min = INT_MAX;
for (i = 0; i < n; i++)
if (vals[i] < min)
min = vals[i];
printf ("\n Mininum of '%d' values is : %d\n",
n, min);
}
else if (c == 'x' || c == 'X') { /* display maximum code */
int i, max = INT_MIN;
for (i = 0; i < n; i++)
if (vals[i] > max)
max = vals[i];
printf ("\n Maxinum of '%d' values is : %d\n",
n, max);
}
else if (c == 's' || c == 'S') { /* compute sum code */
int i, sum = 0;
for (i = 0; i < n; i++)
sum += vals[i];
printf ("\n Sum of '%d' values is : %d\n",
n, sum);
}
else if (c == 'a' || c == 'A') { /* compute avg code */
int i, sum = 0;
double avg = 0.0;
for (i = 0; i < n; i++)
sum += vals[i];
avg = (double)sum/n;
printf ("\n Average of '%d' values is : %.2lf\n",
n, avg);
}
else /* if not matched, then invalid selection */
fprintf (stderr, "error: invalid selection.\n");
}
return 0;
}
(the operation and output from both program versions will be identical)
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;
}
}
}
}