Unexpected output of int datatype - c

I created a simple program from the book let us c pg no.26 which is an example to illustrate and the code is somewhat like this
#include <stdio.h>
int main() {
char x,y;
int z;
x = 'a';
y = 'b';
z = x + y;
printf("%d", z);
return 0;
}
But the output i expected was the string ab (i know the z is in int but still that was the output i can think of) but instead the output was 195 which shocked me so please help me to figure this out in easy words.

Chars/letters are internally represented as numbers in terms of some protocols (e.g., Ascii or Unicode). ASCII is a popular standard to represent the most common symbols and letters. Here is the ASCII table. This table tells all the common symbols/letters in ASCII are essentially a number between 0 and 255 (ASCII has two parts: 0 to 127 is the standard ASCII; the upper range of 128 to 255 is defined in Extended ASCII; many variants of extended ASCII are used).
To put it into the context of your code, here is what happened.
// The letter/char 'a' is internally saved as 97 in the memory
// The letter/char 'b' is internally saved as 98 in the memory
x = 'a'; // this will copy 97 to x
y = 'b'; // this will copy 98 to x
z = x +y ; // 97+98=195 -> z
If you want to print "ab", you must have two chars next to each other. Here is what you should do
char z[3];
z[0]='a'; //move 'a' or 97 to the first element of z (recall in C, the index is zero-based
z[1]='b';//move 'b' or 98 to the second element or z
z[2]=0; //In C, a string is null-ended. That is, the last element must be a null (i.e.,0).
print("%s\n",z); // you will get "ab"
Alternatively, you can get "ab" in the following way based on the Ascii table:
char z[3];
z[0]=97; //move 97 to the first element of z, which is 'a' based on the ascii table
z[1]=98;//move 98 to the second element or z, which is 'b'
z[2]=0; //In C, a string is null-ended. That is, the last element must be a null (i.e.,0).
print("%s\n",z); // you will get "ab"
Edit/comment:
Considering this comment:
"Chars are signed on x86, so the range is -128 ... 127 and not 0 ... 255 as you state ".
Note that nowhere did I mention that the char type in C has a range of 0 ... 255. I refer to [0 ... 255 ] only in the context of the ASCII standard.

You summed up 97 to 98, hence the 195.
Feeding a sum of two char in an int will promote those char to int then store the result.
Then if you want that to be printed as a string, you can printf("%s\n", z);. Printing %d will interpret the variable as a decimal signed integer.
Don't print that as a string, because you don't know how far the first chars array terminator is.
Chars array in C, for many functions such as printf, don't end where its size ends, but where the terminator char (0x00 or 0 or '\0') marks its end.

Related

Do char's in C have pre-assigned zero indexed values?

Sorry if my title is a little misleading, I am still new to a lot of this but:
I recently worked on a small cipher project where the user can give the file a argument at the command line but it must be alphabetical. (Ex: ./file abc)
This argument will then be used in a formula to encipher a message of plain text you provide. I got the code to work, thanks to my friend for helping but i'm not 100% a specific part of this formula.
#include <stdio.h>
#include <cs50.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
int main (int argc, string argv[])
{ //Clarify that the argument count is not larger than 2
if (argc != 2)
{
printf("Please Submit a Valid Argument.\n");
return 1;
}
//Store the given arguemnt (our key) inside a string var 'k' and check if it is alpha
string k = (argv[1]);
//Store how long the key is
int kLen = strlen(k);
//Tell the user we are checking their key
printf("Checking key validation...\n");
//Pause the program for 2 seconds
sleep(2);
//Check to make sure the key submitted is alphabetical
for (int h = 0, strlk = strlen(k); h < strlk; h++)
{
if isalpha(k[h])
{
printf("Character %c is valid\n", k[h]);
sleep(1);
}
else
{ //Telling the user the key is invalid and returning them to the console
printf("Key is not alphabetical, please try again!\n");
return 0;
}
}
//Store the users soon to be enciphered text in a string var 'pt'
string pt = get_string("Please enter the text to be enciphered: ");
//A prompt that the encrypted text will display on
printf("Printing encrypted text: ");
sleep(2);
//Encipher Function
for(int i = 0, j = 0, strl = strlen(pt); i < strl; i++)
{
//Get the letter 'key'
int lk = tolower(k[j % kLen]) - 'a';
//If the char is uppercase, run the V formula and increment j by 1
if isupper(pt[i])
{
printf("%c", 'A' + (pt[i] - 'A' + lk) % 26);
j++;
}
//If the char is lowercase, run the V formula and increment j by 1
else if islower(pt[i])
{
printf("%c", 'a' + (pt[i] - 'a' + lk) % 26);
j++;
}
//If the char is a symbol just print said symbol
else
{
printf("%c", pt[i]);
}
}
printf("\n");
printf("Closing Script...\n");
return 0;
}
The Encipher Function:
Uses 'A' as a char for the placeholder but does 'A' hold a zero indexed value automatically? (B = 1, C = 2, ...)
In C, character literals like 'A' are of type int, and represent whatever integer value encodes the character A on your system. On the 99.999...% of systems that use ASCII character encoding, that's the number 65. If you have an old IBM mainframe from the 1970s using EBCDIC, it might be something else. You'll notice that the code is subtracting 'A' to make 0-based values.
This does make the assumption that the letters A-Z occupy 26 consecutive codes. This is true of ASCII (A=65, B=66, etc.), but not of all codes, and not guaranteed by the language.
does 'A' hold a zero indexed value automatically? (B = 1, C = 2, ...)
No. Strictly conforming C code can not depend on any character encoding other than the numerals 0-9 being represented consecutively, even though the common ASCII character set does represent them consecutively.
The only guarantee regarding character sets is per 5.2.1 Character sets, paragraph 3 of the C standard:
... the value of each character after 0 in the above list of decimal digits shall be one greater than the value of the previous...
Character sets such as EBCDIC don't represent letters consecutively
char is a numeric type that happens to also often be used to represent visible characters (or special non-visible pseudo-characters). 'A' is a value (with actual type int) that can be converted to a char without overflow or underflow. That is, it's really some number, but you usually don't need to know what number, since you generally use a particular char value either as just a number or as just a character, not both.
But this program is using char values in both ways, so it somewhat does matter what the numeric values corresponding to visible characters are. One way it's very often done, but not always, is using the ASCII values which are numbered 0 to 127, or some other scheme which uses those values plus more values outside that range. So for example, if the computer uses one of those schemes, then 'A'==65, and 'A'+1==66, which is 'B'.
This program is assuming that all the lowercase Latin-alphabet letters have numeric values in consecutive order from 'a' to 'z', and all the uppercase Latin-alphabet letters have numeric values in consecutive order from 'A' to 'Z', without caring exactly what those values are. This is true of ASCII, so it will work on many kinds of machines. But there's no guarantee it will always be true!
C does guarantee the ten digit characters from '0' to '9' are in consecutive order, which means that if n is a digit number from zero to nine inclusive, then n + '0' is the character for displaying that digit, and if c is such a digit character, then c - '0' is the number from zero to nine it represents. But that's the only guarantee the C language makes about the values of characters.
For one counter-example, see EBCDIC, which is not in much use now, but was used on some older computers, and C supports it. Its alphabetic characters are arranged in clumps of consecutive letters, but not with all 26 letters of each case all together. So the program would give incorrect results running on such a computer.
Sequentiality is only one aspect of concern.
Proper use of isalpha(ch) is another, not quite implemented properly in OP's code.
isalpha(ch) expects a ch in the range of unsigned char or EOF. With k[h], a char, that value could be negative. Insure a non-negative value with:
// if isalpha(k[h])
if isalpha((unsigned char) k[h])

Saving the int value of a char into an int variable

There are hundreds of questions on the net about this topic but are not what I'm looking for. I am looking for a way to convert a character to its ascii value.
I don't mean display the ascii value. I mean an actual value in a variable that I can use. Just changing the place holder is not going to work for this. That only displays the value. I need the actual working value. To be more specific I want to type in a character and have its ascii value saved into an int variable.
Ex.. enter 'A' and then the variable someVariable is initialized with the value 65. Then I want to add a constant value of 20 to the value 65 (or whatever the case would be for that character), to get 85, and then use that resulting number for the reference index of an array.
So you see I need to actually convert the value to an int not a char displayed as an int.
You can easily make a character an ascii value and assign it to an int like the example below. You can also add to the value and convert it to a different ascii character.
#include <stdio.h>
int main(void)
{
char c ='A';
int ascii = (int)c;//Convert to ascii value
printf("%d\n",ascii);
ascii += 20; //value is now 85
printf("%d\n",ascii);
char d = ascii - '0'; //convert back to new character.
printf("%c\n",d);
}
output:
65
85
%

Character frequency histogram in C

I read this program, but i'm not able to understand it. Please explain what exactly is happening in the length[] arraay . How can it be used to store different type of characters i.e. both digits & chars.Following is the code:
#include <stdio.h>
#define EOL '\n'
#define ARYLEN 256
main()
{
int c, i, x;
int length[ARYLEN];
for(x = 0; x < ARYLEN;x++)
length[x] = 0;
while( (c = getchar() ) != EOL)
{
length[c]++;
if (c == EOL)
break;
}
for(x = 0; x < ARYLEN; x++)
{
if( length[x] > 0){
printf("%c | ", x);
for(i = 1; i <= length[x]; ++i){
printf("*");
}
printf("\n");
}
}
}
The array doesn't store any characters (at least conceptually). It stores the number of times the program has encountered a character with the numerical value c in the array position of index c.
Basically, in the C programming language, a char is a datatype that consists of 8 bits and is able to hold values of the range 0 to 255 for an unsigned char or -128 to 127 for a signed char.
The program then defines an array large enough to hold as many different values as it is possible to represent using a char, one array position for each unique value.
Then it counts the number of occurances using the appropriate array position, length[c], as a counter for that specific value. As it loops over the array to print out the data, it can tell which character the data belongs to just by looking at the current index inside the loop, so printf("%c | ", x); is the character while length[x] is the data we're after.
In your code the integer array length[] is not used to store characters. It is only used to store the count of each character being typed. The characters are read one by one into the character variable c while( (c = getchar() ) != EOL).
But the tricky part is length[c]++;. The count of each character is kept at a location equal to its ASCII value - 1 in the array length[].
For example in a system using ASCII codes, length[64] contains the count of A, because 65 is the ASCII code for A.
length[65] contains the count of B, because 66 is the ASCII-8 code for B.
length[96] contains the count of a, because 97 is the ASCII code for a.
length[47] contains the count of 0, because 48 is the ASCII code for 0.

Store an integer value in a character array in C

It is a very trivial question but I don't know why I am not getting the correct output. Here is what I am trying to do:
char sendBuffer[1000];
int count=0:
while(count<10)
{
sendBuffer[0]=count;
sendBuffer[1]='a';
sendBuffer[2]='b';
sendBuffer[3]='c';
sendBuffer[4]='\0';
printf(%s,sendBuffer);
count=count+1;
}
In the output, all buffer is printed correctly except the first index. I want 1,2,3 and so on to be printed at the start of the buffer but it does not work. Please Help
You need to convert that number into a character. A cheap way to do it is:
sendBuffer[0] = '0' + count;
is there anyway to display integers greater than 9
If you need that you'll want to shift to more elaborate schemes. For example, if you want to convert an integer 42 into the string "42" you can say:
#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
char str[ENOUGH];
snprint(str, sizeof str, "%d", 42);
Credit for ENOUGH goes to caf.
printf(%s,sendBuffer); should be printf("%s",sendBuffer);
Change
sendBuffer[0]=count;
to
sendBuffer[0]='0' + count;
i.e. convert the integer 0...9 to the characters '0' ... '9'
Also add a quote i.e. printf("%s",sendBuffer);
Quoted from the question:
In the output, all buffer is printed correctly except the first
index.i want 1,2,3 and so on to be printed at the start of the buffer
but it does not work. Please Help
I think her problem is that she does not get any output for the first line. That is because in the first iteration, count is 0, i.e. sendBuffer[0] is 0 which is the '\0' character. Hence the string is treated as empty.
You are trying to print the ascii characters corresponding to decimal values 0-9 which are non-printable characters. If you need to print decimal 0-9 then initialise count to 48 which is the ascii decimal code for '0' and change the condition in the while block to count < 58; 57 is the ascii deciaml code for '9'. See below:
char sendBuffer[1000];
int count=48:
while(count<58)
{
sendBuffer[0]=count;
sendBuffer[1]='a';
sendBuffer[2]='b';
sendBuffer[3]='c';
sendBuffer[4]='\0';
printf(%s,sendBuffer);
count=count+1;
}
To convert an integer value to a char representation, add the value of the character '0':
sendBuffer[0]=count + '0';
Notice that's the character '0', not the number 0. This is because of how ascii values work. The char with a literal value of 0 is \0, the null terminator. Digit '0' has a literal value of 48, '1' 49 and so on.
This works for the digits 0-9. You can't put a char representation of a number bigger than that in a single char, obviously.
char sendBuffer[1000];
// take fixed stuff outside the loop
sendBuffer[1]='a';
sendBuffer[2]='b';
sendBuffer[3]='c';
sendBuffer[4]='\0';
// it's best not to rely on order of ASCII values
for(char* numbers="0123456789"; *numbers!=0; numbers++){// use for loop for numbers
sendBuffer[0] = *numbers;
printf("%s",sendBuffer);
}

my program prints some arbit ascii string

I wrote following program
int main ()
{
char a=0xf;
a=a+1;
printf("%c\n",a);
}
the output of above program is what I am not able to understand.It is giving me some character which I am not able to understand.Is it possible to find out ASCII code of the character that I am getting in my above program so that I understand what is it printing.
EDIT
Based on the replies I read I am adding further to my confusion
if I write a statement as following
char ch='Z';
then what would be stored in ch,
1) The character Z
2) ASCII value of Z
3) Z along with single inverted commas
4) Both (1) and (2)
ASCII value for 16(0x0f + 1 = 0x10) is DLE (data link escape) which is non-printable character.
Just Print as integer like this.
printf("%d\n",a);
The characters from 0 to 31 are non-printing characters (in your case, you've chosen 0xF, which is 15 in decimal). Many of the obscure ones were designed for teletypes and other ancient equipment. Try a character from 32 to 126 instead. See http://www.asciitable.com for details.
In response to your second question, the character stores the decimal value 90 (as characters are really 1-byte integers). 'Z' is just notation that Z is meant to be taken as a character and not a variable.
You can modify your program like that:
int main ()
{
char a=0xf;
a=a+1;
printf("Decimal:%u Hexa:%x Actual Char:|%c|\n",a,a,a);
}
Printf can use different formatting for a character.
Its printing the character 0x10 (16).
If you want the output, change your print to output the values (in this case, character, hex value, decimal value):
printf("%c - %x - %d\n", a, a, a);
#include<stdio.h>
int main ()
{
char a='z'; \\\ascii value of z is stored in a i.e 122
a=a+1; \\\a now becomes 123
printf("%c",a); \\\ 123 corresponds to character '{'
}

Resources