My program should first ask for the number of integers to read and dynamically allocate an array just big enough to hold the number of values I read. Then, I need to categorize these values into odd and even.
This is the code I've tried
#include <stdio.h>
#include <stdlib.h>
int main(void){
//declare variables
int i; //loop counter
int count; //integer amount from user
int j = 0; int k = 0;
// read in integer count from user
printf("enter the amount of numbers: ");
scanf("%d", &count);
// declare pointer
int *number = malloc(sizeof(int)*count);
int *evens = malloc(sizeof(int)*count);
int *odds = malloc(sizeof(int)*count);
// declare variable
//int odds_count = 0;
//int evens_count = 0;
//loop to read in numbers from user
for (i=0; i<count; i++){
printf("enter number %02d: ",i+1);
scanf("%d",(number+i));
printf("you entered %d\n", *(number+i)); //--- entered values are correct here
if (*(number+i)% 2 ==0){
*(number+i) = *(evens+j);
j++;
//evens_count++;
} else {
*(number+i) = *(odds+k);
k++;
}
printf("you entered %d\n", *(number+i)); //---entered values become 0
}
//print array elements
printf("\nEntered array elements are:\n");
for(i=count;i>0;i--)
{
printf("%d ",*(number+i));
}
printf("\n");
// print out even numbers
printf("even numbers: ");
for (i=0;i<j;i++){
printf("%5d",*(evens+i));
}
printf("\n");
// print out odd numbers
printf("odd numbers: ");
for (i=0;i<k;i++){
printf("%5d",*(odds+i));
}
printf("\n");
return 0;
}
No matter what input I enter, the output only displays 0.
E.g:
Input- 1, 2, 3
Output-
Evens: 0
Odds: 0 0
Please help me with this. Thanks in advance!
While getting the input from user, try putting an '&' symbol before your variable name. I think that should work.
scanf("%d",&(number+i));
Happy coding :)
Your biggest issues regarding assigning values occurs when you attempt to assign evens[j] and odds[j] to numbers[i] before the elements of either evens or odds have been initialized. Following your call to malloc for each evens and odds the block of memory allocated contains whatever garbage values happen to be in that memory region at the time of allocation. malloc does not initialize the content of the memory in any way and leave the values indeterminate. If you want to both allocate and zero all bytes, you can use calloc instead of malloc.
This problem occurs here:
if (*(number+i)% 2 ==0){
*(number+i) = *(evens+j);
j++;
//evens_count++;
} else {
*(number+i) = *(odds+k);
k++;
}
Look carefully, you check whether numbers[i] is even/odd with % 2 == 0, but then attempt to overwrite the value at numbers[i] with either evens[j] or odds[k] -- this is backwards. The intent would be to assign the value in numbers[i] to either evens[j] or odds[k], e.g.
if (number[i] % 2 ==0){
evens[j] = number[i];
j++;
//evens_count++;
} else {
odds[k] = number[i];
k++;
}
Next, your use of variables is jumbled. You don't need all the different i, j, k counters declared at the beginning of main(). For the past 20 years, since C99, you can declare the loop variable within the for loop declaration itself. This eliminates the chance that your use of your loop variable will conflict with another use of i, j, k somewhere else in the program.
You have count, odd_count & even_count, those are the only counters you need.
Further, you need to VALIDATE every User Input and every Allocation. Otherwise, you risk invoking Undefined Behavior with the slip of a keystroke or when (not "if") an allocation returns NULL. Validate every critical step.
Putting those measures to use, you can simplify your declaration to:
int count, /* integer amount from user */
odd_count = 0, /* odd count (initialized zero) */
even_count = 0, /* even count (initialized zero)*/
*number, /* declare pointers */
*evens,
*odds;
You can validate your input with:
/* read in integer count from user (VALIDATE every input) */
printf("enter the amount of numbers: ");
if (scanf("%d", &count) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
...
for (int i = 0; i < count; i++) { /* loop count times for input */
printf ("enter number %2d: ", i + 1);
if (scanf ("%d", &number[i]) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
if (number[i] % 2 == 0) /* assign, increment evens count */
evens[even_count++] = number[i];
else /* same for odds */
odds[odd_count++] = number[i];
}
And you can validate your allocations:
/* allocate count integers each pointer (VALIDATE every allocation) */
if ((number = malloc (count * sizeof *number)) == NULL) {
perror ("malloc-number");
return 1;
}
if ((evens = malloc (count * sizeof *evens)) == NULL) {
perror ("malloc-evens");
return 1;
}
if ((odds = malloc (count * sizeof *odds)) == NULL) {
perror ("malloc-odds");
return 1;
}
Then it is simply a matter of looping i = 0; i < count to output the number, i = 0; i < even_count to output evens and finally i = 0; i < odd_count to output odds, e.g.
puts ("\n numbers\n--------"); /* output each array on its own */
for (int i = 0; i < count; i++)
printf ("%8d\n", number[i]);
puts ("\n evens\n--------");
for (int i = 0; i < even_count; i++)
printf ("%8d\n", evens[i]);
puts ("\n odds\n--------");
for (int i = 0; i < odd_count; i++)
printf ("%8d\n", odds[i]);
And Finally, you can output all 3 arrays at once with:
/* output all arrays together */
puts ("\nnumbers even odd\n-------- -------- --------");
for (int i = 0; i < count; i++) { /* loop printing number */
printf ("%8d", number[i]);
if (i < even_count) { /* if i < even_count */
printf (" %8d", evens[i]); /* output evens */
if (i < odd_count) /* if odds too, output them */
printf (" %8d\n", odds[i]);
else
putchar ('\n'); /* no more odds output '\n' */
}
else if (i < odd_count) /* if only odds left, output */
printf ("%18d\n", odds[i]);
else
putchar ('\n');
}
At the end, don't forget to free the memory you allocate, e.g.
free (number); /* don't forget to free what you allocated */
free (evens);
free (odds);
Putting it altogether, you could do:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int count, /* integer amount from user */
odd_count = 0, /* odd count (initialized zero) */
even_count = 0, /* even count (initialized zero)*/
*number, /* declare pointers */
*evens,
*odds;
/* read in integer count from user (VALIDATE every input) */
printf("enter the amount of numbers: ");
if (scanf("%d", &count) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
/* allocate count integers each pointer (VALIDATE every allocation) */
if ((number = malloc (count * sizeof *number)) == NULL) {
perror ("malloc-number");
return 1;
}
if ((evens = malloc (count * sizeof *evens)) == NULL) {
perror ("malloc-evens");
return 1;
}
if ((odds = malloc (count * sizeof *odds)) == NULL) {
perror ("malloc-odds");
return 1;
}
for (int i = 0; i < count; i++) { /* loop count times for input */
printf ("enter number %2d: ", i + 1);
if (scanf ("%d", &number[i]) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
if (number[i] % 2 == 0) /* assign, increment evens count */
evens[even_count++] = number[i];
else /* same for odds */
odds[odd_count++] = number[i];
}
puts ("\n numbers\n--------"); /* output each array on its own */
for (int i = 0; i < count; i++)
printf ("%8d\n", number[i]);
puts ("\n evens\n--------");
for (int i = 0; i < even_count; i++)
printf ("%8d\n", evens[i]);
puts ("\n odds\n--------");
for (int i = 0; i < odd_count; i++)
printf ("%8d\n", odds[i]);
/* output all arrays together */
puts ("\nnumbers even odd\n-------- -------- --------");
for (int i = 0; i < count; i++) { /* loop printing number */
printf ("%8d", number[i]);
if (i < even_count) { /* if i < even_count */
printf (" %8d", evens[i]); /* output evens */
if (i < odd_count) /* if odds too, output them */
printf (" %8d\n", odds[i]);
else
putchar ('\n'); /* no more odds output '\n' */
}
else if (i < odd_count) /* if only odds left, output */
printf ("%18d\n", odds[i]);
else
putchar ('\n');
}
free (number); /* don't forget to free what you allocated */
free (evens);
free (odds);
}
Example Use/Output
$ ./bin/number_evens_odds
enter the amount of numbers: 10
enter number 1: 21
enter number 2: 22
enter number 3: 23
enter number 4: 24
enter number 5: 119
enter number 6: 121
enter number 7: 131
enter number 8: 140
enter number 9: 141
enter number 10: 143
numbers
--------
21
22
23
24
119
121
131
140
141
143
evens
--------
22
24
140
odds
--------
21
23
119
121
131
141
143
numbers even odd
-------- -------- --------
21 22 21
22 24 23
23 140 119
24 121
119 131
121 141
131 143
140
141
143
Look things over and let me know if you have further questions.
Related
Example: input: 420 50 -4
output: Numbers 3
Positive 2
Negative 1
and also for the same code:
input: 420 50 -4 7
output: Numbers 4
Positive 3
Negative 1
#include<stdio.h>
#define N 2
int main()
{
int a[N], i=0, n=0, k=0, z=0;
for(i=0; i<N; i++)
{
scanf("%d" , &a[i]);
if((a[i] >= -10000 && a[i] <= 10000 ))
n++;
if(a[i]>0)
k++;
if(a[i]<0)
z++;
}
printf("Numbers:%d \n", n);
printf("Positive:%d \n", k);
printf("Negative:%d \n", z);
return 0;
}
new issue
So the idea is this, I need my programm(mostly done by yano here) to only be able to load numbers ranging for -10000 to 10000 including border numbers, if other numbers would be loaded, the program should print the correct numbers, and ignore the incorrect (more like remove from array and replacing the element with the rest, which is correct, whilst reducing the total number of elements in the array)
example
input 140 -154161 20 30
output 140, 20, 30
Error: Input is outside interval!"
#include <stdio.h>
#include <stdlib.h>
#define INITIAL_SIZE 10
void
printArray (const int *myArray, size_t numsEntered)
{
int i, c = 0, k = 0, z = 0, s=0, l=0, sum=0, max, min;
float pk, pz, ps, pl, prumer;
for (size_t i = 0; i < numsEntered; i++) //does math
{
sum = sum + myArray[i];
if (i)
printf (", ");
printf ("%i", myArray[i]);
if ((myArray[i] >= -10000 && myArray[i] <= 10000))
c++;
if (myArray[i] > 0)
k++;
if (myArray[i] < 0)
z++;
if(myArray[i]%2==0)
s++;
else
l++;
max = myArray[0];
min = myArray[0];
if(myArray[i] > max)
{
max = myArray[i];
}
if(myArray[i] < min)
{
min = myArray[i];
}
}
if ((myArray[i] >= -10000 && myArray[i] <= 10000)) //checks if arrays are in range
{
prumer=(float) sum/2;
pk = (float) k / c;
pz = (float) z / c;
ps = (float) s / c;
pl = (float) l / c;
printf ("\n");
printf ("Pocet cisel: %d\n", c);
printf ("Pocet kladnych: %d\n", k);
printf ("Pocet zapornych: %d\n", z);
printf ("Procento kladnych: %.2lf\n", pk);
printf ("Procento zapronych: %.2lf\n", pz);
printf("Pocet sudych: %d\n", s);
printf("Pocet lichych: %d\n", l);
printf ("Procento sudych: %.2lf\n", ps);
printf ("Procento lichych: %.2lf\n", pl);
printf("Prumer: %.2lf\n", prumer );
printf("Maximum: %d\n", max);
printf("Minimum: %d\n", min);
}
if (myArray[0]<-10000 || myArray[0]>10000) //checks if first element is in wrong range
programm prints arror and returns 0
{
printf("\n");
printf ("Error: Vstup je mimo interval!");
}
}
int
main ()
{
int lastArray = 0, end = 0, b = 0, i=0;
size_t arraySize = INITIAL_SIZE;
size_t numsEnteredSoFar = 0;
int *myArray = malloc (sizeof (*myArray) * arraySize);// initially make room for 10
if (myArray == NULL)
exit (-1);
while (1)
{
int curEntry, size = sizeof (myArray) / sizeof (int);
char ch;
if (scanf ("%d", &curEntry) == 1)
{
b = curEntry;
end = numsEnteredSoFar;
ch = fgetc (stdin);
myArray[numsEnteredSoFar++] = curEntry;
if (numsEnteredSoFar == arraySize)
{
arraySize += INITIAL_SIZE;
int *temp = realloc (myArray, arraySize * sizeof (*myArray));
if (temp == NULL)
{
fprintf (stderr, "out of memory\n");
exit (-1);
}
else
{
myArray = temp;
}
}
}
for (size_t i = 0; i < numsEnteredSoFar; i++)
if((myArray[i]<-10000 || myArray[i]>10000)) //checks if input is in range if not exits
{
if (i) //my attempt for making this work
printf (", ");
printf ("%i", myArray[i]);
printf ("\n");
printf ("Error: Vstup je mimo interval!");
exit (-1);
}
if (ch == 10)
{
break;
}
}
printArray (myArray, numsEnteredSoFar);
free (myArray);
return 0;
}
There are several ways to solve this problem:
Declare an array that's large enough to accommodate the largest conceivable size of your data.
Include a size at the beginning of your data, and use that to malloc your array.
Use a data structure that doesn't depend on a fixed size, such as a linked list.
This example allows the user to enter numbers "indefinitely" without the need for prompting how many to enter. Of course, your computer only has so much RAM, so there is a limit, but not a practical limit. Essentially, you need to choose an initial size, then allocate more space dynamically when that size is reached.
#include <stdio.h>
#include <stdlib.h>
#define INITIAL_SIZE 10
void printArray(const int* myArray, size_t numsEntered)
{
for (size_t i=0; i<numsEntered; i++)
{
printf("myArray[%zu] = %d\n", i, myArray[i]);
}
}
int main(void)
{
size_t arraySize = INITIAL_SIZE;
size_t numsEnteredSoFar = 0;
int* myArray = malloc(sizeof(*myArray) * arraySize); // initially make room for 10
if (myArray == NULL) exit(-1); // whoops, malloc failed, handle this error how you want
while(1)
{
int curEntry;
printf("enter a number, or 'q' to quit: ");
if (scanf("%d", &curEntry) == 1)
{
// store in the array, increment number of entries
myArray[numsEnteredSoFar++] = curEntry;
// here you can check for positives and negatives, or
// wait to do that at the end. The point of this example
// is to show how to dynamically increase memory allocation
// during runtime.
if (numsEnteredSoFar == arraySize)
{
puts("Array limit reached, reallocing");
// we've reached our limit, need to allocate more memory to continue.
// The expansion strategy is up to you, I'll just continue to add
// INITIAL_SIZE
arraySize += INITIAL_SIZE;
int* temp = realloc(myArray, arraySize * sizeof(*myArray));
if (temp == NULL)
{
// uh oh, out of memory, handle this error as you want. I'll just
// print an error and bomb out
fprintf(stderr, "out of memory\n");
exit(-1);
}
else
{
// realloc succeeded, we can now safely assign temp to our main array
myArray = temp;
}
}
}
else
{
// the user entered 'q' (or anything else that didn't match an int), we're done
break;
}
}
// print the array just to show it worked. Instead, here you can
// loop through and do your comparisons for positive and negative,
// or you can continue to track that after each entry as you've
// shown in your code
printArray(myArray, numsEnteredSoFar);
free(myArray);
return 0;
}
Demo
Several parts to the answer.
Either declare a nice, big array, bigger than you'll ever need, or, prompt the user for the size, and then use that user-entered size to declare or allocate the array. (This is a popular strategy, but it's a lousy user experience, since the user shouldn't need to know or say how many numbers they're going to enter.)
Check the return value of scanf. If the return value isn't 1, this means that scanf failed, and didn't input a number. You can take this as an indication that the user stopped entering numbers.
Have two variables: the size of the array, and the number of numbers actually entered. You set the number of numbers actually entered by noticing when scanf failed. Then, later, when you work with the date in the array, you don't do for(i = 0; i < N; i++), you do for(i = 0; i < number_of_numbers; i++).
If you don't want to ask the user to explicitly enter the number of numbers, and you don't want to pick a "big enough" size in advance (either because you don't want to waste memory, or because you want to make sure the user can enter a lot of inout, potentially more than any number you picked), it's possible to dynamically reallocate an array bigger and bigger as the user enters more and more data, but that's an advanced topic.
I am doing coding exercise in HackerRank. In the Variable Sized Arrays exercise of C++, I tried to do it with C, but I couldn't get it right.
My code sometimes pass the simple test case 0, but sometimes not. The code was exactly the same but came out with different answer.
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int n, q;
scanf("%d%d", &n, &q);
int *p_arr[n];
if (n > 0) {
for (int i = 0; i < n; i++) {
int tmp;
scanf("%d", &tmp);
int tmp_arr[tmp];
p_arr[i] = tmp_arr;
for (int j = 0; j < tmp; j++) {
int value;
scanf("%d", &value);
p_arr[i][j] = value;
printf("%d ", p_arr[i][j]);
}
printf("\n");
}
}
if (q > 0) {
for (int i = 0; i < q; i++) {
int row, col;
scanf("%d%d", &row, &col);
printf ("%d %d\n", row, col);
int answer = p_arr[row][col];
printf("%d\n", answer);
}
}
return 0;
}
This was the wrong answer I got
1 5 4
1 2 8 9 3
0 1
21973
1 3
32764
I didn't know where the 21973 and 32764 came from.
This was the answer I expected
1 5 4
1 2 8 9 3
0 1
5
1 3
9
Sometimes I got the wrong answer, sometimes I got the correct. Why was that?
Thanks a lot!
Continuing from the comments, if the exercise involves a Variable Length Array, then it should be written in C because the C++ standard does not provide VLAs (and they have been made optional beginning in C11 after being added with C99)
The primary problem with your code (aside from a complete failure to allocate the inputs) is that it invokes Undefined Behavior because int tmp_arr[tmp] goes out of scope at the end of the for loop. What you assign with p_arr[i] = tmp_arr; no longer exists outside the loop because tmp_arr no longer exists. Any attempt to access a value after it has gone out of scope invokes Undefined Behavior, see Undefined, unspecified and implementation-defined behavior
Every time you handle input, you must validate the input succeeded and the value obtained is within a valid range. For instance both n and q must be positive values. Using scanf you could do (minimally)
if (scanf("%d%d", &n, &q) != 2 || n <= 0 || q <= 0) {
fputs ("error: invalid format or value.\n", stderr);
return 1;
}
The above validates that 2 inputs were received and that both are positive values.
In order to preserve the pointer assigned with p_arr[i] = tmp_arr;, tmp_arr must be an allocated type to handle an unknown tmp number of elements, or it must be declared outside the loop (and large enough to handle all anticipated values -- which given that tmp is read as input -- doesn't seem like the intended approach). You cannot declare tmp_arr static either as there would only be one instance and assigning it repeatedly to p_arr[i] would leave all elements of p_arr[i] pointing to the same place.
Simply allocate for tmp_arr and then the assignment to p_arr[i] will survive for the life of the program or until it is freed, e.g.
int *tmp_arr = calloc (tmp, sizeof *tmp_arr); /* allocate */
if (!tmp_arr) { /* validate every allocation */
perror ("calloc-tmp_arr");
return 1;
}
p_arr[i] = tmp_arr;
(note: calloc was used above to zero the new memory allocated. You can use malloc instead since the code assigns to each element)
Putting it altogether and adding (minimal) validation, you could do something similar to:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int n, q; /* validate EVERY input */
if (scanf("%d%d", &n, &q) != 2 || n <= 0 || q <= 0) {
fputs ("error: invalid format or value.\n", stderr);
return 1;
}
int *p_arr[n]; /* array of n-pointers to int */
for (int i = 0; i < n; i++) {
int tmp;
if (scanf("%d", &tmp) != 1 || tmp <= 0) { /* validate! */
fputs ("error: invalid input - tmp.\n", stderr);
return 1;
}
int *tmp_arr = calloc (tmp, sizeof *tmp_arr); /* allocate */
if (!tmp_arr) { /* validate every allocation */
perror ("calloc-tmp_arr");
return 1;
}
p_arr[i] = tmp_arr;
for (int j = 0; j < tmp; j++) {
int value;
if (scanf("%d", &value) != 1) { /* validate! */
fputs ("error: invalid input - value.\n", stderr);
return 1;
}
p_arr[i][j] = value;
printf ("%d ", p_arr[i][j]);
}
putchar ('\n'); /* no need to printf a single-character */
}
for (int i = 0; i < q; i++) {
int row, col; /* validate! */
if (scanf ("%d%d", &row, &col) != 2 || row < 0 || col < 0) {
fputs ("error: invalid input, row or col.\n", stderr);
return 1;
}
printf ("%d %d\n%d\n", row, col, p_arr[row][col]);
}
for (int i = 0; i < n; i++)
free (p_arr[i]);
return 0;
}
(Note: untested as no hackerrank input was provided)
Look things over and let me know if you have further questions.
I'm looking to draw a line of char's if the argument is less than 0 must print 50 chars on the line. If argument is over 50, must print first 50 chars, new line then continue to print the chars until argument becomes 0.
When the argument is over 50 I don't know how to print the first 50 chars on one line, then the remaining chars on a new line
void drawLine(char c, int n){
if(n<0){
for(int i =0; i < 50; i++){
printf("%c",c);
}
}
else if(n>50){
for(int i=0; i<50;i++){
printf("%c",c);
n--;
if (n!=0 && i % 50 == 0){
printf("\n");
for(int i= 0; i<50;i++){
printf("%c",c);
}
break;
}
}
}
else{
for(int i=0;i<n;i++){
printf("%c",c);
}
}
printf("\n\n");
}
int main(void) {
drawLine('*',55);
return 0;
}
I tried to keep as much of your original code as possible whilst making the code clearer and better readable. The problem for n greater than 50 was that if (n != 0 && i % 50 == 0) is always true for the first iteration with n something above 50 and i = 0, since 0 % 50 = 0. Therefore it only printed one instead of 50 elements on the first line.
void drawLine (char c, int n) {
//n less than zero equals n = 50
if (n < 0) {n = 50;}
//if printable on first line
if (n <= 50) {
for (int i = 0; i < n; i++) {
printf("%c",c);
}
}
else {
//print 50 chars on first line
for (int i = 0; i < 50; i++) {
printf("%c",c);
}
//reduce n by this number
n = n - 50;
printf("\n");
//print remaining number of chars
for (int i = 0; i < n; i++) {
printf("%c",c);
}
}
printf("\n\n");
}
If you want to begin a new line for every 50 elements, a loop starting a new line every 50 iterations is the way to go.
You can greatly simplify your logic just by thinking about the problem a little differently.
First, never use the variadic printf function to output a single character -- that is the wrong tool for the job. Instead use putchar() or fputc which are character-oriented output functions. [1]
When working with void functions, there is no reason you cannot return from any point within the function. You can use this to your advantage to avoid nesting if{} else{}... Simply return after you complete the needed block of code.
Next, don't use magic numbers throughout your code. If you need a constant for 50, then #define one, e.g.
#define LNSZ 50
That way if you decide to make your line size 60, there is only one place, easily accessible, at the top of your code where you can make the change. No need to go picking though multiple for loop declarations to change each loop limit.
Putting those pieces together, you can rewrite your drawline function as follows (note: traditionally C avoid the use of camelCase function names)
void drawline (char c, int n)
{
if (n < 0) { /* handle value < 0 */
for (int i = 0; i < LNSZ; i++) /* output LNSZ chars */
putchar (c);
putchar ('\n'); /* tidy up with '\n' */
return; /* all done */
}
for (int i = 0; i < n; i++) { /* output n chars */
if (i && i % LNSZ == 0) /* after every 50 \n */
putchar ('\n');
putchar (c); /* output char */
}
putchar ('\n'); /* tidy up with '\n' */
}
Putting together a short example to exercise the function by allowing the line size to be specified as a command line argument (and using a default of 55 if no argument is given), you could do something similar to the following:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
#define LNSZ 50
void drawline (char c, int n)
{
if (n < 0) { /* handle value < 0 */
for (int i = 0; i < LNSZ; i++) /* output LNSZ chars */
putchar (c);
putchar ('\n'); /* tidy up with '\n' */
return; /* all done */
}
for (int i = 0; i < n; i++) { /* output n chars */
if (i && i % LNSZ == 0) /* after every 50 \n */
putchar ('\n');
putchar (c); /* output char */
}
putchar ('\n'); /* tidy up with '\n' */
}
int main (int argc, char **argv) {
errno = 0;
long v = argc > 1 ? strtol (argv[1], NULL, 10) : 55;
if (errno) { /* minimal validation of any strtol conversion */
perror ("invalid conversion");
return 1;
}
if (v < INT_MIN || INT_MAX < v) { /* validate v in int range */
fprintf (stderr, "error: value exceeds storable int.\n");
return 1;
}
drawline ('*', (int)v);
return 0;
}
Example Use/Output
$ ./bin/drawline
**************************************************
*****
$ ./bin/drawline 50
**************************************************
$ ./bin/drawline -1
**************************************************
$ ./bin/drawline 10
**********
$ ./bin/drawline 151
**************************************************
**************************************************
**************************************************
*
Look things over than let me know if you have any further questions.
footnote [1] Yes, a smart compiler may optimize printf to putchar for you, but do not rely on the compiler to fix lazy coding habits.
Yes, hello. I'm really new to programming. I genuinely need help because I would like to both understand what I'm doing wrong and also pass my class.
I'm in a Intro to Programming class and my assignment is to create a program that uses an array to store percentage grades in the range from 0 to 100 (inclusive). The program should allow the user to indicate when they are done entering grades. When the user is done entering grades, the program should print out the grades entered.
I have a running code, compiled in Code::Blocks. But my questions/problems are:
A.) What's the best way to tell C when the user is done? Should I
Leave the code as is and let any key be hit?
Add a specific variable like 'done'?
Do something else?
B.) How do I print only the grades that have been entered without it going through all 100 slots? I can't for the life of me find the solution.
Any and all suggestions welcome and appreciated!!!
int i = 0;
float percentScore[100];
for (i = 0; i < 10; i++) {
printf("Grade %d: ", i + 1);
scanf("%f", &percentScore[i]);
}
for (i = 0; i < 10; i++) {
printf("\n%.2f%%", percentScore[i]);
}
return 0;
Your choices for A) are not mutually exclusive; the first is something the user can do, the second is a way to represent that in the code. As such, you could reasonably do both.
As for B), you need a way to represent the number of grades entered (hint: a variable); this can then be used to control how many get printed.
Here is a simple approach for your problem:
for each input, read a full line from the user ;
try and convert this line as a number with sscanf() ;
if the conversion fails, consider the input exhausted ;
if the value is out of bounds, restart this input.
The user can thus signal the end of the list by entering a blank line.
Here is a example:
#include <stdio.h>
#define GRADE_NB 100
int main(void) {
int i, n;
float grade, percentScore[GRADE_NB];
char buf[100];
for (n = 0; n < GRADE_NB;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
return 0;
}
If the potential number of inputs is not limited, you must allocate the array from the heap and reallocate it as more inputs are gathered. Here is a simple solution for this where the array is reallocated for each input:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i, n;
float grade, *percentScore;
char buf[100];
for (n = 0, percentScore = NULL;;) {
printf("Grade %d: ", n + 1);
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file reached: input exhausted */
break;
}
if (sscanf(buf, "%f", &grade) != 1) {
/* not a number: input exhausted */
break;
}
if (grade >= 0 && grade <= 100) {
/* value is OK, grade accepted */
percentScore = realloc(percentScore, (n + 1) * sizeof(*percentScore));
if (percentScore == NULL) {
printf("allocation failed\n");
return 1;
}
percentScore[n] = grade;
n++;
} else {
printf("Invalid grade: %f\n", grade);
}
}
for (i = 0; i < n; i++) {
printf("%.2f%%\n", percentScore[i]);
}
free(percentScore);
return 0;
}
The program I am writing to take a number and display that number as a calculator would display it (shown below) is compiling with no issues, but when I try to run it, I am able to input my number, but nothing happens. It seems like it is "hanging", since no further output is shown as I would have expected. Might anyone know what the problem is?
#include <stdio.h>
#define MAX_DIGITS 20
char segments[10][7] = /* seven segment array */
{{'1','1','1','1','1','1','0'}, /* zero */
{'0','1','1','0','0','0','0'}, /* one */
{'1','1','0','1','1','0','1'}, /* two */
{'1','1','1','1','0','0','1'}, /* three */
{'0','1','1','0','0','1','1'}, /* four */
{'1','0','1','1','0','1','1'}, /* five */
{'1','0','1','1','1','1','1'}, /* six */
{'1','1','1','0','0','0','0'}, /* seven */
{'1','1','1','1','1','1','1'}, /* eight */
{'1','1','1','0','0','1','1'}};/* nine */
char digits[3][MAX_DIGITS * 4]; /* digits array */
int i, j; /* count variables */
int adjust; /* output formatting */
int main(void) {
clear_digits_array();
int digit[20];
for (i = 0; i < 20; i++) {
digit[i] = 0;
}
int count = 20;
int position = 0;
printf("Enter a number: ");
int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&digit[0],
&digit[1],
&digit[2],
&digit[3],
&digit[4],
&digit[5],
&digit[6],
&digit[7],
&digit[8],
&digit[9],
&digit[10],
&digit[11],
&digit[12],
&digit[13],
&digit[14],
&digit[15],
&digit[16],
&digit[17],
&digit[18],
&digit[19]); //NOTHING HAPPENS AFTER HERE
printf("Got input, number is %d", number);
while (count > 0) {
printf("Reading digits, count is %d", count);
process_digit(digit[20 - count], position);
position++;
count--;
}
print_digits_array();
printf("\n");
return 0;
}
void clear_digits_array(void) {
/* fill all positions in digits array with blank spaces */
for (i = 0; i < 3; i++) {
for (j = 0; j < (MAX_DIGITS * 4); j++) {
digits[i][j] = ' ';
}
}
}
void process_digit(int digit, int position) {
/* check each segment to see if segment should be filled in for given digit */
for (i = 0; i < 7; i++) {
printf("Processing digit %d at position %d, i is %d", digit, position, i);
if (segments[digit][i] == 1) {
switch (i) {
case 0: digits[0][(position * 4) + 1] = '_';
break;
case 1: digits[1][(position * 4) + 2] = '|';
break;
case 2: digits[2][(position * 4) + 2] = '|';
break;
case 3: digits[2][(position * 4) + 1] = '_';
break;
case 4: digits[2][(position * 4) + 0] = '|';
break;
case 5: digits[1][(position * 4) + 0] = '|';
break;
case 6: digits[1][(position * 4) + 1] = '_';
break;
}
}
}
}
void print_digits_array(void) {
/* print each character in digits array */
for (i = 0; i < 3; i++) {
for (j = 0; j < (MAX_DIGITS * 4); j++) {
printf("%c", digits[i][j]);
}
printf("/n");
}
}
Your code includes:
printf("Enter a number: ");
int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&digit[0],
&digit[1],
&digit[2],
&digit[3],
&digit[4],
&digit[5],
&digit[6],
&digit[7],
&digit[8],
&digit[9],
&digit[10],
&digit[11],
&digit[12],
&digit[13],
&digit[14],
&digit[15],
&digit[16],
&digit[17],
&digit[18],
&digit[19]); //NOTHING HAPPENS AFTER HERE
Have you entered twenty separate digits? If not, scanf() is waiting for you to type some more numbers.
Note that the return value from scanf() is the number of successfully converted numbers (0..20 in the example), not the value you entered.
Is that the issue? I tried to make it such that the maximum amount of numbers the user could enter was 20, and if any more were entered they would be ignored, or if fewer were entered, it would only consider those (say, 5 were entered, then only the 5 would be used). Is there an easier way to do this sort of thing then?
Yes, I think that's the issue.
There are probably several easier ways to do it. I'd be tempted to use:
char buffer[22]; // 20 digits, newline, null
if (fgets(buffer, sizeof(buffer), stdin) != EOF)
{
size_t len = strlen(buffer);
if (len >= sizeof(buffer) - 1)
{
fprintf(stderr, "You entered too long a string (maximum 20 digits)\n");
exit(EXIT_FAILURE);
}
if (len > 0)
buffer[--len] = '\0'; // Zap newline — carefully
for (int i = 0; i < len; i++)
{
if (!isdigit(buffer[i]))
{
fprintf(stderr, "Non-digit %c found\n", buffer[i]);
exit(EXIT_FAILURE);
}
}
...and from here, process the digits in buffer, one at a time...
...Use buffer[i] - '0' to get a number 0..9 from the character in buffer...
}
Another option is to use a long long number, but that only gives you up to 18 digits (signed) or 19 digits (unsigned), with some values of 19 or 20 also within range. You'd then strip the digits out of the number using division and modulus operations.
long long value;
if (scanf("%lld", &value) == 1)
{
if (value < 0)
...error processing...
do
{
int digit = value % 10;
value /= 10;
...process digit...
} while (value > 0);
}
This has some merits, but in practice, I'd be tempted to use fgets() to read a line of input, and either sscanf() or strtoll() to convert and validate the number. That isn't as simple as it looks; the error returns from strtoll(), in particular, are many and subtle, and none of the scanf() family handle overflowing numbers gracefully. You could constrain the scanf() though with %18lld so that no more than 18 digits are read, but that would mean that if the user typed 19 or more digits, you'd get the leftovers on the next attempt to read with scanf(). So, handling scanf() is not simple either, especially if you need to convert multiple numbers in a single run of the program.
With those caveats out of the way, you can usually do a 'good enough' job with a sensible person providing the input. It is the process of making a program bomb-proof (foolproof — as in, proof against fools) that is hard. I find meaningful error reporting easier when I can report the whole string that was read in (as with fgets()); with scanf(), you can't see the characters that were entered and consumed before something went wrong.
use GDB, here is introduction for it http://www.gnu.org/software/gdb/
look into this tutorial too http://www.cs.cmu.edu/~gilpin/tutorial/
int number = scanf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&digit[0],
&digit[1],
&digit[2],
&digit[3],
&digit[4],
&digit[5],
&digit[6],
&digit[7],
&digit[8],
&digit[9],
&digit[10],
&digit[11],
&digit[12],
&digit[13],
&digit[14],
&digit[15],
&digit[16],
&digit[17],
&digit[18],
&digit[19]);
I don't think this is a good idea use loop here
for (i = 0; i < 20; i++)
scanf("%d",&digit[i]);
And if you need the number
then do like this
int number = i; when loop finishes.
You can also try this
char buf[12];
while((c=getchar())!=EOF && i < 20)
{
buf[j++] =c;
if((c == '\n' || c == ' ' || c == '\t') && (sscanf(buf,"%d",&digit[i])) == 1)
{
i++;
j = 0;
}
}
For EOF you will have to press CTRL+D
In this way you can take 20 or less integers