#include <stdio.h>
int main (void)
{
int c;
while ( (c = getchar ()) != EOF )
putchar (c);
return 0;
}
So in this program, there is c = getchar (). So i would assume that getchar returns to an integer regardless of what you type?
If that was the case, if I had the code:
#include <stdio.h>
int main (void)
{
char c;
c = getchar();
printf("%c",c);
return 0;
}
It should not work. As if I typed 'y' for example, the getchar function can return to an integer that is 2digits or more and cannot be stored in a char variable. Yet it worked.... In fact, when I type 'f' c becomes f. But why??
Characters are integers, or rather there are contexts where certain integer values are interpreted as characters. The type char is just an integer type in C, so an int can hold all values of a char.
One reason why getchar returns an int is because the special value EOF is not any of the integer values that represent characters (because if it were, you could not distinguish end of file from such a character being input). Once you have checked that the value returned by getchar was not EOF, all other possible return values are characters.
So in this program, there is c = getchar (). So i would assume that getchar returns to an integer regardless of what you type?
True. Detail: int getchar() returns not any integer but an int. The return value is either in the unsigned char range (example 0 ... 255) or EOF. EOF is a negative value.
char c = getchar();
printf("%c",c);
... should not work. As if I typed 'y' for example, the getchar function can return to an integer that is 2 digits or more and cannot be stored in a char variable. Yet it worked.... In fact, when I type 'f' c becomes f. But why??
If the user types y, the typical reuslt is a valueof 121 (ASCII y). The int in not "2 digits or more". The int is a value store in memory, typical 32-bits. It is not store as "digits".
The printf("%c",c); accepts an int as to match the "%c". As a char, c goes though integer promotion (to an int) before being passed to printf(char *format, ...) all it well specified.
The following will typically all print the same. "%c" recieves the int value, converts it to an unsigned char and then print the corresponding character associate with that value. usually ASCCI y.
char c = 'y';
printf("%c", c);
printf("%c", 'y');
printf("%c", 121);
printf("%c", 121 + 256);
Related
This question already has answers here:
Comparing unsigned char and EOF
(6 answers)
Closed 5 years ago.
I’m learning C using Xcode 8 and the compiler doesn’t run any code after a while- or for-loop executes. is this a bug? how can I fix it?
In the example provided below printf("code executed after while-loop"); never executes
#include <stdio.h>
int getTheLine(char string[]);
int getTheLine(char string[]) {
char character;
int index;
index = 0;
while ((character = getchar()) >= EOF) {
string[index] = character;
++index;
}
printf("code executed after while-loop");
return index;
}
int main(int argc, const char * argv[]) {
char string[100];
int length = getTheLine(string);
printf("length %d\n", length);
return 0;
}
getchar returns an int not a char, and comparison with EOF should be done with the != operator instead of the >= operator.
...
int character; // int instead of char
int index;
index = 0;
while ((character = getchar()) != EOF) { // != instead of >=
...
It's the >= EOF, which will let the condition be always true. The reason is that a "valid" result of getchar() will be a positive integer, and a "non-valid" result like end-of-file will be EOF, which is negative (cf. getchar()):
EOF ... integer constant expression of type int and negative value
Hence, any valid result from getchar will be >EOF, while the end-of-file-result will be ==EOF, such that >= EOF will always match.
Write != EOF instead.
Note further that you do not terminate your string by the string-terminating-character '\0', such that using string like a string (e.g. in a printf("%s",string)) will yield undefined behaviour (crash or something else probably unwanted).
So write at least:
while ((character = getchar()) != EOF) {
string[index] = character;
++index;
}
string[index]='\0';
Then there is still the issue that you may write out of bounds, e.g. if one enters more then 100 characters in your example. But checking this is now beyond the actual question, which was about the infinite loop.
The symbolic constant EOF is an integer constant, of type int. It's (usually) defined as a macro as -1.
The problem is that the value -1 as an (32-bit) int has the value 0xffffffff and as a (8-bit) char the same value would be 0xff. Those two values are not equal. Which in turn means that your loop condition will never be false, leading to an infinite loop.
The solution to this problem is that all standard functions that reads characters returns them as an int. Which means your variable character needs to be of that type too.
Important note: It's a compiler implementation detail if plain char is a signed or an unsigned type. If it is signed then a comparison to an int would lead to sign extension when the char value is promoted in the comparison. That means a signed char with the value 0xff would be extended to the int value 0xffffffff. That means if char is signed then the comparison would work.
This means that your compile have char as unsigned char. So the unsigned char value 0xff after promotion to int will be 0x000000ff.
As for why the value -1 becomes 0xffffffff is because of how negative numbers are usually represented on computers, with something called two's complement.
You also have another couple of flaws in your code.
The first is that since the loop is infinite you will go way out of bounds of the string array, leading to undefined behavior (and a possible crash sooner or later). The solution to this is to add a condition to make sure that index never reaches 100 (in the specific case of your array, should really be passed as an argument).
The second problem is that if you intend to use the string array as an actual string, you need to terminate it. Strings in C are actually called null terminated strings. That terminator is the character '\0' (equal to integer 0), and need to be put at the end of every string you want to pass to a standard function handling such strings. Having this terminator means that an array of 100 characters only can have 99 characters in it, to be able to fit the terminator. This have implications to the solution to the above problem. As for how to add the terminator, simply do string[index] = '\0'; after the loop (if index is within bounds of course).
In below program ,How is int being converted into char by printf()? Is it being demoted implicitly?
#include<stdio.h>
int main()
{
int c=2;
printf("%c",c);
}
The code is working fine! You will just get the ASCII character for c.
Let´s look on another example:
int c;
for (c = 97; c < 123; c++)
{
printf("%c",c);
}
This code would generate the following output:
abcdefghijklmnopqrstuvwxyz
If the value of c is greater than the biggest value of char the output just starts from the begin. This means c = 1 would generate the same output as c = 257.
In your code,
printf("%c",c);
works, because, as per the C11 standard, chapter §7.21.6.1, The fprintf() function, the %c format specifier,
c
If no l length modifier is present, the int argument is converted to an
unsigned char, and the resulting character is written.
So, the value held by c will get converted to an unsigned char, which then will be printed out using %c format specifier.
why does the following code work fine:
#include<stdio.h>
int main()
{
FILE *fp=fopen("input.txt","r+");
char c;
while((c=getc(fp))!=EOF)
{
printf("%c",c);
}
fclose(fp);
return 0;
}
but this code gives an error 'segmentation fault, core dumped':
#include<stdio.h>
int main()
{
FILE *fp=fopen("input.txt","r+");
char c;
while((c=fscanf(fp,"%c",&c))!=EOF)
{
printf("%c",c);
}
fclose(fp);
return 0;
}
input.txt contains a space separated list of characters like: a b c d e f
This will not work the way you expect:
while((c=fscanf(fp,"%c",&c))!=EOF)
getc() returns the character read, which can be EOF, but fscanf() returns the number of input items assigned, or EOF if there was a failure before any conversion took place.
You can't assign this return value to c, because the return value is not the character read (which you then try to print later).
You should try this instead:
while(fscanf(fp,"%c",&c) == 1)
Or:
while(fscanf(fp,"%c",&c) != EOF)
Which is equivalent to saying "As long as there is a character to read..."
Also, in the first case (the code where you use getc()), c should be int - you can have an infinite loop if the target platform uses unsigned chars, because c will always be converted to a positive int (again, only in platforms with unsigned chars), and thus will never be equal to EOF. If you check the manpages for getc() and putc() (and other functions that deal with a character), you will see that they receive int, not char.
I'm testing this function that's supposed to read input from the user but it throws me a segmentation fault
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_STRING_LENGTH 10
int
readinput(char *input)
{
int c;
int i=0;
while((c=getchar()) != EOF && c != '\n') //Here is where the warning occurs.
{
input[i]=c;
i++;
}
input[i]=0;
if(strlen(input)>0)
{
if(isalpha(input[0]) && input[1]=='-' && isalpha(input[2]) && strlen(input)==3)
return 0;
else if(!strcmp(input, "quit"))
return 1;
else if(!strncmp(input, "save ", 5))
return 2;
else if(!strcmp(input, "undo"))
return 3;
}
return -1;
}
int main()
{
char *str;
printf("write a string\n");
int nr=readinput(str);
printf("%d\n", nr);
printf("%s\n", str);
return 0;
}
I did notice the stupid error I made, but still, segmentation fault, why?
This is because EOF is defined (in my compiler) as -1 and char is unsigned byte. so it is always !=
c != '/n' is wrong
change it to
c != '\n'
c != '/n' should be c != '\n'
\ is an escape character which indicates, in the case where it is followed by n, a newline. /n will be treated as two distinct characters, which cannot properly be compared to a single char variable.
As for you segmentation fault, you'll need to allocate some space for str in your main function:
char* str = malloc(sizeof(char)*MAX_STRING_LENGTH);
or
char str[MAX_STRING_LENGTH];
but you'll also have to ensure you don't try to read a string that has more characters than your str array can hold.
It faults because you never allocated space for str and it points to a random location which causes readinput to try to store data in a place that doesn't exist.
The segmentation fault arises because you've passed an uninitialized pointer to the function readinput(). You need to do something like:
char str[4096];
int nr = readinput(str);
You should pass in a length of the array so that the called code can verify that it does not overflow its boundaries. Or you can live dangerously and decide that 4096 is big enough, which it probably will be until someone is trying to break your program deliberately.
The original compiler warning was because the multi-character constant '/n' has a value (of type int) which is outside the range of values that can be stored in a char, so when c is promoted to int, the != comparison with the (implementation-defined) value of '/n' is bound to be true. Hence the warning:
Warning: comparison is always true due to limited range of data type
All multi-character character constants have implementation-defined values. There are no portable multi-character character constants.
ISO/IEC 9899:2011 §6.4.4.4 Character constants
¶10 ... The value of an integer character constant containing more than one character (e.g.,
'ab'), or containing a character or escape sequence that does not map to a single-byte
execution character, is implementation-defined. ...
ok so im reading this book: The C Programming Language - By Kernighan and Ritchie (second Edition) and one of the examples im having trouble understanding how things are working.
#include <stdio.h>
#define MAXLINE 1000
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main(int argc, char *argv[])
{
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while((len = getline(line, MAXLINE)) > 1)
{
if(len > max)
{
max = len;
copy(longest, line);
}
}
if(max > 0)
printf("%s", longest);
getchar();
getchar();
return 0;
}
int getline(char s[], int lim)
{
int c, i;
for(i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if(c == '\n')
{
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while((to[i] = from[i]) != '\0')
++i;
}
the line : for(i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
where it says c = getchar(), how can an integer = characters input from the command line? Integers yes but how are the characters i type being stored?
Thanks in advance
Unlike some other languages you may have used, chars in C are integers. char is just another integer type, usually 8 bits and smaller than int, but still an integer type.
So, you don't need ord() and chr() functions that exist in other languages you may have used. In C you can convert between char and other integer types using a cast, or just by assigning.
Unless EOF occurs, getchar() is defined to return "an unsigned char converted to an int" (same as fgetc), so if it helps you can imagine that it reads some char, c, then returns (int)(unsigned char)c.
You can convert this back to an unsigned char just by a cast or assignment, and if you're willing to take a slight loss of theoretical portability, you can convert it to a char with a cast or by assigning it to a char.
The getchar() function returns an integer which is the representation of the character entered. If you enter the character A, you will get 'A' or 0x41 returned (upgraded to an int and assuming you're on an ASCII system of course).
The reason it returns an int rather than a char is because it needs to be able to store any character plus the EOF indicator where the input stream is closed.
And, for what it's worth, that's not really a good book for beginners to start with. It's from the days where efficiency mattered more than readability and maintainability.
While it shows how clever the likes of K&R were, you should probably be looking at something more ... newbie-friendly.
In any case, the last edition of it covered C89 and quite a lot has changed since then. We've been through C99 and now have C11 and the book hasn't been updated to reflect either of them, so it's horribly out of date.
The C char type is 8 bits, which means it can store the range of integers from (depending on if it is signed or not and the C standard does not dictate which it is if you do not specify it) either -128 to 127 or 0 to 255 (255 distinct values; this is the range of ASCII). getchar() returns int, which will be at least 16 bits (usually 32 bits on modern machines). This means that it can store the range of char, as well as more values.
The reason why the return type is int is because the special value EOF is returned when the end of the input stream is reached. If the return type were char, then there would be no way to signal that the end of the stream was encountered (unless it took a pointer to a variable where this condition was recorded).
Now let's play a game of logic.
Char is also a type of integer which has a smaller range than int, more specifically 8 bits, that is, 1 byte. As we all know, integer types consists of signed ( default ) and unsigned. As for char, the range of signed is -127 ~ 128 and the range of unsigned is 0 ~ 255. Now we know the type and "capability" of signed and unsigned char.
We human understand characters while the computer recogonize only binary sequence. Thus all kinds of programming language must provode a model to deal with the cevertion from characters to binary sequence. ASCII code is the standard for the mapping which applied in C and many other programming languages. It takes 0 - 255 to code basic characters like 0-9, a-z and A-Z, as well as usual special ones.
You may wonder that unsigned char is the exact choice. However, the progamming should know when to stop. The simplest way is to meet a special value, a negative one is a good choice since bigger positive values might be used for other languages. Finally, C choosed -1, which is more commonly called EOF.
Now we've got the point. Signed char will not suffice to code ASCII characters while unsigned leaves no room for the termination value. We require a larger range to balace this, that is, the int type. Savy?
Thanks for the answer of #cdhowie, it acually kindled me.
Every character (including numbers) entered on the command line is read as a character and every character has an integer value based on its ASCII code http://www.asciitable.com/.
Answer for your Question is answered. But just add 1 more thing.
As you are declaring variable c as int. It is pretty clear that you are taking values from 0 to 9 having ascii value of 48-57.
So you can just add 1 more line to the code-
c = c-48.