How to remove newline in tabular addition - c

When executing this code, additions are separated by a newline each time I enter a value. So for example:
1
4 7 10
I reckon this is caused by the scanf() inputting a new line. How do you write the following code such that
1 4 7 10
is printed?
#include <stdio.h>
int main() {
int number;
int counter = 1;
printf("A\tA+3\tA+6\tA+9\n");
scanf ("%d", &number);
while (number != -1) {
while (counter <=3) {
number += 3;
printf("\t%d", number);
counter++;
}
printf("\n");
scanf ("%d", &number);
counter = 1;
}
}

I think you've mixed the concept of input & output. Actually in your code, you had only output:
> 4 7 10
try replace this code with your inner while loop, then pipe the standard out to another file, check the results and you will understand.
while (counter <=4){
printf("%d\t", number);
number += 3;
counter++;
}
./your_program > output_file

Related

Pythagorean triplets program

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

How to limit an integer's input to 2-12 only?

I want to strictly limit a user's input on an integer in this program to 2-12 only. How do I do that?
#include <stdio.h>
int main(){
int i;
scanf("%d", &i);
int diceThrown, diceResult;
int sum = 0;
for(diceThrown = 1; diceThrown <= i; diceThrown++){
scanf("%d", &diceResult); //limit this input to 2-12 only, how?
sum += diceResult;
}
if(sum >= 40){
sum = sum % 40;
if(sum == 12){
printf ("28\n");
} else if(sum == 35){
printf ("7\n");
} else{
printf ("%d\n", sum);
}
} else if(sum < 40){
if(sum == 12){
printf ("28\n");
} else if(sum == 35){
printf ("7\n");
} else{
printf ("%d\n", sum);
}
}
return 0;
}
Also just to clarify, that I'm still a beginner in programming (like only 2 months into C.SCi course), so if you could explain it to me like I'm not a expert that would be great.
scanf has no functionality to do what you want. You can just use an if to validate input.
if(scanf("%d", &diceResult) != 1 || diceResult < 2 || diceResult > 12) {
//handle invalid input here
}
If the input is invalid it is up to you what you want to do. You could ignore the input and ask the user to enter a valid number, you can quit the whole program or just ignore the error, or something else entirely.
You can also check the input repeatedly with an while:
while(scanf("%d", &diceResult) != 1 || diceResult < 2 || diceResult > 12) {
//prompt user to enter valid input here
}
As mentioned by chux, part of handling invalid input would be to cosume the invalid input and check for EOF.
The scanf("%d", &diceResult) != 1 will assure, that scanf actually read exactly one number and no parsing errors occurred.
Consider this:
#include <stdio.h>
int main(){
int x;
do
{
printf("give a number between [2-12]\n");
scanf ("%d",&x);
}
while(x<2 || x>12);
return 0;
}
You can use a do-while loop so that you only take the values that are between the 2-12 range. That way you can force the user to give an integer as an input that is in the range that you ask for, in that case from [2,12]. Otherwise the program will turn back and request a valid input again.

How to fix infinite printing of random number?

I wrote a program that scans an unknown amount of integers into an array but when I run it, it print the last value it has gotten an infinite amount of times.
For example for the input: 1 2 3 4 5
The output would be 55555555555555555555555...
Why does this happen and how can I fix that?
My goal here is to create a array, for an instance {1, 2, 3, 4, 5} and then print what it scanned into the array, ONLY ONCE...
int *pSet = (int*) malloc(sizeof(int)); int i; int c;
printf("Please enter a stream of numbers to make a set out of them: ");
printf("\n");
scanf("%d", &c);
pSet[0] = c;
printf("%d ", c);
for(i = 1; c != EOF; i++) {
pSet = (int*) realloc(pSet, sizeof(int)*(i+1));
if(pSet == NULL) {
return FAIL;
}
scanf("%d", &c);
pSet[i] = c;
printf("%d ", c);
}
free(pSet);
Why does this happen (?) (print ... an infinite amount of times.)
Look at the loop terminating conditions c != EOF.
int c;
scanf("%d", &c);
for(i = 1; c != EOF; i++) { // Not good code
scanf("%d", &c);
}
EOF is some negative value, often -1. scanf("%d", &c) attempts to read user input and convert to an int. scanf() returns a 1,0,EOF depending on if it 1) succeeded, 2) failed to find numeric text or 3) end-of-file or input error occurred. Unfortunately code does not use that return value. Instead code used the number read, c and checked if that number read was the same as EOF.
how can I fix that?
Only loop when the return value of scanf() is as expected (1).
for(i = 1; scanf("%d", &c) == 1; i++) {
...
}
Putting this together with some other ideas
#include <stdio.h>
#include <stdio.h>
int main(void) {
printf("Please enter a stream of numbers to make a set out of them:\n");
int *pSet = NULL; // Start with no allocation
size_t i = 0;
int c;
for (i = 0; scanf("%d", &c) == 1; i++) {
// +--------------------------- No cast needed.
// v v----------v Use sizeof de-referenced pointer
void *p = realloc(pSet, sizeof *pSet * (i + 1));
if (p == NULL) {
free(pSet);
return EXIT_FAILURE;
}
pSet = p;
pSet[i] = c;
}
for (size_t j = 0; j < i; j++) {
printf("%d ", pSet[j]);
}
free(pSet);
return 0;
}
There are a number of problems.
1) Terminate the loop when scanf fails instead of using EOF. Do that by checking that the return value is 1 (i.e. the number of input items
successfully matched)
2) Don't allocate memory until it's needed
3) Never do realloc directly into the target pointer - always use a temp variable.
Fixing this your code could be:
#include <stdio.h>
int main(void) {
int *pSet = NULL;
printf("Please enter a stream of numbers to make a set out of them: ");
printf("\n");
int i = 0;
int c;
while (1) {
if (scanf("%d", &c) != 1)
{
printf("Terminating input loop\n");
break;
}
int* tmp = realloc(pSet, sizeof(int)*(i+1));
if(tmp == NULL) {
printf("oh dear...\n");
break;
}
pSet = tmp;
pSet[i++] = c;
printf("%d ", c);
}
for (int j=0; j < i; ++j) printf("%d\n", pSet[j]);
free(pSet);
return 0;
}
Input:
1 2 3 4 5 6 7 stop
Output:
Please enter a stream of numbers to make a set out of them:
1 2 3 4 5 6 7
Terminating input loop
1
2
3
4
5
6
7
You should stop your loop when scanf fails. According to the manual:
On success, [scanf] return[s] the number of input items successfully matched and assigned; this can be fewer than provided for, or even zero, in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching failure occurs. EOF is also returned if a read error occurs. [...]
So you can turn your for loop into a while one.
#include <stdio.h>
#include <stdlib.h>
#define FAIL 0
int main() {
int *pSet = (int*) malloc(sizeof(int));
int c;
int i=0;
printf("Please enter a stream of numbers to make a set out of them: ");
while(scanf("%d", &c) == 1) {
pSet[i] = c;
pSetNew = (int*) realloc(pSet, sizeof(int)*(i+1));
if(pSetNew == NULL) {
free(pSet);
return FAIL;
} else {
pSet = pSetNew;
}
printf("%d ", c);
i++;
}
free(pSet);
}
But if you want a more robust piece of code, I suggest you to retrieve the answer as a string (NULL-terminated array of char), and then parse it with dedicated functions like strtol which let you check if the whole string is a valid entry, and not only the first characters.
Note: HengLi fixed a potential memory leak in the code sample above

Stop scanf loop if user enters a specific number (Not working) C

I've looked at multiple solutions but none of them worked for me.
I'm asking the user to enter numbers in a loop, but if the user enters a specific number the loop should break.
This is what I've got so far.
#include <stdio.h>
#include <stdlib.h>
#define MAXNUMBERS 5
int getNumbers(int array[])
{
int i;
int n = 0;
printf("Enter max. %d numbers, enter empty line to end:\n", MAXNUMBERS);
for (i = 0; i < MAXNUMBERS; i++)
{
scanf("%d", &array[i]);
fflush(stdin);
n++;
if (array[i] == '5')
{
break;
}
}
return n;
}
int main()
{
int array[MAXNUMBERS];
int amount_numbers;
amount_numbers = getNumbers(array);
printf("Numbers entered: %d\n", amount_numbers);
printf("First three: %d %d %d", array[0], array[1], array[2]);
return 0;
}
Input:
1
5
4
3
2
Output:
Numbers entered: 5
First three: 1 5 4
If the user enters 5 the loop should break.
I'm using 5 as an example, I later want it to do with an empty line. But it doesn't even work with 5.
It just keeps prompting the user to enter another number after he entered 5.
The actual problem is '5' != 5 the former is the character 5 which is in fact it's ascii value, and the latter is the number 5, since you are reading integers, i.e. using the "%d" specifier in scanf() you should use 5, but it would be better if it was just a int variable, and you could initialize it to any number you like before the loop starts.
Your loop is wrong anyway because if the user enters a non-numeric value then your program will invoke undefined behavior. Besides you already invoke undefined behavior with fflush(stdin), so
Remove fflush(stdin)1
7.21.5.2 The fflush function
If stream points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten data for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is
undefined.
So the behavior is undefined for an input stream like stdin, or even if the most recent operation was input.
You must check that the value was read properly, and then check in the loop condition if it equals the value you want to stop the loop with, try this
int readNumber()
{
int value;
printf("input a number > ");
while (scanf("%d", &value) == 1)
{
int chr;
printf("\tinvalid input, try again...\n");
do { /* this, will do what you thought 'fflush' did */
chr = getchar();
} ((chr != EOF) && (chr != '\n'));
printf("input a number > ");
}
return value;
}
int getNumbers(int array[])
{
int i;
int stop = 5;
printf("Enter max. %d numbers, enter empty line to end:\n", MAXNUMBERS);
array[0] = 0;
for (i = 0 ; ((i < MAXNUMBERS) || (array[i] == stop)) ; i++)
array[i] = readNumber();
return i;
}
1This is a quote from the C11 draft 1570.
if (array[i] == '5')
You're checking whether array[i] is equal to the ASCII value of the character '5'.
Remove the '' to make it compare against the integer 5.
You are checking if an integer is equal to the character '5', which is then being cast to an ascii value of '5'.
Try using this:
if (array[i] == 5)
Disregard everything!
I should have written
if (array[i] == 5)
without the quotes!
I'm an idiot!
I sat 2 hours at this error...

C - scanf has gone ROGUE

I have this c program where I am inputing a number N followed by N more numbers. For example, I'll enter 100 followed by 100 more numbers. For some reason, after so many inputs the scanf function will stop working properly. It's as if it has stopped taking input and will just continue one with whatever value is in size.
The use case I came up with is 100 1 2 3 4 5 6 7 8 9 10... (repeated ten times). then after three or four times of that I'll type in 100 10 9 8 7 6 5 4 3 2 1... (repeated ten times) and then there will be an infinite loop of print statements.
int main(int argc, const char * argv[]) {
int histogram[10000];
int i;
while (1) {
int *rectPtr = histogram;
int size;
scanf("%d", &size);
if (!size) return 0;
for (i = 0; i < size; ++i) {
scanf("%d", rectPtr);
rectPtr++;
}
printf("%d", 1);
printf("\n");
}
return 0;
}
Distrust infinite loops.
In a series of comments, I said:
You're not testing the return value from scanf(), so you don't know whether it is working. The pair of printf() statements is odd; why not write printf("%d\n", 1); or even puts("1");?
Your code does not test or capture the return value from scanf(), so you do not know whether scanf() is reporting a problem. As a general rule, test the return value of input functions to make sure what you thought happened did in fact happen. You could also print out the values read just after you read them:
if (scanf("%d", rectPtr) != 1)
{
fprintf(stderr, "scanf() failed\n");
return 1;
}
printf("--> %d\n", *rectPtr);
rectPtr++;
Similarly when inputting size. Also consider if (size <= 0) return 0;. And using fgets() plus `sscanf() can make reporting errors easier.
j.will commented:
It is great to know if scanf fails, but I want to know why it fails and prevent it from failing. How do I do that?
I responded:
I understand you'd like to know. With scanf(), the best you can do after a failure is usually to read all the characters that follow up to a newline or EOF, and if you want to know what went wrong, then you print those characters too, because scanf() leaves the last character that it read in the input buffer ready for the next input operation.
void gobble(void)
{
printf("Error at: <<");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
puts(">>");
if (c == EOF)
puts("<<EOF>>");
}
The first character in the output is what caused the failure.
See also How to use sscanf() in loops?
Hacking your code to match this:
#include <stdio.h>
static void gobble(void)
{
printf("Error at: <<");
int c;
while ((c = getchar()) != EOF && c != '\n')
putchar(c);
puts(">>");
if (c == EOF)
puts("<<EOF>>");
}
int main(void)
{
enum { MAX_VALUES = 10000 };
int histogram[MAX_VALUES];
int size;
while (printf("Number of items: ") > 0 && scanf("%d", &size) == 1 &&
size > 0 && size <= MAX_VALUES)
{
int *rectPtr = histogram;
for (int i = 0; i < size; ++i)
{
if (scanf("%d", rectPtr) != 1)
{
gobble();
return 1;
}
rectPtr++;
}
printf("size %d items read\n", size);
}
return 0;
}
IMO, you need to check the return value of scanf() for proper operation. Please check the below code. I have added some modifications.
To exit from the program, you need to press CTRL+ D which will generate the EOF. Alternatively, upon entering some invalid input [like a char instead of int] wiil also cause the program to beak out of while() llop and terminate.
I have put the sequence to check first scanf(). All others need to be checked, too.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, const char * argv[]) {
int histogram[10000] = {0};
int i;
int *rectPtr = histogram;
int size = 0;
int retval = 0;
printf("Enter the number of elements \n");
while ( (retval = scanf("%d", &size)) != EOF && (retval == 1)) {
rectPtr = histogram;
if (!size) return 0;
printf("Enter %d elements\n", size);
for (i = 0; i < size; ++i) {
scanf("%d", rectPtr); //check in a simmilar way to above
rectPtr++;
}
printf("%d\n", 1111111);
printf("Enter the number of elements: \n");
}
return 0;
}
The output of a sample run
[sourav#broadsword temp]$ ./a.out
Enter the number of elements: 2
Enter 2 elements
1
2
1111111
Enter the number of elements: 3
Enter 3 elements
1
2
3
1111111
Enter the number of elements: 9
Enter 9 elements
0
9
8
7
6
5
4
3
2
1111111
Enter the number of elements: r
[sourav#broadsword temp]$
histogram is declared to have size 10000. You say you do 100 1 2 3 ... repeated 10 times. If I correctly understand that uses 1000 slots in histogram.
If you repeat the test more than 10 times, you exhaust histogram and begin to write past the end of array causing undefined behaviour.
So you must either :
reset recPtr = histogram at each iteration
control recPtr - histogram + size <= sizeof(histogram) after reading size (IMHO better)
And as other said, you should always control input operations : anything can happen outside of your program ...

Resources