I want to calculate the length of an char array in C with a while loop.
But If I insert otto it returns the length of 5. Shouldn't be 4 the right answer?
char eingabe[255];
printf("geben Sie eine Zeile ein:");
fgets(eingabe, 255, stdin);
int i = 0;
while (eingabe[i] != '\0')
{
++i;
}
printf("Laenge: %d\n", i);
It's very likely that eingabe contains:
{ 'o', 't', 't', 'o', '\n', '\0', junk ... }
Check the man page of fgets().
Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer.
As you are reading from stdin, it stores the trailing newline [\n] character also in the supplied buffer.
Change your check to while ((eingabe[i] != '\0') && (eingabe[i] != '\n')). Hope this will solve your issue.
A newline character '\n' makes fgets stop reading, but it is considered a valid character by the function, and included in the string copied to the result. If you would like to avoid this, use fscanf like this:
fscanf(stdin, "%254[^\n]", eingabe);
Note the limit in the format: it is less than the actual length of the buffer to accommodate the null terminator.
Note: You can use strlen to compute the length of the string. It does the same thing as your for loop:
int i = strlen(eingabe);
The size of eingabe is 255. Now, if you want the number of initialized characters in it you should use strlen. But first, insert this code:
int n;
for(n = 0; n < 255; n++){
if(eingabe[n] == '\n'){
eingabe[n] = '\0';
}
}
eingabe[254] = '\0';
This code replaces the '\n' character with a NULL character. Without this, strlen will return wrong values. I also include eingabe[254] = '\0'; so that if the string read in is long enough that the newline character does not fit in the buffer, there is still a NULL character so that strlen can function properly
Related
Please ignore the Japanese there.
I attempt to count the length of the string entered from stdin using the following code. But it didn't work expectedly:
#include <stdio.h>
int main(int argc, const char *argv[]) {
char str[100];
printf("文字列を入力してください:"); // Please enter a string:
fgets(str,99,stdin);
int n = 0;
while (str[n++] != '\0');
printf("文字列の長さは%dです\n", n); // The length of the string is %d\n
return 0;
}
For example, if I enter glacious, I'll get n=10, which I expected to be n=8.
I understand that n++ will increment n after str[n++] != '\0' gets evaluated, and \0 is the default character appended to every string. But somehow this doesn't make sense to me. I know I can make this work for my purpose by adding n-=2 at the end, but I really want to understand what's going on here. Many thanks in advance!
"I attempt to count the length of the string entered from stdin"..."I know I can make this work for my purpose by adding n-=2 at the end, but I really want to understand what's going on here. "
Documentation for fgets() includes the following:
"...reads a line from the specified stream and stores it into the string pointed to by str. It stops when either (n-1) characters are
read, the newline character is read, or the end-of-file is reached,
whichever comes first."
This call, without checking the return value of the function, and by passing an incorrect value for the length of the string, limits the potential of detecting errors, and introduces the possibility of undefined behavior. To address these issues, change this:
fgets(str,99,stdin);
To, for example this:
if( fgets (str, sizeof str, stdin) != NULL )
{
...
Dissecting the following: given user input value: "glacious", str looks like this in memory:
|g|l|a|c|i|o|u|s|\n|\0|?|...|?|
0 1 2 3 4 5 6 7 8 9 10 99
int n = 0;
while(str[n++] != '\0');
iterations:
n at start n at finish
1st: n==0, str[0] (g) != \0, n++, n==1
2nd: n==1, str[1] (l) != \0, n++, n==2
3rd: n==2, str[2] (a) != \0, n++, n==3
4th: n==3, str[3] (c) != \0, n++, n==4
5th: n==4, str[4] (i) != \0, n++, n==5
6th: n==5, str[5] (o) != \0, n++, n==6
7th: n==6, str[6] (u) != \0, n++, n==7
8th: n==7, str[7] (s) != \0, n++, n==8
9th: n==8, str[8] (\n) != \0, n++, n==9
10th: n==9, str[9] (\0) == \0, n++, n==10
Clearly illustrates the state of all iterations, including the final post-increment of n, bringing it's total to 10 for a user input assumed to be only 8 characters. The \n and the final post-increment ( for \0) account for the additional value to n`. In summary the problem is simply adjusting your expectations to account for all characters in the buffer, including the ones you do not see.
Of interest, counting value of n does not equate to measuring the string length of str, for which the idiomatic method ( strlen() ), will yield 9. Given the definition of a C string, the following shows varying results for each corresponding method of looking at str, assuming initialization:
char str[100] = {0};
And str contents are: "glacious\n"//null terminator is implied
//method to calculate n in discussion above
// //yields n == 10
int len = strlen(str); //yields n == 9
//after using strcspn()
str[strcspn(str, "\n")] = 0;
len = strlen(str); //yields n == 8
size_t size = sizeof str; //yields size == 100
As an aside, if goal is to count the number of entries, and if an alternative approach is okay, consider simplifying the method...
Replacing this section:
char str[100];
printf("文字列を入力してください:");
fgets(str,99,stdin);
int n = 0;
while(str[n++] != '\0');
printf("文字列の長さは%dです\n", n);
return 0;
With this one which will break the loop upon seeing \n (newline character), or EOF (-1) (#define in stdio.h), resulting in a correct count of user inputs (minus newline):
int count = 0;
printf("Please enter a string:");
int c = fgetc(stdin);
while(( c != '\n') && (c != EOF))
{
count++; //only increments when c meets criteria
fputc(c, stdout);
c = fgetc(stdin);
}
printf("\n\nThe length of the string is: %d\n", count);
return 0;
If fgets() encounters a newline character in stdin, it will write it to the end of str before the null terminator, and because you're using a post-increment operator in the condition expression of your while loop, you are also including the null terminator in your total count. This accounts for the difference of 2 from your expected value n.
Consider using strcspn(), found in the <string.h> header, so that you can compute the length of str up until the first encountered \n, or until the null terminator if none is found:
size_t n = strcspn(str, "\n");
The loop while(str[n++] != '\0'); counts all bytes read by fgets(), including the newline and the null terminator because n is incremented at every test including the last one that evaluates to false.
Also note that fgets(str, 99, stdin); should be fgets(str, 100, stdin); or better if (fgets(str, sizeof str, stdin) == NULL) return 1; to avoid undefined behavior in case of unexpected end of file (empty file redirected as input stream).
Modified version:
#include <stdio.h>
#include <string.h>
int main(int argc, const char *argv[]) {
char str[100];
printf("文字列を入力してください:"); // Please enter a string:
if (!fgets(str, sizeof str, stdin))
return 1;
str[strcspn(str, "\n")] = '\0'; // strip the trailing newline if any
int n;
for (n = 0; str[n] != '\0'; n++)
continue;
printf("文字列の長さは%dです\n", n); // The length of the string is %d\n
return 0;
}
I'm just starting to code and I need help figuring out why this loop counts spaces within a string.
To my understanding, this code should tell the computer to not count a space "/0" and increase count if the loop goes through the string and it's any other character.
int main(void)
{
string t = get_string("Copy & Past Text\n");
int lettercount = 0;
for (int i = 0; t[i] != '\0'; i++)
{
lettercount++;
}
printf("%i", lettercount);
printf("/n");
}
\0 represents the null character, not a space. It is found at the end of strings to indicate their end. To only check for spaces, add a conditional statement inside the loop.
int main(void)
{
string t = get_string("Copy & Past Text\n");
int lettercount = 0;
for (int i = 0; t[i] != '\0'; i++)
{
if (t[i] != ' ')
lettercount++;
}
printf("%i", lettercount);
printf("\n");
}
Space is considered a character, your code goes through the string (an array of characters) and counts the characters until it reaches the string-terminating character which is '\0'.
Edit: set an if condition in the loop if(t[i] != ' ') and you wouldn't count the spaces anymore.
You misunderstand the nature of C strings.
A string is an array of characters with a low value ( '\0') marking the end of the string. Within the string some of the characters could be spaces (' ' or x20).
So the " t[i] != '\0' " condition marks the end of the loop.
A simple change:
if ( t[i] != ' ') {
lettercount++;
}
Will get your program working.
This for loop
for (int i = 0; t[i] != '\0'; i++)
iterates until the current character is the terminating zero character '\0' that is a null character. So the character is not counted.
In C there is the standard function isalpha declared in the header <ctype.h> that determines whether a character represents a letter.
Pay attention to that the user can for example enter punctuation symbols in a string. Or he can use the tab character '\t' instead of the space character ' '. For example his input can look like "~!##$%^&" where there is no any letter.
So it would be more correctly to write the loop the following way
size_t lettercount = 0;
for ( string s = t; *s; ++s )
{
if ( isalpha( ( unsigned char )*s ) ) ++lettercount;
}
printf("%zu\n", lettercount );
This statement
printf("/n");
shall be removed. I think instead you mean
printf("\n");
that is you want to output the new line character '\n'. But this character can be inserted in the previous call of printf as I showed above
printf("%zu\n", lettercount );
A null-terminator is the last leading element in a character array consisting of a string literal (e.g. Hello there!\0). It terminates a loop and prevent further continuation to read the next element.
And remember, a null-terminator isn't a space character. Both could be represented in the following way:
\0 - null terminator | ' ' - a space
If you want to count the letters except the space, try this:
#include <stdio.h>
#define MAX_LENGTH 100
int main(void) {
char string[MAX_LENGTH];
int letters = 0;
printf("Enter a string: ");
fgets(string, MAX_LENGTH, stdin);
// string[i] in the For loop is equivalent to string[i] != '\0'
// or, go until a null-terminator occurs
for (int i = 0; string[i]; i++)
// if the current iterated char is not a space, then count it
if (string[i] != ' ')
letters++;
// the fgets() reads a newline too (enter key)
letters -= 1;
printf("Total letters without space: %d\n", letters);
return 0;
}
You'll get something like:
Enter a string: Hello world, how are you today?
Total letters without space: 26
If a string literal has no any null-terminator, then it can't be stopped from getting read unless the maximum number of elements are manually given to be read till by the programmer.
I want to ask how can I scanf a letter that has value 0x00 (I know its null). I call my function echo -e '\x00' | function /.myfunction and I need to scanf it into a string for fprinting it later.
how can I scanf a letter that has value 0x00
Sure, with input Null Character1 Enter. "%s" treats a null character like any other non-white-space character.
char s[2];
scanf("%1s", s);
will nicely make s[0] == '\0' (due to input null character) and s[1] == '\0' due to the appended null character.
Subsequent code will likely have trouble working with s[] as a string though. You may want a new approach with "%c" or getchar(). Suggest an array of characters with an accompanying length, rather than a string.
If required to use scanf(), then keep track of the length with "%n".
char buf[100];
int n1,n2
if (scanf(" %n%99s%n2", &n1, buf, &n2) == 1) {
int length_read = n2 - n1;
for (int i=0; i<length_read; i++) {
if (isprint((unsigned char) buf[i])) {
printf("%c", buf[i]);
} else {
// do something special for non-printable characters.
printf("(%X)", (unsigned char) buf[i]);
}
}
}
1 Null Character may be difficult to enter directly other than piping as OP is using. Some keyboards allow Crtl Shift #.
This question already has an answer here:
fgets is getting skipped
(1 answer)
Closed 4 years ago.
Been trying to remove a character but the call to fgets gets skipped/jumped over. On different computers it runs like it should but for some reason, it skips and basically jumps to the end of the program. Any ideas?
Several problems in your code but I do not see any reason of fgets() skipped or jumped over. The getchar() function reads the next character from stdin. Generally when we give input to the getchar() function, we enter the character and press ENTER key. This left the \n character in input stream which can be consumed by next input function called. But in your case you are not calling any other input function after getchar().
[Try calling getchar() above fgets() and give input as - enter a character followed by ENTER key. You will see the fgets() is skipped because it consumes the leftover \n character from input stream stdin.]
Problem 1:
Look at this statement:
str[j] = str + 1;
Since, the str is a char array, str[j] represents a character at location j and str + 1 is pointer. So, this assignment is incompatible because you are trying to assign a char * type to a char. It should be:
str[j] = str[j + 1];
Problem 2:
Your code is having a logical problem. It is unable to handle the scenario where the character to be removed occurs consecutively in the input string. Test your code for input like "Hello World" [character l is occurring consecutively]. Your program output will be [after fixing problem 1]:
Enter a sentence:
Hello World
This is the sentence: Hello World
Enter character to remove:
l
Sentence after removal: Helo Word <==== character l not removed
Your program is unable to handle this particular scenario because once it removes a character, in the next iteration it starts with next character.
Problem 3:
The strlen() return type is size_t and you are using char type to receive its return value. Instead, you should use size_t type.
The getchar() return type is int [because it returns the special value EOF when the end of the input stream is reached]. You are using char type variable to receive getchar() return value.
One more point (it is not a problem but you should be aware of it and take the precautionary measures):
From fgets() [emphasis mine]:
Reads at most count - 1 characters from the given file stream and stores them in the character array pointed to by str. Parsing stops if end-of-file occurs or a newline character is found, in which case str will contain that newline character. If no errors occur, writes a null character at the position immediately after the last character written to str.
So, it is possible that your input buffer passed to fgets() can have new line character ('\n') in it. For e.g., if you give input Hello World followed by ENTER key than the input buffer str will have "Hello World\n" in it. In your case this will not cause any problem but few extra iteration of loop. You can remove the \n from str buffer like this:
fgets(str, 100, stdin);
str[strcspn(str, "\n")] = 0; // This will remove the trailing newline character from input buffer
Also, you should check the fgets() return. In case of failure, fgets() returns NULL.
Putting these altogether, you can do:
#include <stdio.h>
#include <string.h>
int main() {
char str[100];
size_t i, j, len;
int r;
printf("Enter a sentence: \n");
if (fgets(str, 100, stdin) == NULL) {
fprintf (stderr, ("fgets failed"));
return -1;
}
str[strcspn(str, "\n")] = 0;
printf("This is the sentence: %s\n", str);
printf("Enter character to remove: \n");
r = getchar();
/*If getchar returns EOF, no need to go through character removal logic*/
if (r != EOF) {
len = strlen(str);
i = 0;
while (str[i] != '\0') {
if (str[i] == (char)r) {
for (j = i; j < len; j++) {
str[j] = str[j+1];
}
len--;
}
else
i++;
}
}
printf("Sentence after removal: %s\n", str);
return 0;
}
Output:
# ./a.out
Enter a sentence:
Hello World
This is the sentence: Hello World
Enter character to remove:
l
Sentence after removal: Heo Word
# ./a.out
Enter a sentence:
zzzzz
This is the sentence: zzzzz
Enter character to remove:
z
Sentence after removal:
# ./a.out
Enter a sentence:
aazz
This is the sentence: aazz
Enter character to remove:
a
Sentence after removal: zz
Try changing r = getchar(); with scanf("%c\n", &r);.
Also, your loop has some bugs or inconsistencies:
You're assigning to str[j] the value of a pointer. Should be assigning to str[j] the value of str[j+1].
The end of the inner loop should be len-1 then.
j-- has no effect at all.
You should end your string with \0 after you're done, otherwise you'll print garbage (in my case it was a bunch of \ns).
Putting everything together:
for (i = 0; i < len; i++) {
if (str[i] == r) {
for (j = i; j < len-1; j++) {
str[j] = str[j+1];
}
len--;
}
}
str[len] = '\0';
printf("Sentence after removal: %s\n", str);
If you want to remove the \n at the end of the string after you read it, you can do
str[len] = '\0';
len--;
before the loop.
This is a function to read character by character from a file and place then convert the string to a float but the while loop is not terminating when a '/0' is read.
GSF555 "Gas Filter - Ford Escort" 64.50 9 <-- this is what is read in but from " 64.50 "
PKL070 "Park Lens - Toyota Corolla" 36.50 8
The while loop goes past the '/0' and also reads " 9" and characters from the next line of data.
I just have printf to see what was going wrong.
float getPrice(FILE * in){
char ch;
int i = 0;
char str[10];
ch = fgetc(in);
printf("INDEX + NUMBER = %d %c\n", i, ch);
if(ch == '\0')
ch = fgetc(in);
str[i++] = ch;
while(ch != '\0' && i < 10){
str[i++] = ch;
printf("Index I = %d\n", i);
ch = fgetc(in);
printf("3 %c\n",ch);
}
printf("STRING = %s\n", str);
return atof(str);
}
I am not sure from what I am seeing in your post where the \0 you are referring to is, but I can see a couple of problems.
First, fgetc returns an integer, not a character. This can be important for testing for the end-of-file, since the EOF is an integer with value -1, not a character which typically takes values of 0-255. You can change the declaration of ch to be an int, not a char. (Don't worry, this will not affect the print of ch with %c.)
Also, if you are trying to detect the end-of-line by testing with \0, it may not work. The end-of-line is the newline, \n. Depending on the underlying operating system, this may be take two characters, not one. You should be able to compare ch if declared as an int to the newline character, but it may not work if you keep ch as a char, if that is what you are trying to do.
the while loop is not terminating when a '/0' is read.
There's no such thing as '/0' (barring multibyte characters, for the pedants), and '\0' is a NUL whereas '0' is the zero digit. So replace those '\0' in your program with '0'. Although looking for '0' is odd; it's much more common to look for a delimiter, such as whitespace (or any other non-digit) that comes after the number.