Why is this still counting spaces within a String? - c

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.

Related

Code not working as expected in C

I was working on a program in C to count the number of spaces in a sentence. But I haven't managed to get it to work properly. If I enter something like Hello world 1234 how are you the output I'm getting is 3 when the output expected is 5.
My code is :
//Program to count number of words in a given Sentence
#include <stdio.h>
#include <string.h>
int main()
{
char sent[100];
char sentence[] = {' ', '\0'};
printf("\nEnter a sentence :\n");
gets(sent);
strcat(sentence, sent);
int l = strlen(sentence), i = 0, count = 0, countCh = 0;
printf("%d", l);
char ch, ch1;
for (i = 0; i < (l-1); i++)
{
ch = sentence[i];
if (ch == ' ')
{
ch1 = sentence[i+1];
if (((ch1 >= 'A') && (ch1 <= 'Z'))||((ch1 >= 'a') && (ch1 <= 'z')))
count++;
}
}
printf("\nNo of words is : %d", count);
return 0;
}
I used the same logic in Java and it worked fine. Could someone explain whats going wrong?
The problem in your code is with the definition of sentence. When you leave out the array dimension and initialize it, the size of the array will be determined by the length of the initializer.
Quoting the man page of strcat()
The strcat() function appends the src string to the dest string, overwriting the terminating null byte ('\0') at the end of dest, and then adds a terminating null byte. The strings may not overlap, and the dest string must have enough space for the result. If dest is not large enough, program behavior is unpredictable;
That is, the program will invoke undefined behavior.
This way, sentence has certainly way less memory than it it supposed to hold. Moreover, strcat() is not at all required there.
The correct way to do it will be
Define sentence with a proper dimention, like char sentence[MAXSIZE] = {0};, where MAXSIZE will be a MACRO having the size of your choice.
use fgets() to read the user input.
use isspace() (from ctype.h) in a loop to check for presence of space in the input string.
The following
if (((ch1 >= 'A') && (ch1 <= 'Z'))||((ch1 >= 'a') && (ch1 <= 'z')))
count++;
probably should be
if (ch1 != ' ')
count++;
As now " 12345" would not be counted as word.
Also count counts the spaces, so the word count is one more: hence 3 instead of 5.
Your sentence seems to have had the intention of counting the terminatin NUL.
If you want to count real words containing letters, use a bool state whether current and prior state of being in a letter differ.
As mentioned overflow is possible with your code.

why below code is giving garbage value?

why following code is giving garbage value ?
here I am trying to get an string as an input from user character by character. In the following code i have got input from user and stored in string[] array then in order to do some other operations i have stored the same in other array called temp_string[i]. But surprisingly i am getting garbage value in output.and also length calculated using strlen is not correct. can anybody look at this code and explain whats going wrong?
#include<stdio.h>
#include<stdio.h>
int main()
{
char ch;
int i = 0, j = 0;
int length = 0;
int lengthsb = 0;
char string[100];
printf(" Enter the string to divide\n ");
while(ch != '\n')
{
ch = getchar();
string[i] = ch;
i++;
}
char temp_string[i];
printf("%s", string);
i = 0;
while(string[i] != '\n')
{
temp_string[i] = string[i];
i++;
}
length = strlen(temp_string);
printf("Entered string is %s and its length is %d\n", temp_string, length);
}
You forgot to add the null at the end of the string.
C strings are null-terminated, that means that all operations in c strings expect a null to mark the end of the string, including functions like strlen.
you can achieve that just adding:
string[i] = '\0';
After fill the string.
Another thing, what happens if the user enters a string bigger than 100? Is good to validate the input for these cases, otherwise you can get a buffer overflow.
You need to add a NULL - terminated at the end of your string. Add \0.
You need to put a '\0' char at the end of the string so strlen(), printf() and other C functions dealing with strings will work. That is how the C API knows it reached the end of the string.
Also, you don't want to set new characters at the memory space past the string array. So you better check that in your loop (and save a last array item to set the '\0').
while (ch != '\n' && i < 99)
{
ch = getchar();
string[i] = ch;
i++;
}
string[i] = '\0'; // set the string terminator past the end of the input
Remember to do the same after copying the characters to temp_string. (By the way, you can replace that loop with a call to strcpy(), that does exactly that, except it will end only when it finds a '\0'.)
You might also want to read What's the rationale for null terminated strings?
Here is your Final Code:
#include<stdio.h>
#include<stdio.h>
#include<string.h>
int main()
{
char ch;
int i = 0, j = 0;
int length = 0;
int lengthsb = 0;
char string[100];
char temp_string[100];
printf(" Enter the string to divide\n ");
while(ch != '\n')
{
ch = getchar();
string[i] = ch;
i++;
}
string[i]=NULL;
printf("%s", string);
i = 0;
while(string[i] != '\0')
{
temp_string[i] = string[i];
i++;
}
temp_string[i]=NULL;
length = strlen(temp_string);
printf("Entered string is %s and its length is %d\n", temp_string, length);
}
In the above code what exactly you are missing is NULL or '\0' termination of the string. I just added it to make it useful.

Redundant characters in string, c

I'm trying to get selected characters from one string into another. Everything looks okay, except the program keeps adding additional characters to the output. And it seems that it tends to add different number of these "unecessary" characters. Where might the problem be?
int main(void) {
int i,j=0;
char string[256];
char second_arr[256];
scanf("%255s", string);
for(i=0;i<256;i++){
if(string[i]=='('||string[i]=='['||string[i]=='{'){
second_arr[j]=string[i];
j++;
}
}
printf("%s", second_arr);
}
Say,
input: (hello)(}[} --->
Output:(([[H
Problem 1: You're not testing scanf for failure. It can return EOF, or zero to indicate the input didn't match your format string.
Problem 2: You're copying all 256 chars even if the user entered fewer, which means you're copying junk.
Problem 3: You're not adding a null terminator to second_arr.
Just do this:
if (scanf("%255s", string) != 1)
{
printf("scanf failed\n");
return 1;
}
for (i = 0; i < 256 && string[i]; i++) {
if(string[i]=='('||string[i]=='['||string[i]=='{'){
second_arr[j]=string[i];
j++;
}
}
second_arr[j] = '\0';
printf("%s", second_arr);
return 0;
Try this:
for (i=0; string[i]!=0; i++) // iterate the input string until the null-character
{
if (string[i] == '(' || string[i] == '[' || string[i] == '{')
second_arr[j++] = string[i];
}
second_arr[j] = 0; // set a null-character at the end of the output string
There is nothing to terminate the second string. Add
||string[i]=='\0'
to your conditions. Also break out of the loop when you see that null char, but only after you have copied it.
You should add at the end of second string second_arr the char '\n' to indicate its end.

converting new line character

I am trying to convert new line character \n to dos style which is \r\n , without using libc.
here is my attempt, what am I doing wrong?
for(i = 0; str[i]!='\0'; ++i)
{
if ('\r' == str[i] && '\n'==str[i+1])
++count;
}
strPtr = malloc(i + 1 + count);
for(i = j = 0; str[i]!='\0'; ++i)
{
if ('\r' == str[i])
strPtr[j++] = "";
}
strPtr[j] = 0;
output should now be
"Hi\r\n, How are you \r\n, are you okay\r\n"
There are many problems here. Firstly, you are modifying the string in place using the original buffer. However, the original buffer does not have enough space to store the additional \r characters. You'll need to allocate a larger buffer.
Secondly, a UNIX-style carriage return character is not stored as two separate \ and n characters. It is a single ASCII character with a value of 0xA, which can be represented using the escape sequence \n. So to check if your current character is a newline character, you want to say strPtr[i] == '\n'
Finally, you are overwriting the old buffer when you say strPtr[i-1] = '\r'. This will replace the character before the \n, (such as the i in Hi).
Basically, what you want to do is create a second buffer for output, and copy the string character by character to the output buffer. When you encounter a \n character, instead of copying a single \n to the new buffer, you copy \r\n.
The size of the output buffer needs to be twice the size of the input buffer to handle the case of an input string where every character is \n, plus 1 for the NULL terminator. However, you can compute an optimal size for the output buffer by counting the number of \n characters in the original string beforehand.
All the escape sequence characters in C language are one character which is stored in one byte of memory only, dont consider it as two.
So you can directly check for a byte to \n as you are checking for \0.
If you want to replace \n(1 character) with \r\n(2 character) means, str should have additional memory, but in your program its not having additional memory.
char *a = "\n"; //This is one byte
char *b = "\\\n"; //This is two byte, 1st byte for '\' and 2nd byte for new line
char *c = "\\\r\n"; //Similarly this is three byte
char *c = "\r\n"; //Similarly this is two byte
All the below escape sequence characters are single byte character in C language.
\n – New line
\r – Carriage return
\t – Horizontal tab
\\ – Backslash
\' – Single quotation mark
\" – Double quotation mark
You can't do this in-place. You're adding a new character ('\r') for every '\n' which means the string must expand. The worst case scenario is that every character is a '\n' which means we would double the size of the string. Thus, let's make a buffer twice the size of the original string.
strtmp = malloc(strlen(str) * 2 + 1); /* +1 for null */
strcpy(strtmp, str);
strptr = strtmp;
for (i = 0; str[i] != 0; i++)
{
if ((str[i] == '\\') && (str[i+1] == 'n'))
{
*strptr++ = '\\';
*strptr++ = 'r';
}
*strptr++ = str[i];
}
printf(strtmp);
free(strtmp);
The \n in your string is an escape sequence and is represented by one character.
Your code should be like this:
int main(void)
{
char str[] = "Hi\n, How are you \n, are you okay\n";
char *strPtr = str;
int i, j;
int count=0;
for(i = 0; str[i]!='\0'; ++i)
{
if (`\n` == str[i]) ++count;
}
strPtr = malloc(i + 1 + count);
for(i = j = 0; str[i]!='\0'; ++i)
{
if ('\n' == str[i]) strPtr[j++] = `\r`;
strPtr[j++] = str[i];
}
strPtr[j] = 0;
printf("This many times we changed it", count);
}
EDIT
As you have decided to change the question (BTW - Just add to the question for clarification and not delete huge chunks of the original OP as the answers will not make any sense for future visitors) - here is the code:
int main(void)
{
char str[] = "Hi\r\n, How are you \r\n, are you okay\r\n";
int i, j;
for (i = j = 0; 0 != str[i]; ++i)
{
if ('\r' == str[i] && '\n' == str[i + 1])
{
++count;
}
else
{
str[j++] = str[i];
}
}
str[j] = 0;
.. etc - str is without \r\n but \n, count is the number of lines.

Printing a string with null characters in it

I take as input a string with spaces in it and replace the spaces with the NULL character '\0'. When I print the string now, I expect only the part till the first NULL character which was the first space earlier but I am getting the original string.
Here is the code-
#include<stdio.h>
int main(){
char a[1000];
int length, i = 0;
length = 0;
scanf("%[^\n]s", a);
while(a[i]!='\0')
i++;
length = i;
printf("Length:%d\n", length);
printf("Before:%s\n", a);
for(i=0;i<length;i++){
if(a[i] == " ")
a[i] = '\0';
}
printf("After:%s\n", a);
return 0;
}
What is wrong in this?
Your code is wrong.
for(i=0;i<length;i++){
if(a[i] == " ")
a[i] = '\0';
}
The comparison is trying to compare a character with a pointer (denoted by " " ->This becomes a pointer to a string of characters. In this case the string is only having a space.)
This can be fixed by the following replacement
for(i=0;i<length;i++){
if(a[i] == ' ')
a[i] = '\0';
}
Or better to do it in this manner, since you can have other whitespace too like tab, apart from space.
(Please include ctype.h also)
for(i=0;i<length;i++){
if(isspace(a[i]))
a[i] = '\0';
}

Resources