Storing and Iterating through user inputs in C - c

The program below asks the user to input 10 integer numbers and stores the user inputs in a corresponding array of 10 ints. When an input is done it should iterate through the already existing user inputs and print them out. I want to iterate through the stored values in storedinputs by using a function like strlen(), however the stored values are not strings but are integers. How could i do such a thing.
int main(void) {
int storedinputs[10] = {0};
int input;
for(int i = 0; i < 10; i++) {
printf("\nPlayer input:");
scanf("%d", &input);
storedinputs[i] = input;
for(int s = 0; s < strlen(storedinputs); s++) {
printf("Inputs %d", storedinputs);
}
}
return 0;
}
Expected Output:
Player input: 1
Inputs: 1
Player input: 3
Inputs: 1 3
Player input: 60
Inputs: 1 3 60

You cannot use the function strlen() because storedinputs is an array of integers. If you want to print the stored values every time you insert a new one you should edit the for loop condition, as suggested by Weather Vane in the comments, as follows:
for(int s = 0; s <= i; s++)
The variable i indicates the number of the cell containing the last number added.

Here is the fixed code including error checking.
Superfluous input needs to be skipped over (while(fgetc(stdin) != '\n');)
scanf has insufficient error checking capabilities. Use combination of fgets and strtol.
In the internal loop you need to terminate when outer loop counter is reached
You should not count invalid input (Therefore, I replaced outer for loop by a while loop)
You should not store invalid inputs in your array
You need to index your stored inputs when printing them out
--
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
// In contrast to #define this provides a nice means for grouping constants
// and it can be changed into a typedef, later on
// Furthermore, it's a compiler aware constant
enum {INPUT_COUNT = 10, MAX_INPUT_LENGTH = 20};
int main(void) {
int input_count = 0; // The count of valid inputs
char input[MAX_INPUT_LENGTH + 1] = {0}; // The string buf for one input
int converted_input; // Result of integer conversion
int storedinputs[INPUT_COUNT] = {0}; // Array with valid results
char *endptr; // Needed for strtol error checking
while(input_count < 10) { // Loop over 10 valid inputs
printf("\nPlayer input (Enter single integer value):");
fgets(input, sizeof(input), stdin);
printf("Got input: %s\n", input); // input contains '\n', already
// If input was longer than MAX_INPUT_LENGTH, get rid of remains
if (input[strlen(input) - 1] != '\n') {
while(fgetc(stdin) != '\n');
}
// Reset errno, so strtol returns a fresh value
errno = 0;
converted_input = strtol(input, &endptr, 10);
// The errno is set if input is out of range
if (errno) {
perror("Conversion error");
continue;
}
// Here we have invalid characters present in the input
if ( (endptr == input) || (*endptr != '\n') ) {
printf("Please enter single integer!\n");
continue;
}
// Everything fine, so we can store result
storedinputs[input_count] = converted_input;
// Now we output all valid inputs, up to now
printf("Inputs: ");
for(int s = 0; s <= input_count; s++) {
printf("%d ", storedinputs[s]);
}
printf("\n");
++input_count;
}
return 0;
}
Output:
Player input (Enter single integer value):12
Got input: 12
Inputs: 12
Player input (Enter single integer value):13
Got input: 13
Inputs: 12 13
Player input (Enter single integer value):14
Got input: 14
Inputs: 12 13 14
Player input (Enter single integer value):1324567543245678654324567
Got input: 13245675432456786543
Conversion error: Numerical result out of range
Player input (Enter single integer value):asdc
Got input: asdc
Please enter single integer!
Player input (Enter single integer value):
Got input:
Please enter single integer!
Player input (Enter single integer value):12 12 12
Got input: 12 12 12
Please enter single integer!
Player input (Enter single integer value):1
Got input: 1
Inputs: 12 13 14 1
Player input (Enter single integer value):2
Got input: 2
Inputs: 12 13 14 1 2
Player input (Enter single integer value):3
Got input: 3
Inputs: 12 13 14 1 2 3
Player input (Enter single integer value):4
Got input: 4
Inputs: 12 13 14 1 2 3 4
Player input (Enter single integer value):5
Got input: 5
Inputs: 12 13 14 1 2 3 4 5
Player input (Enter single integer value):67
Got input: 67
Inputs: 12 13 14 1 2 3 4 5 67
Player input (Enter single integer value):7
Got input: 7
Inputs: 12 13 14 1 2 3 4 5 67 7
OK, 10 inputs have been made

Related

Input ints separated by whitespace and pass them to an int array

I'm trying to write a program in C where the user inputs a defined number of ints (in this case 5 ints) separated by whitespaces. Then, the input is stored in an int array so, lastly, it can be stored in a char array.
As an example of how the program is intended to work, when it asks for an input:
Input: 20 5 63 4 127
The output of the program should be:
Output: 20 5 63 4 127
This is what I've written so far, but I don't know how to get the input transformed into an int array. Note that I know the length of the input beforehand (in this case, as said above, 5 ints).
// Input: 20 5 63 4 127
// Ask for user input.
// Store the input in this int array.
int input_int_array[5];
unsigned char char_array[5];
for(int i=0;i<5;i++)
{
char_array[i]=input_int_array[i];
printf("%d ", char_array[i]);
}
// Should print: 20 5 63 4 127
You are probably expected to use scanf() to read user input as integers into an array of int:
#include <stdio.h>
int main() {
int input_int_array[5];
// Ask for user input.
printf("input 5 numbers: ");
for (int i = 0; i < 5; i++) {
// Store the input into the array.
if (scanf("%d", &input_int_array[i]) != 1)
return 1;
}
// Output the contents of the array:
for (int i = 0; i < 5; i++) {
printf("%d ", input_int_array[i]);
}
printf("\n");
return 0;
}

Facing problems with the atoi function if used repeatedly

I have to find the frequency of digits {0,1,2,3,4,5,6,7,8,9} in a given string, I'm using atoi function to convert the character to an integer and I'm having problems with the atoi function when the input string is large (tried this with different test cases of varying length),
for example if the input string is
1v88886l256338ar0ekk
my code works properly and the answer is
1 1 1 2 0 1 2 0 5 0
where the 1st digit indicates the frequency of 0 and so on upto 9,
but if the input string is
9139f793308o0lo66h6vc13lgc697h0f6c32lu84445972k0o0l033od17c083yn5051d6j319hyo8j939n28d913015ns6zx5653x01211x12ch2526o65sg7xw6302141q9203s22l336319ll9yx4b597mr318a7943906750j4u152067nq83ne9f24thu96yd05173l47c803roxci45615f0w53i1sz913jj6za733l73tw6r66mq6p44sfhjr26h8e801z8zlcx2l1e65r2879xj3w3acv216196uq158o663y7oz2i5378v0v5w17762451t424352m23026r9o202i9785382o159e4gu1c8561157z5f1vqs5755465b8u728u956434mv944885li456628a994u7j5278m269n1pk8e46940q834h06il6h447888tr7ig72z10fe09k5g98h9bgt6z40v42s16pt6k3l3v45i83i01b9448g554741w766f2q7v31i085488h060e710p53076c6nm98pi946g8j2n6j8x29qa1ad48172y0u4818121p686bud89741201p54087u56g8scerv9pvhuo09re477zfb224i2c1325bj58jx4bk7b009f6446j5i95474p266i503r670n631x6940gwl71ejbx47imx576129248901765rnpu6l80084t0j1839f5y3409w2n403fu6ogw1170jmb6o5l520vg0703e0
upon reaching the end of the string the atoi function returns wrong values
for example,
my code uses atoi to convert char text to an integer and stores it into int num
at the beginning the function works fine,
text is 9 num is 9
text is 1 num is 1
text is 3 num is 3
text is 9 num is 9
text is 7 num is 7
text is 9 num is 9
text is 3 num is 3
text is 3 num is 3
text is 0 num is 0
text is 8 num is 8
text is 0 num is 0
.
.
.
and upon nearing the very end of the string the function returns
.
.
.
text is 2 num is 2
text is 4 num is 4
text is 0 num is 0
text is 3 num is 30
text is 6 num is 60
text is 1 num is 10
text is 1 num is 10
text is 7 num is 70
text is 0 num is 0
text is 6 num is 61
text is 5 num is 51
text is 5 num is 51
text is 2 num is 21
text is 0 num is 1
text is 7 num is 71
text is 0 num is 1
text is 0 num is 1
text is 3 num is 31
If I replace int num = atoi(&text) with int num = text - '0' my program works perfectly for all test cases,
so can someone please tell me what went wrong and whether I have used the function incorrectly.
Please keep in mind I just want to know why atoi didn't work, hence I'm not looking for replacements for the function.
I've included the snippet of my code below
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#include <ctype.h>
int main() {
int arr[10] = {0};
char text;
text = getchar();
while(text != EOF)
{
if(isdigit(text))
{
printf("text is %c ",text);
int num = atoi(&text);
printf("num is %d\n ",num);
for(int i =0; i<10;i++)
{
if(num==i)
{
arr[i]++;
//printf("arr[%d] is %d\n", i,arr[i]);
break;
}
}
}
text = getchar();
}
for(int i=0; i<10;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
Thanks in advance for taking the time to read and answer my question
Per the atoi() documentation in the C standard:
The atoi, atol, and atoll functions convert the initial portion of the string pointed to by nptr to int, long int, and long long int representation, respectively.
Note the bolded part.
Given
char text;
this code invokes undefined behavior because the address passed to atoi() is not that of a string:
int num = atoi(&text);
One fix would be:
char text[2];
text[1] = '\0';
// getchar() returns int, not char, in order
// to handle EOF properly
int input = getchar();
while(input != EOF)
{
text[0] = input;
if(isdigit(text[0]))
{
printf("text is %s ",text);
int num = atoi(text);
That ensures that a string (a nul-terminated series of char) is passed to atoi().
you don't need atoi() since you are dealing with single characters, not with strings
getc()returns an int [0 .. 255 for actual characters, -1 for EOF]
you can avoid a lot of {} braces by using break and continue
#include <stdio.h>
#include <ctype.h>
int main() {
int arr[10] = {0};
int text, num;
while(1) {
text = getchar();
if (text == EOF) break;
if (!isdigit(text)) continue;
printf("text is %c ", text);
num = text - '0'
printf("num is %d\n ",num);
arr[num]++;
//printf("arr[%d] is %d\n", num, arr[num]);
}
for(int i=0; i<10;i++)
{
printf("%d ",arr[i]);
}
return 0;
}

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 ...

fgets inside of a For loop causing strange behavior

I'm trying to get user input using fgets and some funky (not correct) things are happening and I can't seem to understand why.
The program is run with an argument that indicates how many values the user is to input.
Here is how the program is supposed to run:
./a.out 6
Enter 6 integer values to place in tree:
5
4
3
2
1
6
Input values:
5
4
3
2
1
6
If I have 1 as the argument, it doesn't even allow me to enter an input, and where did the 0 come from?
./a.out 1
Enter 1 integer values to place in tree:
Input values:
0
If I have 2 as the argument, it only allows me to enter 1 input and the phantom 0 appears again.
./a.out 2
Enter 2 integer values to place in tree:
1
Input values:
1
0
If I have 3 or more arguments, it functions correctly.
Here's the source:
int main (int argc, const char* argv[]){
int numIntegers;
char buffer[20];
if (argc == 1){
printf("Usage: a.out #\n");
return EXIT_FAILURE;
}
else{
numIntegers = atoi(argv[1]);
if (numIntegers <= 0){
printf("# must be greater than 0\n");
return EXIT_FAILURE;
}
else{
int intArray[numIntegers];
printf("Enter %d integer values to place in tree: \n", numIntegers);
for (int i = 0; i < numIntegers; i++){
fgets(buffer, numIntegers, stdin);
intArray[i] = atoi(buffer);
}
printf("Input values:\n");
for (int i = 0; i < numIntegers; i++){
printf(%d\n", intArray[i]);
}
}
}
}//end main
The size argument to fgets() refers to the size of buffer, which should be 20 in your case.
fgets(buffer, sizeof(buffer), stdin);
By the way, your code won't actually compile.
printf(%d\n", intArray[i]); // missing a quotation mark

C stop at enter key

I'm learning C in ansi c and I have a question.
I what to stop reading from the console when the user prints enter.
Ideally the user will enter this
1 2 3 4 5
and right after typing 5 the program would output
1
2
3
4
5
I have this code:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 5
int main()
{
int vector[SIZE] = {0}, number, counter = 0,i;
while (scanf("%d", &number) != EOF && counter < SIZE){
vector[counter] = number;
counter++;
}
for (i = 0; i < counter; i++){
printf("%d\n", vector[i]);
}
return 0;
}
Now, the program if I input 1 2 3 4 5 and then hit ENTER, it does not stop and if I type 1 2 3 4 5 6 it program stops.
Two things.
I believe the condition to scan until EOF it's not doing nothing. Second, program stops just because the counter < SIZE
So, how can I stop after user hits enter?
thanks
One option is to swap the order of your conditions:
while (counter < SIZE && scanf("%d", &number) != EOF){
As the conditions are evalulated left-to-right, your program waits for new input (via scanf(%d...)) before it evaluates counter < SIZE. This change would cause the program to immediately exit the while loop after the 5 is typed, BEFORE a user presses enter, as it evaluates counter < SIZE after the 5 is processed.
(If you choose this option, you will also want to print an endline character before you begin to repeat the numbers, as the user will not have pressed enter before it begins printing)
If you want the program to exit the loop when the user presses enter, you'll have to change your scanf. scanf(%d... reads a digit, and an endline character is not a digit.
Here's one approach off the top of my head (warning, untested):
int number;
char nl = 0;
while (counter < 5 && scanf("%d%c", &number, &nl) != EOF)
{
...
/**
* If we picked up a newline, exit the loop.
*/
if (nl == '\n')
break;
}
Try checking the last character of input to see if its a \n. ENTER does not constitute EOF, it generally is a \n character.

Resources