Basically, I have this really long string full of digits:
char *number = "insert really long number";
Now I want to perform math operations on individual digits contained in this string, let's say the following (summing two consecutive digits in this string aka array of chars):
sum = number[i] + number[i+1];
However, this does not produce the correct result, it returns a garbage value. I know how to extract a single value with printf for example:
printf("%c", number[i]);
But how can I get this %c to use in computations as above? I tried with atoi, but I get "error: incompatible integer to pointer conversion passing 'char' to parameter of type 'const char *'; take the address with &".
1) atoi accept string rather than single character
2) If you want to convert just one ACSII char 0 - 9 just use following code:
if(rChar >= '0' && rChar <= '9')
val = rChar - '0';
You probably want this:
char *number = "123";
int n = 0;
char c;
for (int i = 0; c = number[i]; i++)
{
n += number[i] - '0';
}
printf("n = %d\n", n);
For any number which is represented as a datatype char, you can subtract that number from '0' to get that number in integer type.
For example:
char a = '5';
int num = a - '0';
//num will store 5
Why this works?
Because if you check the ASCII value for '5', it is 53 and for '0' it is 48. So the difference is 5. This will work for converting any number in character form to integer.
The ASCII value for '0' is 48, for '1' it is 49 and so on. So the subtraction from '0' results in giving us the difference of ASCII values.
Here is a link to ASCII values: http://www.asciitable.com/
atoi convert string (const char*) to int, if you give it a char it will not work. A solution to convert a char to an int is to use the ASCII table:
char c = '9'
int v = c - '0'; // v == 9
Related
I have been trying to learn C and decided to do an encryption project. I want to use ROT 13 encryption for the project but I have been getting an error. The code is supposed to check the value of a char at index position words[i] and compare its value. If it's in the range of 97-122 ('a' - 'z'), run the code and add the encryption. I learned, however, that when I want to replace a letter like 'z' and move it 6 positions, it doesn't work. Moving it 5 positions does work. Please see the code below:
#include <stdio.h>
#include <string.h>
int main(){
char words[25]= "ABC MNO XYZ";
printf("%s \n", words);
printf("size of 'words' is %d \n", strlen(words));
int size_t = strlen(words);
for (int i=0; i < size_t; i++){
printf("%c \n", words[i]);
}
printf("unencrypted ends here... \n\nStarts the cipher\n");
//converts array to lowercase for ascii purposes
for (int i=0; i < size_t; i++){
words[i]= tolower(words[i]);
}
for (int i=0; i < size_t; i++)
{
char res = 'z';
if(words[i]>=97 && words[i]<=122)
{
words[i] = words[i]+6;
while(words[i] > 122)
{
res = words[i]-res;
printf("The value of res is: %d\n", res);
words[i]=96;
words[i]= words[i]+res;
}
}
//'res' ascii value equals 122
//if words[i] is more than 122 (z), subtract 122 from it and store it in res
//restart words[i] at position before 'a', then add res
//not sure why but after 122 + 6 or more positions, does not reset to a char before 'a'
//gives those weird chars at 128+ ascii locations
printf("%c \n", words[i]);
}
return 0;
}
#user3386109 has already commented a solution to your problem:
Subtract 'a' from the letter. Add 13 (for rot13), and then subtract 26
if the result is >= 26. Then add 'a' to get the final result.
But here's an explanation of why adding 5 to words[i] works but 6 doesn't:
The main reason adding 5 to words[i] works but adding 6 doesn't is because in your case char is signed (range -128 to 127) so if words[i] (a char) is equal to 122, adding 6 to it (128) overflows the range of signed char.
Since words[i] will never be negative, try using unsigned char instead of char.
Last but not the least, size_t is a datatype in C, try to avoid using it as a variable name.
The problem is that a char may have a range of [-128, 127], which is why adding 5 works, but adding 6 causes an out-of-range assignment. One solution is to first convert the char to a larger type, for example an int, but there is something better:
for (int i=0; i < size_t; i++)
{
if (islower(words[i]))
words[i] = (words[i] - 'a' + 13) % 26 + 'a';
printf("%c \n", words[i]);
}
This takes the character, makes it a value between 0 and 25, applies the shift, takes the remainder to handle the wrapping around the alphabet, and finally adds 'a' again to convert the value back to the ASCII 'a' to 'z' range.
This will still implicitly convert the char to an int type, as 'a' and 13 are ints, but now we no longer need an if-statement and it expresses clearly that we are using values modulo 26.
For more information on the range of char and type promotions, see here. Note that assigning an out-of-range value to a signed integer is actually implementation-defined behavior.
Some additional advice:
The typical signature for main, using no parameters, is int main(void).
To use tolower, include the ctype.h header.
Do not use an identifier called size_t. This is a type used in C and is typedef'd in many commonly used headers.
Using 'a' and 'z' makes the code easier to understand than using 97 and 122. For checking if a char is lowercase, use islower.
The strlen function returns a value of the type size_t. The correct format specifier for this is not %d, but %zu.
I am trying to write a program in C to sum the value of an integer and a character. If the user enters an integer where the character should be, I am expecting my program to calculate the value of the 2 integers. My code below works with the user entering 2 integers but only calculates up to 9 (Ex: 4 5: "Character '4' represents a digit. Sum of '4' and '5' is 9"). If the user enters 5 6, the result is: "Character '5' represents a digit. Sum of '5' and '6' is ;". I have been searching for a while now and any potential solution always leads to the incorrect sum. I also expect my program to accept user input higher than '9' (Ex: 20 50), but if I change '9' to '99', I get the following warning: "warning: multi-character character constant [-Wmultichar]". Can someone please point me in the right direction to achieve these goals?
#include <stdio.h>
int sum (int m, char n){
return m+n;
}
int main(){
char ch;
int c;
printf("Enter an integer and a character separated by a blank> ");
scanf("%d %c",&c, &ch);
if((c >= '0' && c <= '9')||(ch >= '0' && ch <= '9')){
int cs = sum(c, ch - 0);
printf("Character '%d' represents a digit. Sum of '%d' and '%c' is %d" , c, c, ch - 0, cs);
}
return 0;
}
int cs = sum(c, ch - 0);
It looks like your trying to account for ASCII values by subtracting the ASCII value of 0 from whatever character the user enters. However, you used an integer literal of 0, when you'd want to use a character literal of '0'. See below:
int cs = sum(c, ch - '0');
Also, I would recommend renaming your int to i or something other than c. It's a little difficult to distinguish that the types of c and ch are different.
Also consider changing
if((c >= '0' && c <= '9')
to
if((c >= 0 && c <= 9)
c is an integer and you should compare it as such. By using ' ', you're basically doing a cast to a char variable which is unnecessary here.
Another problem is that I don't think you're going to be able to accomplish what you're trying to do using a char variable for a two-digit number. A char variable can hold a single character, where as a two-digit number is composed of, well, two characters.
Sorry I can't comment so I'm adding this answer for the problem abou t using only one digit.
You have a single char
char ch;
So it reads only one char, you need an array of chars like char ch[10]
Then you'd use int foo = atoi(ch) to converto your array to an integer
I am trying to store an integer in a char array. How can I do that? This is my approach (by casting it the int to a char) but it does not work. What am I missing?
#include <stdio.h>
int main(int argc, char** argv)
{
char cArray[10] = {};
// Store a character in the char array
cArray[5] = 'c';
printf("%c\n", cArray[5]);
// Store an integer in the char array
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[6]);
}
Let's start with the basics.
For x86 architecture(assuming you use it) a char variable is stored in 1 byte and an int variable is stored in 4 bytes.
It is IMPOSSIBLE to store a random integer value in a char variable unless you have some compression schema and know that some integer values will not occur(no random!) in your program. No exceptions.
In your case, you want to store integers in a char array. There are four options:
1.If you want to store a random integer in this char array, then you should get the pointer to the index that you want to store the integer and cast it to an integer pointer and use it like that.
char mychars[10];
int * intlocation = (int*)(&mychar[5]);
*intlocation = 3632; // stores 3632
Beware that this will write to 4 bytes(4 char locations in your array) starting from the index you have specified. You should always check you are not going out of array.Also you should do the same casting for retrieving the value when needed.
2.If your values are between [0,255] or [-128,127] you can safely store your integers in a char since these ranges can be represented using a byte. Beware that char being signed or unsigned is implementation-dependent. Check this out!
mychars[5] = 54;
3.If your integer is just a digit, you can use the char representation of the digit.
mychars[5] = your_digit + 48; // 48 is the ascii code for '0'
4.If you want to store the string representation of your integer, then you should use itoa() and write each char of the resulting string to your array one by one. In that case, you should always check that you are not going out of array.
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[6]);
This code attempts to print a character with the encoding 0; assuming ASCII, nothing will get displayed because there is no printable character associated with that code.
If you intend to store the ASCII code for the character '0' and print it, then you need to write
cArray[6] = 48; // same as writing cArray[6] = '0' (ASCII)
printf( "%c\n", cArray[6] );
This will print 0 to your console.
If, on the other hand, you want to store any arbitrary integer value1 to cArray[6] and display that value, then you need to use the %d conversion specifier:
cArray[6];
printf( "%d\n", cArray[6] );
1. That is, any integer that fits into the range of char, anyway
Normally, a computer exactly does what you tell it. The instruction DWIM (do what I mean) hasn't been invented yet.
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
sets the index position 6, but
printf("%c\n", cArray[5]);
prints the index position 5.
I would like to add on to Seçkin Savaşçı's answer (in which you cast a char* pointer to somewhere in the char array to an int* pointer, allowing you to write an integer to the array by dereferencing the pointer).
You can also use bit-shifting:
#include <stdio.h>
int main() {
int first_int = 4892; // number larger than 127 (max. value of char)
int second_int = 99584; // same
// char array to hold two integers:
char array[8]; // ...assuming an integer size of 4 and char size of 1
// Now, assuming you are on a little endian system (in which the least
// significant bytes come first), you can add the two above integers to the
// array like so:
array[0] = first_int; // assigns first_int's least significant byte
array[1] = first_int >> 8; // assigns first_int's 2nd least significant byte
array[2] = first_int >> 16; // assigns first_int's 2nd most significant byte
array[3] = first_int >> 24; // assigns first_int's most significant byte
// repeat for second_int:
array[4] = second_int;
array[5] = second_int >> 8;
array[6] = second_int >> 16;
array[7] = second_int >> 24;
// You can now prove that this char array holds the two integers like this:
printf("First integer: %d\n", *((int *) array));
printf("Second integer: %d\n", *((int *) (array + 4)));
return 0;
}
On a big endian system you would first assign the most significant byte, and move on to the least significant bytes.
Replace
cArray[6] = (char) 0; // WHY DOES THIS NOT WORK???
printf("%c\n", cArray[5]);
By
cArray[6] = (char)51;
printf("%c\n", cArray[6]);
Should display '3'
I think you will understand your mistake... 0 as int does not represent the printable character '0', but the NULL termination string
51 as int represent the character '3'
You may use itoa(0,&cArry[6],10).
Use the correctly desired format specifier.
cArray[6] = (char) 0; does store an integer 0 into array element cArray[6]. Its the printf() that is fooling OP into thinking that did not work.
Using %c says OP wants the character that is encoded with a 0. (It usually not visible). Use %d to print the integer value of cArray[6].
printf("%d\n", cArray[6]);
You can add the ASCII value of 0 to the value you want to store digit into the character array.
For example if you want to store 0,1,...,9 into the character array A[10], you may use the following code.
for(j = 0; j<k; j++)
{
A[j] = j + '0'; // Same effect if you use A[j] = j + 0x30
}
This works only if the integer you want to store is less than 10. Otherwise you will have to extract the digits using modulo operator and store.
I am trying to figure out how to convert a char number, say
char num = "1";
to the same number as an integer so
char num = "1"; would be converted to int numc = "1";
and the only way that I can think of to do it is to manually do a bunch of if statements, which seems a bit excessive, so I was just wondering if anyone knew of an easier way to do this? thanks!
In C, characters are really just numbers representing their character value, so:
char ch = '1';
int num = ch - '0';
printf("ch=%c num=%d\n", ch, num);
This takes advantage of the fact that in all common character sets, the character values '0' through '9' are sequentially allocated.
Notice also that char values are surrounded by single quotes, while multi-character strings are surrounded by double quotes.
A quick solution to your problem is to subtract '0' from your digit's value as shown below:
char num = '2';
int i = num - '0';
I plan to make a program like this:
loop
read first character
read second character
make a two-digit hexadecimal number from the two characters
convert the hexadecimal number into decimal
display the ascii character corresponding to that number.
end loop
The problem I'm having is turning the two characters into a hexadecimal number and then turning that into a decimal number. Once I have a decimal number I can display the ascii character.
Unless you really want to write the conversion yourself, you can read the hex number with [f]scanf using the %x conversion, or you can read a string, and convert with (for one possibility) strtol.
If you do want to do the conversion yourself, you can convert individual digits something like this:
if (ixdigit(ch))
if (isdigit(ch))
value = (16 * value) + (ch - '0');
else
value = (16 * value) + (tolower(ch) - 'a' + 10);
else
fprintf(stderr, "%c is not a valid hex digit", ch);
char a, b;
...read them in however you like e.g. getch()
// validation
if (!isxdigit(a) || !isxdigit(b))
fatal_error();
a = tolower(a);
b = tolower(b);
int a_digit_value = a >= 'a' ? (a - 'a' + 10) : a - '0';
int b_digit_value = b >= 'a' ? (b - 'a' + 10) : b - '0';
int value = a_digit_value * 0x10 + b_digit_value;
put your two characters into a char array, null-terminate it, and use strtol() from '<stdlib.h>' (docs) to convert it to an integer.
char s[3];
s[0] = '2';
s[1] = 'a';
s[2] = '\0';
int i = strtol(s, null, 16);