String length prints weird numbers. Where is the issue in my code? - c

My task is: Write a program that calculates the length of a string without using the library
This is my answer, but there is a problem with execution. The length doesnt show properly ! the execution shows length as 107 or 127 for any string I insert.
#include <stdio.h>
#include <stdlib.h>
int main()
{
//Declaration of variables :
char ch[50+1];
int length, i;
//data :
printf("ch : ");
scanf("%s", &ch);
printf("\n");
//Search length of string :
i = 0;
do
{
if(ch[i] == '\0')
{
length = i;
}
else
{
i++;
}
}
while(ch[i] != '\0');
//Result "
printf("length pf %s is : %d \n", ch, length);
return 0;
} ```

There is a problem with the algorithm of the do-while loop.
The counter i increments short before the condition check.
If '\0' is found in the next array element (Note, that i is incremented) the loop breaks immediately and won´t be able to set length to i at the next iteration (because there is no next iteration).
Since length is not initialized, the program has undefined behavior.
Change:
do
{
if (ch[i] == '\0')
{
length = i;
}
else
{
i++;
}
}
while (ch[i] != '\0');
to
while (ch[i] != '\0') i++;
length = i;
or even simpler:
while (ch[i] != '\0') length++;
and omit the counter i, but you need to initialize length by 0 then.
Side Notes:
Change scanf("%s", &ch); to scanf("%s", ch);. - ch decays to a pointer to its first element.
Use a length modifier at scanf() -> scanf("%50s", ch); to ensure that no buffer overflow occurs when the user inputs a string longer than 50 characters.
Always check the return value of scanf() if an error occurred at consuming input.
Never ignore at the compiler warnings. For scanf("%50s", ch); the compiler should have raised a warning.

Related

why does the statements inside loop condition execute when condition is false in c programming?

I am just running a code to find the length of a given string input by the user in C programming language. I used a loop condition to determine the length but statements inside loop executes when the condition is false also. The code I have tried in c is:
#include <stdio.h>
#define ArrayLength 50
int StringLengthCount();
int main() {
printf("Hello, World!\n");
/*Question: Find inserted string's length, without build in function*/
int c=StringLengthCount();
printf("Your inserted string's length is:%d",c);
return 0;
}
int StringLengthCount(){
printf("\n");
printf("Please enter a sentence to find its length of character:");
char array1[ArrayLength];
fgets(array1,ArrayLength,stdin);
printf("Your inserted string is:%s\n",array1);
int i=0;
int count=0;
while(array1[i]!='\0'){
count++;
printf("%d character is %c",count,array1[i]);
printf("\n");
i++;
}
printf("\n");
printf("Your inserted string's total character i.e string length is:%d",count);
}
I am expecting the result 2 for a sample string input "we", but it gives result 3.
The output result in CLion compiler is given below
enter image description here
Can you kindly tell me why it happens?
If by "statements inside loop executes when the condition is false also" you mean that you see an extra character every time you execute remember that also the line feed (LF alias \n) character that you use to enter your string is part of the acquired string.
So even the empty string has one character that is \n or 0x10.
Your check should be something like this:
while (array1[len] != '\0' && array1[len] != '\n' )
And you function, as suggested in the comments, should have a return and could use just one variable like this:
int StringLengthCount() {
printf("\n");
printf("Please enter a sentence to find its length of character:");
char array1[ArrayLength];
fgets(array1, ArrayLength, stdin);
printf("Your inserted string is:%s\n", array1);
int len = 0;
while (array1[len] != '\0' && array1[len] != '\n' ) {
printf("%d character is %c", len + 1, array1[len]);
printf("\n");
len++;
}
printf("\n");
printf("Your inserted string's total character i.e string length is:%d\n\n",
len);
return len;
}
The function fgets will also read the newline character, so you need to change the condition in the while-loop from str[i] != '\0' to str[i] != '\n'. I have also implemented the suggested changes by Devolus.
#include <stdio.h>
#include <stdlib.h>
#define LEN 50
void string_length();
int main(void)
{
string_length();
return EXIT_SUCCESS;
}
void string_length(void)
{
printf("Enter a string: ");
char str[LEN];
fgets(str, LEN - 1, stdin);
printf("Your entered string is: %s\n", str);
int i = 0;
while (str[i] != '\n') {
printf("The %d. character is '%c'.\n", i + 1, str[i]);
++i;
}
printf("\nThe string's length is %d.\n", i);
}

Advice needed on loops and characters

I'm writing a simple code that will read in a series of characters which terminates upon reading in '\n' character/ typing enter. The code will also only read in a maximum of 50 characters. However, I am receiving errors when compiling, segmentation fault. I am unsure why the loop is not ending despite taking in '\n' character.
#include <stdio.h>
#include <ctype.h>
#define MAX 50
int main(void){
char str[MAX] = "0"; //initialise 1st char for the loop
int i;
printf("Enter your sentence, at most 50 character: \n");
for(i = 0; str[i] != '\n'; i++){ //terminates upon \n
str[i] = getchar();
putchar(str[i]);
}
return 0;
}
However, I tried moving the loop condition into the loop itself and use the if-break combo, it works perfectly.
#include <stdio.h>
#include <ctype.h>
#define MAX 50
int main(void){
char str[MAX] = "0"; //initialise 1st char for the loop
int i;
printf("Enter your sentence, at most 50 character: \n");
for(i = 0;; i++){ //terminates upon \n
str[i] = getchar();
putchar(str[i]);
if(str[i] == '\n')
break;
}
return 0;
}
Can any pros please explain to me why is this so and how do I correct it? Thanks a lot in advance! :)
RESOLVED. I'm checking the wrong element in the array. LOL.
Learn how for loop works.
The
for(expr1; expr2; expr3) // lack of expr2 means 'forever'
instr;
is equivalent to
expr1;
while(expr2) // expr2 is replaced with 'true' if empty
{
instr;
expr3;
}
So in your case
for(i = 0; str[i] != '\n'; i++)
the test str[i] != '\n' is calculated after the increment i++, hence it tests the wrong element of the array – the one past the one just read!
Additionally, you do not check the length of input data, so if you enter an input line longer than 50 characters, your loop will try to store the tail of a line past the end of declared array, which triggers an Undefined Behavior.
EDIT
A simple way to fulfill both criteria is to do both tests:
char str[MAX];
int i;
// print the actual value of defined maximum
printf("Enter your sentence, at most %d character: \n", MAX);
for(i = 0; i < MAX; i++){ // test the length
str[i] = getchar();
if(str[i] == '\n') // test the input char
break;
putchar(str[i]);
}
This happens because in the first case after str[i] = getchar(); ,the i++ statement executes before str[i] != '\n'; condition cheking . So the checking fails in your first code.
Try this modified for-loop:-
for(i = 0; (str[i] = getchar()) != '\n'; i++){ //Here checking happens while reading itself.
putchar(str[i]);
}
Remember that after the body of the for-loop executes, the flow of control jumps back up to the increment statement not to condition-cheking.

Character replacement and substitution in C

I'm trying to write a code which will replace character in the string user selects with character he/she does. Eg string london if user picks o and a then the output should be landan.
Here is the code:
#include <stdio.h>
#include <string.h>
#define MAXLEN 100
int function2(char str[], char drop, char sub) {
int i = 0; int num = 0;
while (str != NULL) {
if (str[i] == drop) {
str[i] = sub;
num++;
}
i++;
}
return num;
}
int main() {
char d, s;
char my_string[MAXLEN];
printf("Input your string\n");
scanf("%s", &my_string);
printf("Input character you want to drop\n");
scanf(" %c", &d);
printf("Now character you want to substitute\n");
scanf(" %c", &s);
function2(my_string, d, s);
printf("The string is %s\n", my_string);
return EXIT_SUCCESS;
}
It works up until the point where you actually print the altered string. All I get is Segmentation fault (core dumped). Note that code for function was not mine (I found it on some website, so owner of the original code for function2- Thank you in advance). Any help would be appreciated!
First of all, you should avoid using scanf. If you're interested for the reason and alternatives click here.
But back to your problem
while(str != NULL)
is an infinite loop, because the pointer won't become NULL
while(str[i] != '\0')
should do the trick. It checks each time if you've already arrived at the end of the string.
if (str != null){
while(str[i] != '\0'){
if (str[i] == drop){
str[i] = sub;
num++;
}
i++;
}
}
str is a char array, with str != NULL, you check that the array point to a valid memory address.
With while loop and i++, you loop all characters in array, because the string ends with '\0', you need to stop the loop with while(str[i] != '\0').
Your function runs an infinite loop because str never become NULL, but since i is incremented, str[i] will eventually access memory beyond the end of the string and at some point invalid memory causing a Segmentation fault.
Note also that it is not simple to tell scanf() the maximum number of characters to read into my_string. Using fgets() is much safer and allows a whole phrase to be substituted.
Here is a corrected version:
#include <stdio.h>
#include <stdlib.h>
#define MAXLEN 100
int function2(char str[], char drop, char sub) {
int num = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (str[i] == drop) {
str[i] = sub;
num++;
}
}
return num;
}
int main(void) {
char d, s;
char my_string[MAXLEN];
printf("Input your string\n");
if (!fgets(my_string, MAXLEN, stdin))
return EXIT_FAILURE;
printf("Input character you want to drop\n");
if (scanf(" %c", &d) != 1)
return EXIT_FAILURE;
printf("Now character you want to substitute\n");
if (scanf(" %c", &s) != 1)
return EXIT_FAILURE;
function2(my_string, d, s);
printf("The modified string is %s", my_string);
return EXIT_SUCCESS;
}

Using character for sentinel but receiving pointer error

I'm trying to program a loop that counts characters until it receives a certain sentinel value. The sentinel value is supposed to be a #, but I've also tried a 0 and a Z and had the same response.
When it compiles, I receive "warning: comparison between pointer and integer" for lines 16 (the line that calls the sentinel.)
If I don't define the sentinel, but instead rely on logical operators in the while statement, then I receive no error, but have an endless loop.
Thanks!
#include <stdio.h>
int main()
{
#define SENTINEL '#'
char ch;
int chcount;
printf("Enter your text, terminate with a #:");
scanf("%s", &ch);
chcount = 0;
while (ch != SENTINEL)
{
if ((ch >= 'A') && (ch <= 'Z'))
{
chcount = chcount +1;
printf("You have entered %d characters", chcount);
}
}
return(0)
}
With the %s format specifier, scanf expects the address of a char buffer, where the string you type will be copied.
And you gave the address &ch of a single char, which is obviously not enough to contain a "word" from input with its terminating null character.
Moreover, your loop reads no input from the user. Thus the endless loop.
This is because the way you use scanf(), with %s format specifier you are writing to a char*, not the char ch (as you've declared). In order to write to a single char variable, you should use a %c format specifier.
To fix this you should either use f.e. getchar() instead of scanf() or use scanf() (and change ch to char* then) but iterate over scanned string to check whether there is #.
I would recommend the first solution.
The while loop never ends so I changed your while loop.
I tried to change your program to:
#include <stdio.h>
#define SENTINEL '#'
int main()
{
char ch;
int chcount;
printf("Enter your text, terminate with a #:");
chcount = 0;
while ((ch = getchar()) != SENTINEL)
{
if ((ch >= 'A') && (ch <= 'Z'))
{
chcount = chcount + 1;
printf("You have entered %d characters\n", chcount);
}
}
return(0);
}
Some issues I found with your code:
scanf("%s", &ch);
It should be
scanf("%c", &ch);
Next, semicolon missing here: return(0);
However, since your aim is:
I'm trying to program a loop that counts characters until it receives a certain sentinel value. The sentinel value is supposed to be a #
I suggest moving your scanf() inside while loop:
#include <stdio.h>
int main()
{
#define SENTINEL '#'
char ch='0';
int chcount;
printf("Enter your text, terminate with a #:");
chcount = 0;
int i=0;
while (ch != SENTINEL)
{ scanf("%c", &ch);
if ((ch >= 'A') && (ch <= 'Z'))
{
chcount = chcount +1;
printf("You have entered %d characters", chcount);
i++;
}
}
return(0);
}
here is a working version of the posted code.
It contains numerous corrections.
Corrections include consistent/usable indentation and logic corrections
Note: not all implementations have the getline() function
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int sentinelFound = 0;
#define SENTINEL '#'
char* line = NULL;
size_t lineLen = 0;
printf("Enter your text, terminate with a #:");
int chcount;
getline(&line, &lineLen, stdin );
size_t i;
for( i=0; i<lineLen; i++)
{
if( SENTINEL == line[i] )
{
sentinelFound = 1;
break;
}
if ((line[i] >= 'A') && (line[i] <= 'Z')) // only count capital letters
{
chcount = chcount +1;
}
}
free( line );
if( !sentinelFound )
printf( "You did not enter the sentinel character!" );
else
printf("You have entered %d capital characters\n", chcount);
return(0);
} // end function: main

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.

Resources