Storing int variable from user into array in C - c

I am fairly new to c programming, and also this forum but I thought I would give it a try. What I want to do is have a user enter a 4 digit number. From there i want to take the number and store it in an array, so as i could call arr[2] when I need it and so on and so on. Thanks in advance for any help!
I would really like to know what is going on here. Thanks again

Many possibilities exist to implementing the behavior you want. Here's one way of doing it:
int arr[4];
int i;
char var1[4];
printf("Please enter a 4 digit number: ");
scanf("%s", var1);
for (i = 0; i < 4; i++ ) {
arr [i] = var1[i] - '0'; // convert char to int
printf("%d", arr[i]);
}
printf("\n");

Your code does not do what you think it does. scanf reads a line from the console. %d matches a number (i.e. 123), not a digit (i.e. 1, 2, 3). You call printf in a loop, not scanf (i.e. you capture one number and you print it multiple times).
Actually, I see it is more than that - you are assuming integer in C++ means digit. Your array of 4 integers does not hold a 4 digit number - it holds four separate integers, each of which can be (usually) from -2147483648 to +2147483648.
The thing is, it's not easy to break a number into digits - because "digits" are base 10 (decimal) while a computer thinks in base 2 (binary). What we can do instead is read and write the number and digits as text, instead. Read the integer as a string, and write each digit as a character:
#include <stdio.h>
int main()
{
char input[4];
//get input as text, instead of as a number
printf ("Please enter a 4 digit number: ");
scanf ("%s", input);
for ( int i = 0; i < 4; i++ )
{
//print as char instead of as number
printf ("%c\n", input[i]);
}
}
This code is not perfect. If the user entered "blah" it will print "b" "l" "a" "h" instead of complain about non-numeric input. If the user enters more than 4 characters, our array of characters to hold the number will overflow causing serious security risks and a crash.

var1 is an integer and you are storing it in each element of the integer array arr, hence the output
If you want to store each number as a character, use fgets, or if you want to store it a number, do
i=0;
while(var1){
arr[len-i-1] = var1%10; //len is 4 in your case
var1 /= 10;
i--;
}

You have asked scanf to read an integer value. You might want to read a string instead.
In a pinch, you can use fgets:
char number[5];
if( fgets(number, sizeof(number), stdin) != NULL )
{
for( i = 0; i < 4; i++ ) {
printf( "%c\n", number[i] );
}
}

Related

4-bit BCD to 7-segment

I'm making a 4-bit BCD decoder to 7-segment display in C.
After the output is displayed I ask if the user wants to input again. I can display the desired output and I can exit the program when I don't want to input again.
The problem is when I want to input again it doesn't stop to ask for my input and prints the previous input.
This is the output:
This program displays the decimal equivalent of a
4-bit binary-coded decimal input on a 7-segment LED Display.
Please enter a 4-bit binary-coded decimal: 1000
You've entered 1000.
The decimal equivalent is 8.
_
|_|
LED Display: |_|
Would you like to input another 4-bit BCD?
Enter [1] if yes or [0] if no. 1
Please enter a 4-bit binary-coded decimal: You've entered 1000.
The decimal equivalent is 8.
_
|_|
LED Display: |_|
Would you like to input another 4-bit BCD?
Enter [1] if yes or [0] if no.
This is my code:
int main() {
int i, dec, retry = 1; //declare integers i ,dec, and retry
int bit[4]; //declare integer array with 4 elements
unsigned char input[5]; //declare string with 5 elements
printf("This program displays the decimal equivalent of a\n 4-bit binary-coded decimal input on a 7-segment LED Display.\n\n");
do {
printf("Please enter a 4-bit binary-coded decimal: "); //instructs user to enter 4-bit bcd
scanf("%[^\n]%*c", input); //read string
printf("You've entered %s.\n\n", input); //shows the 4-bit bcd input
for (i=0; i<5; i++) {
bit[i] = input[i] - '0';
}
dec = bit[0]*8 + bit[1]*4 +bit[2]*2 + bit[3];
printf("The decimal equivalent is %d.\n\n", dec); //shows decimal equivalent
switch (dec) { //displays 7-segment display depending on the value of dec
case 0:
printf(" _ \n | |\nLED Display: |_|\n");
break;
...
}
printf("\n\nWould you like to input another 4-bit BCD?\nEnter [1] if yes or [0] if no. ");
scanf("%d", &retry);
}
while (retry == 1);
}
I also encounter the same problem when using fgets(input, sizeof(input), stdin); instead of scanf("%[^\n]%*c", input);
After the input 1\n is given in order to go on withe next 7 segment number, only 1 is captured by scanf() and \n is left tho the followong one.
But the format %[^\n] tells scanf() to NOT match any input starting with a \n, so the leftover makes the following it return without any value scanf'd. Checking its return value you would find that the second time is 0, so the variable is not updated and that's why the previous value is used.
In order to fix it, since you need %[^\n] in to trim the input (you expect only digits), just add a space before current input format:
scanf(" %[^\n]%*c", input);
in this way any whitespace character (all characters for which isspace() returns true, including '\n', ' ', and'\t') is consumed.
Note that adding
fflush(stdin);
before your first scanf() is Undefined Behavior for the standard C. In some environments it works, but this solution should be avoided as, to say the least, it makes the code non-portable!
Note: you have the same behavior with fgets() because it reads until a \n is found, and like it happened before with scanf, that's exactly the character remaining from the previous user input insertion.
Suggestions on how to check your input
Instead of using %[^\n] format, I suggest a different approach in order to check your input:
while( 1 )
{
printf("Please enter a 4-bit binary-coded decimal: "); //instructs user to enter 4-bit bcd
scanf(" %4s", input); //read string
if( validateBinaryInput( input, 4 ) == 0 )
{
break;
}
else
{
printf( "Wrong input!\n" );
}
}
With scanf(" %4s", input); you make sure to capture exactly four characters, and to store them within input array. The loop makes sure that whenever the input is not valid the input sequence is repeate. The input validity can be checked with validateBinaryInput() function. Please find below an implementation example:
/* Returns 0 on success, -1 on failure */
int validateBinaryInput( unsigned char *input, size_t len )
{
int ret = 0;
if( !input )
{
ret = -1;
}
else
{
int i;
for( i=0; i<len; i++ )
{
if( input[i] != '0' && input[i] != '1' )
ret = -1;
}
}
return ret;
}
Not only it makes sure that every inserted character is a digit, but it verifies that it is a binary digit. In this way you avoid strange behaviors that would occur inserting an input such as 5: your assignment of
dec = bit[0]*8 + bit[1]*4 +bit[2]*2 + bit[3];
would result in the value 5, and the corresponding 7-segments digit would be printed even if the input wasn't a valid binary word.
This line right here is an issue:
scanf("%[^\n]%*c", input); //read string
The previous %d only consumes whitespace before the format specifier, not after. This means that this scanf will read an empty string.
To fix this, add a space before so the whitespace will be consumed:
scanf(" %[^\n]%*c", input); //read string

How to fix segmentation fault when trying to scanf a string?

I'm trying to make a program that writes to a file every combination of letters formed from a given phone number. I'm fairly positive it's giving the segfault where I scanf the name of the file the user wants to write to (in main) because I've put in printf tests and they don't print. For some reason, before adding in my recursive functions it doesn't give me a segfault but after adding them it does.
const char letters[8][5] = {"ABC", "DEF", "GHI", "JKL", "MNO", "PQRS", "TUV", "WXYZ"};
int main()
{
int userNum[7];
char userFile[25];
printf("Please enter the phone number you want to process with no added
characters or spaces: ");
scanf("%d", &userNum);
printf("Enter the file name (including extension and less than 25
characters) that you would like to write to.\n");
scanf("%s", userFile); //This is where I think the seg fault is happening
printf("Test"); //Because this doesn't print
FILE* file_ptr;
char fileName[17];
sprintf(fileName, "%s", userFile);
file_ptr = fopen(fileName, "w");
findWordsHelper(userNum, 7);
}
//Adding this function and the one after is what made the program start
//giving said seg fault
void findWords(int userNum[], int digit, char words[], int n)
{
printf("Test. n = %d", n);
int i;
if(digit == n)
{
printf("%s ", words);
return;
}
for(i = 0; i < strlen(letters[userNum[digit]]); i++)
{
words[digit] = letters[userNum[digit]][i];
findWords(userNum, digit+1, words, n);
if(userNum[digit] == 0 || userNum[digit] == 1)
{
return;
}
}
}
void findWordsHelper(int userNum[], int n)
{
printf("test");
char result[n+1];
result[n] = '\0';
findWords(userNum, 0, result, n);
}
I'm not in an environment that I can test but I see a few things. First off, your printf test isn't printing because if has no new line character. If you're not going to put one in, call fflush. E.g
printf("test");
fflush(stdout);
Second, your use of scanf to read in the phone number shows a bit of misunderstanding of how scanf will treat input as an integer. You don't need an array of 7 ints for this because you've simply instructed for the input to be no extra characters. So, a phone number like 345-6789 is input as 3456789 which will be read as a single int: i.e 3 million, 4 hundred 56 thousand, 7 hundred 89. This will be read into a single integer. I know you want to treat them as separate numbers, but scanf will treat them as 1 number when not separated by whitespace. To read into a single int, this would suffice:
...
int phoneNumber;
scanf("%d", &phoneNumber); // <--- notice the & operator
EDIT
I was reading over the manual page for scanf() and when the %s specifier is used, it should insert a null-character into the string. So, the part directing to check the return and ensure a '\0' character is placed there is not applicable.
EDIT 2
I had a moment this morning and had to figure this out. I think I've got it. Something in the function findWords() looked a bit suspect and compiling, seg-faulting, and looking at the core file showed it to be the case. It's this line in that function
for(i = 0; i < strlen(letters[userNum[digit]]); i++)
Specifically, it is the call to strlen() with the result of using userNum[] to index into letters[]. As myself, and others, have indicated, scanf() isn't going to read a "phone number" such as 3456789 (input as such) into 7 different integer values. It is read as a single int and it's going to be read into userNum[0] (and guess what? digit = 0 when the segfault occurs). This is no surprise, the letters array does not contain 3 million, 4 hundred 56 thousand, 7 hundred 89 indecies. (Assuming the number entered is what I wrote.)
As mentioned by Jasen (I think), ints don't really work well for phone numbers. At the very least, you'll have to develop a different manner of breaking apart the phone number to use as an index.
First of all, lack of printf output does not indicate that the program did not execute past that point, as the output is probably buffered.
You can either do fflush(stdout) immediately after a printf call, or use setvbuf with a null argument to force unbuffering.
Second, in your recursive function, each call results in calling itself up to the number of iterations in your for loop. I suspect there are logic errors there and the number of recursive calls may just explode.
Third, you definitely have a logic problem here:
int userNum[7];
...
scanf("%d", &userNum);
Looks like you are expecting that if a user enters "1234567", that each userNum[i] contains one of the digit, but that's not what's happening.
scanf would treat the argument as a pointer to an int, e.g. on a 32-bit CPU, it would put the integer value 1234567 into the first 4 bytes of "userNum". In fact, this could cause a segfault right there if the CPU cannot write to an integer (whether 16 or 32 bits) to an unaligned address. As userNum is actually an array, it may or may not be aligned suitable for an integer.
int main() {
int userNum[7];
char userFile[25];
printf("Please enter the phone number you want to process with no added"
" characters or spaces: ");
printf("Enter the file name (including extension and less than 25 "
" characters) that you would like to write to.\n");
scanf("%s", userFile); //This is where I think the seg fault is happening
should be :
scanf("%24s",userfile);
that puts a limit of 24 chars on what is read.
char fileName[17];
sprintf(fileName, "%s", userFile);
However userfile could be 24 long... and that can only fit 16, so it should be.
sprintf(fileName, "%.16s", userFile);
which chops off any overflow.

Output the decimal versions of unknown input

I'm trying to write a short script to take in 6 inputs that will be in decimal, hex or octal and output their decimal versions. For example, if I input 1, 1 should be output. Input 010, should get 8, input 0x20, should get 32. Do I have to test each value to see if scanf reads it as its type or can I cast them after scanf reads them all as is? Also do I need functions to convert the octal and hex values to decimal or can I cast them? I'm very new to C and don't understand it well yet, but here's what I have so far (it outputs -200 as 32765 for whatever reason):
int num[6];
printf("Enter six integers:\n");
int i = 0;
int j;
while (i < 6){
if(scanf("0x%x", &j) == 1){
scanf("0x%x", &num[i]);
//hexToDec(num[i]);
} else if (scanf("0%o", &j) == 1){
scanf("0%o", &num[i]);
//octalToDec(num[i]);
} else {
scanf("%i", &num[i]);
}
i+=1;
}
for(int p = 0; p < 6; p+=1){
printf("%i\n", num[p]);
}
Answer for future reference: simply scanning in with "%i" does the conversions automatically. Revised code below:
int main(){
int num[6];
printf("Enter six integers:\n");
int i = 0;
while (i < 6){
scanf("%i", &num[i]);
i+=1;
}
for(int p = 0; p < 6; p+=1){
printf("%i\n", num[p]);
}
}
You cannot use scanf("0x%x", &j) to test the input and then use scanf("0x%x", &num[i]) to put the value in num[i]. scanf consumes the characters it accepts, so they are no longer in the input stream. When you do the second scanf, the characters are gone.
Instead, just attempt to scan the desired thing. If it works, you are done. If it does not work, go on to an else:
if (scanf("0x%x", &num[i]) == 1)
; // Worked, nothing to do.
else if (scanf("0%o", &num[i]) == 1)
;
else if (scanf("%i", &num[i]) == 1)
;
else
{
// Nothing worked, should put error-handling code here.
}
That is actually not great code for real applications, because scanf will consumes some of the input even if it ultimately fails. For example, with scanf("0x%x", &num[i]), if the input contains “0x” but then contains a non-hexadecimal character, scanf will consume the “0x” but leave the next character. However, it suffices for a learning exercise.
Once you have values in the num array, they are just int values. They are mathematical values, not numerals that are in octal, decimal, or hexadecimal. You can print them with %o for octal, or %d or %i for decimal. The original numeral is irrelevant. When printing, the mathematical value will be used to format a string in the requested base.
You should not use %x for printing an int, as %x is for unsigned int. However, you could convert an int to unsigned int and then print it with %x.
Note that you should not scan to int objects with %x. %x is for scanning to unsigned int objects. You can actually scan hexadecimal, octal, and decimal using:
if (scanf("%i", &num[i]) == 1)
;
else
…
The %i specification will recognize hexadecimal numerals beginning with “0x”, octal numerals beginning with “0”, and decimal numerals.
If you did not want to use %i for all three, because you want direct control for some reason, you will need to write more code. Standard C does not provide a direct way to scan only a hexadecimal numeral to an int. You would need to get the characters from the input and calculate the value from them or scan to an unsigned int and then convert the result to an int.
You can use function strtol with a base of 0 to do auto-detection of the integral value's base according to the input strings format (cf, for example, strtol documentation at cppreference.com):
long strtol( const char *str, char **str_end, int base )
Interprets an integer value in a byte string pointed to by str. ...
The valid integer value consists of the following parts:
(optional) plus or minus sign
(optional) prefix (0) indicating octal base (applies only when the base is 8 or ​0​)
(optional) prefix (0x or 0X) indicating hexadecimal base (applies only when the base is 16 or ​0​)
If the value of base is ​0​, the numeric base is auto-detected.
So a call like long val = strtol("0x10",NULL,0); will yield a decimal value of 16.
Note that you can also use scanf in conjunction with format specifier %i, since this is defined to behave just as a call to strtol:
​int scanf( const char *format, ... )
%i matches an integer. The format of the number is the same as expected by strtol() with the value ​0​ for the base argument (base is
determined by the first characters parsed)
The quick answer is use only
if(scanf("%i", &j) == 1){
...
}
what I have so far (it outputs -200 as 32765 for whatever reason):
Yet error handing of scanf() is troublesome. Far better to read the line of user input with fgets() and then parse the line - perhaps with strtol().

Splitting a string into integers

For my first task I am using fgets() to read a string from stdin. So I input 1234567890 on the terminal and it stores the string into a variable called str. Now I want to split the digits up and perform addition. In this case the sum would be 55 since 1+2+3+4+5+6+7+8+9+0 = 55.
How can I do that?
My code so far
#include <stdio.h>
#include <string.h>
int main(void){
char str[100];
printf("Please enter the 10 digit number \n");
fgets(str, 10, stdin);
//Separate the digits
//calculate their sum
int sum =..............
//print out the sum
printf("the sum of the digits is: %s", sum);
return(0);
}
Approach 1:
If you know for sure that you're counting for single digit integer, you can use
array indexing to read the digit-by-digit value from the input string.
convert the char value to corresponding int as per the required encoding (mostly, ASCII).
define one int variable , say res to hold the sum. perform the addition and store the result to sum.
loop untill terminating null is reached.
print out the sum using %d format specifier.
Approach 2:
Alternatively, you can do something like (again assuming,single digit integer)
Convert the whole string to integer using strtol(). You must check for the errors in that case.
define one int variable , say res to hold the sum.
perform modulo 10 (%0) on the converted interger value to take out the last digit. add and store that inres`
divide converted interger value by 10 (p /= 10).
continue to step 2 untill the result is 0.
when the converted interger value becomes 0, print the res.
P.S - Just FYI, usual way of splitting a string based on some delimiter is to use strtok().
Since you are sure the string will contain digits, subtract each character from '0' to get their numeric value.
int sum = 0;
fgets(str, sizeof str, stdin);
char *s = &str;
while(*s != '\0') {
sum += *(s++) - '0';
}
printf("the sum of the digits is: %d", sum);
First, make sure that you read only digits by using scanf, like this:
char str[11]; // 10 digits plus \0 terminator
printf("Please enter the 10 digit number \n");
scanf("%10[0-9]", str);
Now you can go through the digits one by one by indexing into str, and subtracting the code of digit zero, like this:
int nextDigit = str[i] - '0';
This should be enough information for you to complete the solution by adding a for loop around it. Make sure that you print sum using %d, not %s like you did in your code sample.

Trouble with using getchar() instead of scanf()

I'm having trouble making this exercise for C-programming. I need to use the getchar()-method instead of the scanf(). When I use the scanf, everything works perfect when I type for instance 7. However when I use the getchar() and type 7, I will get the ASCII-code of 7, not the int 7. How do I fix this?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int i;
printf("Voer een getal in:\n");
fflush(stdout);
i = getchar();
//scanf("%d", &i);
if (i > -1000 && i < +1000) {
printf("het ingevoerde getal is: %d\n", i);
} else {
printf("foutieve invoer\n");
}
return EXIT_SUCCESS;
}
This is the correct behavior of getchar. While scanf's %d format specifier converts a sequence of digits to a decimal number, with getchar you need to do it yourself.
In order to do that, you need to know three things:
When the sequence of digits ends,
How to convert an ASCII code of a digit to a number, and
How to combine multiple digits into a single number.
Here are the answers:
You can decide to end the character input when the value returned by getchar is not a digit. You can use the isdigit function for that (include <ctype.h> header to use it).
You can convert a single digit character to its corresponding numeric value by subtracting the code of zero (i.e. '0') from the value returned by getchar
You can combine multiple digits into a number by starting the partial result at zero, and then multiplying it by ten, and adding the value of the next digit to it.
int num = 0;
for (;;) {
int ch = getchar();
if (!isdigit(ch)) break;
num = 10 * num + (ch - '0');
}

Resources