#include <stdio.h>
int main()
{
int x=getlength("Hello",10);
printf("%d",x);
}
int getlength(char line[],int limit)
{
int x;
for(x=0;x<limit-1 && line[x]!=EOF && line[x]!='\n';++x)
printf("%c",line[x]) ;
printf("\n");
return x;
}
So this code seems to output this:
Hello%d then it outputs on a new line 9
What I don't understand is where the %d came from and how length of Hello%d is equal to 9
If anyone can explain I'd be happy.
A character string in C is terminated with a null character, '\0'. Change your for loop to test for the null character instead of EOF:
for (x=0; x < limit - 1 && line[x] != '\0' && line[x] != '\n'; ++x)
A function uses the constant EOF to signal the end of a file, but it's not used to terminate strings. That's because binary files can contain (unsigned) characters with values from 0 to 255. In order for a function to signal end-of-file, it must return a value that cannot appear within the file. Every implementation I've seen uses EOF = -1, because unsigned characters can never be negative.
A string, on the other hand, can only contain valid (unsigned) characters, so it can't use EOF to mark its end. Instead, it uses '\0', which is equivalent to the integer 0 and is a vailid—but unprintable—character.
A very common pitfall for programmers is to forget this, and either neglect to terminate a string with a null character (in which case a program will often scan past the end into invalid memory), or to try to manipulate strings that contain binary data (which sometimes includes a null character and terminates the string unexpectedly).
You for loop just counts to 9 as it never finds a EOF or a newline in the string "Hello".
The string "Hello" is terminated with a null character '\0', so change a part of for loop to line[x]!='\0'
The length of 'Hello' is 5. My hunch is you are reading those characters from the stack frame.
You are reading from location even after 'hello' on the stack. This is what is there on the stack.
Probably from the '%d' in the printf.
Try testing the NUL character value:
int getlength(char line[],int limit)
{
int x;
for(x=0;x<limit-1 && line[x]!='\n' && line[x]!='\0'; ++x)
{
printf("%c",line[x]) ;
}
printf("\n");
return x;
}
Related
I am trying to make function that compares all the letters from alphabet to string I insert, and prints letters I didn't use. But when I print those letters it goes over and gives me random symbols at end. Here is link to function, how I call the function and result: http://imgur.com/WJRZvqD,U6Z861j,PXCQa4V#0
Here is code: (http://pastebin.com/fCyzFVAF)
void getAvailableLetters(char lettersGuessed[], char availableLetters[])
{
char alphabet[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int LG,LG2,LA=0;
for (LG=0;LG<=strlen(alphabet)-1;LG++)
{
for(LG2=0;LG2<=strlen(lettersGuessed)-1;LG2++)
{
if (alphabet[LG]==lettersGuessed[LG2])
{
break;
}
else if(alphabet[LG]!=lettersGuessed[LG2] &&LG2==strlen(lettersGuessed)-1)
{
availableLetters[LA]=alphabet[LG];
LA++;
}
}
}
}
Here is program to call the function:
#include <stdio.h>
#include <string.h>
#include "hangman.c"
int main()
{
int i = 0;
char result[30];
char text[30];
scanf("%s", text);
while(i != strlen(text))
{
i++;
}
getAvailableLetters(text, result);
printf("%s\n", result);
printf ("%d", i);
printf ("\n");
}
Here is result when I typed in abcd: efghijklmnopqrstuvwxyzUw▒ˉ
If you want to print result as a string, you need to include a terminating null at the end of it (that's how printf knows when to stop).
for %s printf stops printing when it reaches a null character '\0', because %s expects the string to be null terminated, but result not null terminated and that's why you get random symbols at the end
just add availableLetters[LA] = '\0' at the last line in the function getAvailableLetters
http://pastebin.com/fCyzFVAF
Make sure your string is NULL-terminated (e.g. has a '\0' character at the end). And that also implies ensuring the buffer that holds the string is large enough to contain the null terminator.
Sometimes one thinks they've got a null terminated string but the string has overflowed the boundary in memory and truncated away the null-terminator. That's a reason you always want to use the form of functions (not applicable in this case) that read data, like, for example, sprintf() which should be calling snprintf() instead, and any other functions that can write into a buffer to be the form that let's you explicitly limit the length, so you don't get seriously hacked with a virus or exploit.
char alphabet[]={'a','b','c', ... ,'x','y','z'}; is not a string. It is simply an "array 26 of char".
In C, "A string is a contiguous sequence of characters terminated by and including the first null character. ...". C11 §7.1.1 1
strlen(alphabet) expects a string. Since code did not provide a string, the result is undefined.
To fix, insure alphabet is a string.
char alphabet[]={'a','b','c', ... ,'x','y','z', 0};
// or
char alphabet[]={"abc...xyz"}; // compiler appends a \0
Now alphabet is "array 27 of char" and also a string.
2nd issue: for(LG2=0;LG2<=strlen(lettersGuessed)-1;LG2++) has 2 problems.
1) Each time through the loop, code recalculates the length of the string. Better to calculate the string length once since the string length does not change within the loop.
size_t len = strlen(lettersGuessed);
for (LG2 = 0; LG2 <= len - 1; LG2++)
2) strlen() returns the type size_t. This is some unsigned integer type. Should lettersGuessed have a length of 0 (it might have been ""), the string length - 1 is not -1, but some very large number as unsigned arithmetic "wraps around" and the loop may never stop. A simple solution follows. This solution would only fail is the length of the string exceeded INT_MAX.
int len = (int) strlen(lettersGuessed);
for (LG2 = 0; LG2 <= len - 1; LG2++)
A solution without this limitation would use size_t throughout.
size_t LG2;
size_t len = strlen(lettersGuessed);
for (LG2 = 0; LG2 < len; LG2++)
I was going through a hash function and encountered a condition where the for loop is supposed to exit when a '\0' (NIL) character comes.
unsigned int hash_string (const char *s)
{
register unsigned int i;
for (i = 0; *s; s++) { // This for loop is supposed to end
// when a '\0' comes?
i *= 16777619;
i ^= *s;
}
return i;
}
As far as I know a C-Loop is supposed to end if a condition returns 0.
Here, however, there is no such condition and it still works?
Could someone also tell on what all conditions does a loop succed/fail?
The null character has the value of 0, so in your example, *s will evaluate to zero if it corresponds to the null termination of the character string.
From 5.2.1 Character sets
... A byte with all bits set to 0, called the null character, shall
exist in the basic execution character set; it is used to terminate a
character string.
Then in 6.4.4.4 Character constants
12 EXAMPLE 1 The construction '\0' is commonly used to represent the
null character.
*s de-references the character pointed by s.
If the character code is 0 the loop breaks and it passes for all values other than 0.
\0 is guaranteed to be 0, that why it is guaranteed that loop will terminate at string end when it encounters NUL character.
One of the reason for choosing \0 as string termination in C is to make constructs like this possible.
When *s evaluates to 0 or false, which is convertable from one another, the loop ends.
In fact, the integer representation for character \0 is 0. So it's the same thing.
I was trying an exercise from K&R (ex 1-17), and I came up with my own solution.
The problem is that my program appears to hang, perhaps in an infinite loop. I omitted the NUL ('\0') character insertion as I find C generally automatically attaches it to the end of a string (Doesn't it?).
Can somebody please help me find out what's wrong?
I'm using the GCC compiler with Cygwin on win8(x64), if that helps..
Question - Print all input lines that are longer than 80 characters
#include<stdio.h>
#define MINLEN 80
#define MAXLEN 1000
/* getlin : inputs the string and returns its length */
int getlin(char line[])
{
int c,index;
for(index = 0 ; (c != '\n') && ((c = getchar()) != EOF) && (index < MAXLEN) ; index++)
line[index] = c;
return (index); // Returns length of the input string
}
main()
{
int len;
char chArr[MAXLEN];
while((len = getlin(chArr))>0)
{
/* A printf here,(which I had originally inserted for debugging purposes) Miraculously solves the problem!!*/
if(len>=MINLEN)
printf("\n%s",chArr);
}
return 0;
}
And I omitted the null('\0') character insertion as I find C generally automatically attaches it to the end of a string (Doesn't it?).
No, it doesn't. You're using getchar() to read input characters one at a time. If you put the chars in an array yourself, you'll have to terminate it yourself.
The C functions that return a string will generally terminate it, but that's not what you're doing here.
Your input loop is a little weird. The logical AND operator only executes the right-hand-side if the left-hand-side evaluates to false (it's called "short-circuiting"). Rearranging the order of the tests in the loop should help.
for(index = 0 ; (index < MAXLEN) && ((c = getchar()) != EOF) && (c != '\n'); index++)
line[index] = c;
This way, c receives a value from getchar() before you perform tests on its contents.
I'm not positive about what's wrong, but you don't provide the input to the program so I'm guessing.
My guess is that in getlin your variable c gets set to '\n' and at that point it never gets another character. It just keeps returning and looping.
You never SET c to anything inside your getlin function before you test it, is the problem.
C does not insert a NUL terminator at the end of strings automatically. Some functions might do so (e.g. snprintf). Consult your documentation. Additionally, take care to initialize all your variables, like c in getlin().
1) C doesn't add a final \0 to your string. You are responsible for using an array of at least 81 chars and puting the final \0 after the last character you write in it.
2) You're testing the value of c before reading it
3) Your program doesn't print anything because printf uses a buffer for I/O which is flushed when you send \n. Modify this statement to print a final \n:
printf("\n%s",chArr);
to become:
printf("%s\n",chArr);
4) To send an EOF to your program you should do a Ctrl+D under unix and I don't know if it's possible for windows. This may be the reason why the program never ends.
Why do we need to add a '\0' (null) at the end of a character array in C?
I've read it in K&R 2 (1.9 Character Array). The code in the book to find the longest string is as follows :
#include <stdio.h>
#define MAXLINE 1000
int readline(char line[], int maxline);
void copy(char to[], char from[]);
main() {
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while ((len = readline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0)
printf("%s", longest);
return 0;
}
int readline(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'; //WHY DO WE DO THIS???
return i;
}
void copy(char to[], char from[]) {
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
My Question is why do we set the last element of the character array as '\0'?
The program works fine without it...
Please help me...
You need to end C strings with '\0' since this is how the library knows where the string ends (and, in your case, this is what the copy() function expects).
The program works fine without it...
Without it, your program has undefined behaviour. If the program happens to do what you expect it to do, you are just lucky (or, rather, unlucky since in the real world the undefined behaviour will choose to manifest itself in the most inconvenient circumstances).
In c "string" means a null terminated array of characters. Compare this with a pascal string which means at most 255 charactes preceeded by a byte indicating the length of the string (but requiring no termination).
Each appraoch has it's pros and cons.
Especially string pointers pointed to array of characters without length known is the only way NULL terminator will determine the length of the string.
Awesome discussion about NULL termination at link
Because C defines a string as contiguous sequence of characters terminated by and including the first null character.
Basically the authors of C had the choice to define a string as a sequence of characters + the length of string or to use a magic marker to delimit the end of the string.
For more information on the subject I suggest to read this article:
"The Most Expensive One-byte Mistake" by Poul-Henning Kamp
http://queue.acm.org/detail.cfm?id=2010365
You have actually written the answer yourself right here:
void copy(char to[], char from[]) {
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
The loop in this function will continue until it encounters a '\0' in the array from. Without a terminating zero the loop will continure an unknown number of steps, until it encounters a zero or an invalid memory region.
Really, you do not need to end a character array by \0. It is the char*, or the C representation of the string that needs to be ended by it.
As for array, you have to add a \0 after its end if you want to transfer it to the string (representer by char*).
On the other hand, you need to have \0 at the end of the array, if you want to address it as char* and plan to use char* functions on it.
'\0' in the array indicates the end of string, which means any character after this character is not considered part of the string.It doesn’t mean they are not part of the character array. i.e., we can still access these characters by indexing but they are just not part when we invoke string related things to this character array.
For a string to be in proper format and be able to work properly with the string functions, it must be a null-terminated character array. Without NULL, the programs show undefined behavior when we invoke string functions on the character array. Even though we might get lucky with the results most of the times, it still is an undefined behavior.
I've just looked it up
If your array is considered as string
Which means like this char array[MAX]="string";
Or like this scanf("%s",array);
Or char* table;
Then the NULL character '\0' will append automatically as the end of the characters on that table
But if you initialized it like this char array[MAX]={'n','o','t','s','t,'r'};
Or you fill it using character by character with %c format
for(int i=0;i<MAX;i++)
scanf("%c",&array[i]);
Or getchar() instead of scanf("%c",...)
Then you have to add '\0' by yourself
Because now it considered as any other array's type (int,float...) So the cases that we consider as empty are actually filled by random numbers or characters depends on the type
Meanwhile in the case of a string type the next character after the last considered character is by default '\0'
for more explanation the length of this char array[]="12345" is 6
The array[5]=='\0' will return 1
by other words you can't define a string array like this char array[3]="123" because we left no room for the '\0' that has to append automatically
last example char array[7]={'t','e','s','t','\0'};
Here array[4] is the NULL character
array[5] and array[6] are random values
But if it was string then "test" array[4] and 5 and 6 are all filled by the NULL character (NULL character can refers to any white_space as I think so tab '\t' and enter '\n' are also NULL characters just like '\0' which may refer to spacebar)
nota ben: we can't assign array[7] or more as we all know but if you try to output it, it'll show a random value as any empty case
It is string terminating symbol,When this is encountered ,compiler comes to know that your string is ended.
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. ...