I have a question about c programming infinite loop using While - c

int main() {
int count[26]={0};
char input;
int i;
while(1){
scanf("%c", &input);
if(input>='a'&&input<='z') count[input-'a']++;
else if(input>='A'&&input<='Z') count[input-'A']++;
else break;
}
for (i=0; i<26; i++) {
if(count[i]!=0) {
printf("%c : %d\n", 'A'+i, count[i]);
}
}
return 0;
}
I want this code to stop when a value other than A~Z or a~z is entered.
How should I fix this code?

Here is a demonstrative program that shows how the while loop can look. I considered the space character ' ' as a valid character but it is not counted.
#include <stdio.h>
#include <ctype.h>
int main(void)
{
unsigned int count['Z' - 'A' + 1] = { 0 };
const size_t N = sizeof( count ) / sizeof( *count );
char c;
while ( scanf( "%c", &c ) == 1 &&
( ( 'A' <= ( c = toupper(( unsigned char ) c ) ) && c <= 'Z' ) || c == ' ' ) )
{
if ( c != ' ' ) ++count[c - 'A'];
}
for ( size_t i = 0; i < N; i++ )
{
if ( count[i] )
{
printf( "'%c' : %u\n", ( char )( 'A' + i ), count[i] );
}
}
return 0;
}
If to enter this sentence
Hello World
then the program output will be
'D' : 1
'E' : 1
'H' : 1
'L' : 3
'O' : 2
'R' : 1
'W' : 1

Related

C program to count the character with the lowest frequency

I have written this code for finding the character with the minimum frequency.
So, giving in input "Hi, how is the weather todayy Dori", the output should be
The letter with the minimum frequency is ā€˜sā€™ and the frequency is 1.
But it shows
How to remove the that coma what is my mistake here
#include<stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX 1000
int main()
{
char str[MAX];
int fre[MAX],i,q,r,co=0,num;
printf("The string : ");
gets(str);
for(q=0;str[q];q++);
r=num=q;
for(i=0;i<num;i++)
{
fre[i]=num;
co=1;
if(str[i])
{
for(q=i+1;q<num;q++)
{
if(tolower(str[i]) == tolower(str[q]))
{
{
co++;
str[q]='\0';
}
}
fre[i]=co;
if(co<=r)
r=co;
}
}
}
printf("The letter with the minimum frequency is");
for(q=0;q<num;q++)
{
if(fre[q]==r)
{
printf(" '%c' ",str[q]);
}
}
printf("and the frequency is %d \n ",r);
return 0;
}
For starters the function gets is unsafe and is not supported by the C Standard. Instead use the standard C function fgets.
As an entered string in general can be very big while letters in the string converted to the lower case can be in the range of ['a', 'z'] then there is no sense to declare such a big array as the array fre declared like.
int fre[MAX];
As you already included the header <string.h> then there is no sense manually to calculate the length of the entered string.
for(q=0;str[q];q++);
To exclude non-letters characters from counting you can use the standard C function isalpha declared in the header <ctype.h>.
Pay attention to that in general the entered string can have no letters.
Here is a demonstrative program that shows how your approach can be implemented.
#include <stdio.h>
#include <ctype.h>
int main(void)
{
enum { MAX = 1000 };
char s[MAX];
size_t frequency[ 'z' - 'a' + 1] = { 0 };
const size_t N = sizeof( frequency ) / sizeof( *frequency );
printf( "The string: " );
if ( fgets( s, MAX, stdin ) )
{
for ( const char *p = s; *p; ++p )
{
if ( isalpha( ( unsigned char )*p ) )
{
++frequency[tolower( ( unsigned char )*p ) - 'a'];
}
}
size_t min = 0;
for ( size_t i = 0; i < N; i++ )
{
if ( frequency[i] != 0 && ( min == 0 || frequency[i] < min ) )
{
min = frequency[i];
}
}
if ( min == 0 )
{
puts( "There ie no letters in the entered string." );
}
else
{
printf( "The letter with the minimum frequency is: " );
for ( size_t i = 0; i < N; i++ )
{
if ( frequency[i] == min ) printf( "%c ", ( int )('a' + i ) );
}
printf( "\nand the frequency is %zu\n ", min );
}
}
return 0;
}
The program output might look like
The string: Hi, how is the weather todayy Dor
The letter with the minimum frequency is: s
and the frequency is 1
There's really no reason to read more than one character at a time. In general, that's a good pattern to try and follow. eg:
#include <stdio.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
int main(void)
{
int c;
int fre[26] = {0};
printf("The string : ");
while( (c = getchar()) != EOF ) {
putchar(c);
if( isalpha(c) ) {
fre[tolower(c) - 'a'] += 1;
}
}
printf("The letter with the minimum frequency is");
int idx = 0;
int m = INT_MAX;
for( int q = 0; q < 26; q++ ) {
if( fre[q] > 0 && fre[q] < m ) {
idx = q;
m = fre[q];
}
}
printf(" '%c', with frequency %d\n", idx + 'a', fre[idx]);
return 0;
}

How can i make first letter of all words in a string uppercase recursively? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I wonder how can i make this. I don't want any iteration or isalpha() and toupper() functions. We want to use our own code to read input. We assume that user enters all characters lowercase. This is what i've tried so far:
define MAX_LENGTH 100
int read_line(char str[],int);
void capitalize(char[]);
int main (void){
char A[MAX_LENGTH];
printf("Enter a text \n");
read_line(A, MAX_LENGTH);
capitalize(A);
puts(A);
}
int read_line(char str[],int n){
int ch,i=0;
while ((ch = getchar()) != '\n'){
if(i<MAX_LENGTH)
str[i++] = ch;
}
str[i] = '\0';
return i;
}
void capitalize(char str[]){
int x = strlen(str);
static int i = 0;
if(str[i]=='\0')
return;
if(str[i-1]==' '|| i == 0)
str[i] -= 32;
i++;
return capitalize(&str[i]);
}
Output is like this:
Enter a text:
asdf sdf df
Asdf sdf df
What is wrong with my code?
You code is invalid. For example even the function read_line
int read_line(char str[],int n){
int ch,i=0;
while ((ch = getchar()) != '\n'){
if(i<MAX_LENGTH)
str[i++] = ch;
}
str[i] = '\0';
return i;
}
is incorrect at least because when i is equal to MAX_LENGTH -1 there is an access memory beyond the character array
str[i] = '\0';
That is the condition of the loop is initially written incorrectly.
As for the recursive function then it can look for example the following way.
#include <stdio.h>
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
if ( *s )
{
int blank = is_blank( *s );
if ( !blank )
{
*s &= ~' ';
}
capitalize( s + 1 );
if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
{
*( s + 1 ) |= ' ';
}
}
return s;
}
int main(void)
{
char s[] = "hello everybody. how do you do?";
puts( s );
puts( capitalize( s ) );
return 0;
}
The program output is
hello everybody. how do you do?
Hello Everybody. How Do You Do?
Here is a similar demonstrative program but with your fixed function read_line.
#include <stdio.h>
#define MAX_LENGTH 100
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
if ( *s )
{
int blank = is_blank( *s );
if ( !blank )
{
*s &= ~' ';
}
capitalize( s + 1 );
if ( !blank && !is_blank( *( s + 1 ) ) && *( s + 1 ) )
{
*( s + 1 ) |= ' ';
}
}
return s;
}
size_t read_line( char *s, size_t n )
{
int ch;
size_t i = 0;
while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
{
s[i++] = ch;
}
s[i] = '\0';
return i;
}
int main(void)
{
char s[MAX_LENGTH];
read_line( s, MAX_LENGTH );
puts( s );
puts( capitalize( s ) );
return 0;
}
If to enter the string
hello everybody. how do you do?
then the program output will be the same as shown above.
hello everybody. how do you do?
Hello Everybody. How Do You Do?
If the bit-wise operations is unclear for you then you can substitute this statement
for this statement
*s &= ~' ';
for this statement
*s -= 'a' - 'A';
and this statement
*( s + 1 ) |= ' ';
for this statement
*( s + 1 ) += 'a' - 'A';
If to use your approach to the implementation of a recursive function with a static variable then it will be interesting to you why your function does not work will not be?
Let's consider it ignoring the first statement with the call of strlen.
void capitalize(char str[]){
int x = strlen(str);
static int i = 0;
if(str[i]=='\0')
return;
if(str[i-1]==' '|| i == 0)
str[i] -= 32;
i++;
return capitalize(&str[i]);
}
First of all after the first call the function for one string you may not call it a second time for another string because the static variable i will not be already equal to 0.
The condition of the if statement should be written at least like
if ( i == 0 || str[i-1]==' ' )
that is the order of sub-expressions shall be changed.
The return statement shall not contain an expression
return capitalize(&str[i]);
you could just write
capitalize(&str[i]);
Nevertheless the initial value of the pointer str was changed. However within the function you are using the index i relative the initial value of str of the first call of the function.
And I am sure it is interesting to you how correctly to rewrite the function, is not it?
The function can look the following way as it is shown in the demonstrative program below.
#include <stdio.h>
#define MAX_LENGTH 100
int is_blank( char c )
{
return c == ' ' || c == '\t';
}
char * capitalize( char *s )
{
static size_t i = 0;
if ( *( s + i ) )
{
if ( !is_blank( s[i] ) && ( i == 0 || is_blank( s[i-1] ) ) )
{
s[i] -= 'a' - 'A';
}
++i;
capitalize( s );
--i;
}
return s;
}
size_t read_line( char *s, size_t n )
{
int ch;
size_t i = 0;
while ( i + 1 < n && ( ch = getchar() ) != EOF && ch != '\n' )
{
s[i++] = ch;
}
s[i] = '\0';
return i;
}
int main(void)
{
char s[MAX_LENGTH];
read_line( s, MAX_LENGTH );
puts( s );
puts( capitalize( s ) );
return 0;
}
I would write the following:
void capitalize(char* str) {
if (! *str) return; // job done
*str = toupper(*str); // capitalize "correctly"
capitalize(++str);
}
the main problem is that you're using index and recursion at the same time, simple recursive solution would be:
void capitalize(char* str, bool start){
if (!*str) return; // end as soon as \0 is met
if (start)
if (*str >= 'a' && *str <= 'z') *str = (*str - 'a') + 'A'; // capitalize latin letters
capitalize(str + 1, *str == ' '); // work with next symbol
}
should be called as capitalize(str, true)
Should do the job:
void capitalize(char *s)
{
while(1) {
while (*s==' ') s++; // skip spaces
if (!*s) return; // check for end
if ('a'<=*s && *s<='z') *s -= 32; // capitalize if needed
while (*s && *s!=' ') s++; // advance
} // loop
}
(I call this "Stupid Character Processing")

C - Counting words in a string

i've been trying to do a function that counts the number of words in a string in C. However, in some casas (as the one in the example) it should return 0 and not 1... any ideas of what could be wrong?
#import <stdio.h>
int contaPal(char s[]) {
int r;
int i;
r = 0;
for (i = 0; s[i] != '\0'; i++) {
if (s[i] == '\n')
r = r + 0;
if (s[i] != ' ' && s[i + 1] == ' ' && s[i + 1] != '\0')
r++;
if (s[i] != ' ' && s[i + 1] == '\0') {
r++;
}
}
return r;
}
int main () {
char s[15] = { ' ', '\n', '\0' };
printf("Words: %d \n", (contaPal(s)));
return 0;
}
You should not treat '\n' differently from any other whitespace character.
Here is a simpler version:
#include <ctype.h>
#include <stdio.h>
int contaPal(const char *s) {
int count = 0, hassep = 1;
while (*s) {
if (isspace((unsigned char)*s) {
hassep = 1;
} else {
count += hassep;
hassep = 0;
}
s++;
}
return count;
}
int main(void) {
char s[] = " \n";
printf("Words: %d\n", contaPal(s));
return 0;
}
I suppose that the word is any sequence of characters excluding white space characters.
Your function returns 1 because for the supplied string when the new line character is encountered the variable r is increased due to this condition
if (s[i] != ' ' && s[i + 1] == '\0') {
r++;
}
So the function implementation is wrong.
It can be defined the following way as it is shown in the demonstrative program
#include <stdio.h>
#include <ctype.h>
size_t contaPal( const char s[] )
{
size_t n = 0;
while ( *s )
{
while ( isspace( ( unsigned char )*s ) ) ++s;
n += *s != '\0';
while ( *s && !isspace( ( unsigned char )*s ) ) ++s;
}
return n;
}
int main(void)
{
char s[] = { ' ', '\n', '\0' };
printf( "Words: %zu\n", contaPal( s ) );
return 0;
}
Its output as you expect is
Words: 0
A simple illustration using existing character test functions:
int main(void)
{
int cnt = 0;
int numWords = 0;
BOOL trap = 0; //start count only after seeing a word
char *sentence = "This is a sentence, too long.";
//char *sentence2 = " ";//tested for empty string also
while (*sentence != '\0')
{
if ( isalnum (*sentence) ) //word is found, set trap and start count
{
sentence++; //alpha numeric character, keep going
trap = 1;
}
else if ( (( ispunct (*sentence) ) || ( isspace(*sentence) )) && trap)
{ //count is started only after first non delimiter character is found
numWords++;
sentence++;
while(( ispunct (*sentence) ) || ( isspace(*sentence) ))
{ //handle sequences of word delimiters
sentence++;
}
}
else //make sure pointer is increased either way
{
sentence++;
}
}
return 0;
}
The line:
if (s[i] != ' ' && s[i + 1] == ' ' && s[i + 1] != '\0')
r++;
Exactly matches the case when you look on '\n'.
You should use if ... else if ....

Got stuck in the final part of a program for encryption in Vigenere

I am attending the online course cs50 on Edx and I have an assignment in which I have to create a program where the user enters a keyword ( used then for encryption ) and a string that needs to be encrypted in Vigenere cipher.
Vigenere works by encrypting a text following a keyword: for example if my string is "Hello" and my keyword is "abc" : a is equal to 0 in alphabetical characters, b to 1, and c to 2; so the letter h in the string is encrypted without switching characters ( s letter a in the keyword is = 0), the letter e is switched by one position and is encrypted to f, and so on. If the keyword has a length less than that of the string (like in this case) the encryption has to use again the first character of the keyword and this is my problem.
In fact, I think I implemented well the whole program but I am not sure how to take into consideration if a keyword has less characters than the string entered.
The program is now returning only the first char of my string encrypted and the first char not encrypted and then it stops.
I do not ask for a complete solution, but I just want to understand how I can solve my program problem.
Here is my program:
#include <stdio.h>
#include <cs50.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
int vigenere_low( char c )
{
int v = c - 'a';
return v;
}
int vigenere_up( char c )
{
int v = c - 'A';
return v;
}
int keyword_low( char c )
{
int k = c - 'a';
return k;
}
int keyword_up( char c )
{
int k = c - 'A';
return k;
}
int main( int argc, string argv[] )
{
string p;
string keyword = argv[1];
if ( argc != 2 )
{
printf("Usage: ./vigenere keyword\n");
return 1;
}
for ( int i = 0, n = strlen(keyword); i < n; i++ )
{
if ( !isalpha( keyword[i]) )
{
printf("Usage: ./vigenere keyword(alphabetical) \n");
return 1;
}
}
p = GetString();
int j = 0;
for ( int i = 0, n = strlen( p ); i < n; i++ )
{
if ( isalpha( p[i]) )
{
if ( islower( p[i]) )
{
if ( islower( keyword[j]) )
{
int a = (( vigenere_low( p[i]) + keyword_low( keyword[j]) ) % 26 ) + 'a';
printf("%c", a);
j++;
}
else
{
int a = (( vigenere_low( p[i]) + keyword_up( keyword[j]) ) % 26 ) + 'a';
printf("%c", a);;
j++;
}
}
if ( isupper( p[i]) )
{
if ( islower( keyword[j]) )
{
int a = (( vigenere_up( p[i]) + keyword_low( keyword[j]) ) % 26 ) + 'A';
printf("%c", a);
j++;
}
else
{
int a = (( vigenere_up( p[i]) + keyword_up( keyword[j]) ) % 26 ) + 'A';
printf("%c", a);
j++;
}
}
else
{
printf("%c", p[i] );
}
}
return 0;
}
}
... not sure how to take into consideration if a keyword has less characters than the string entered.
Accessing keyword[j] beyond the end of keyword[] is bad. (Undefined behavior). This happens with OP's code when the key is shorter than the alpha part of the message.
Simply re-use the keyword[] string as needed. Hint: reset j.
Mouse over for answer.
int j_length = strlen(keyword);
...
j++;
if (j >= j_length) j = 0;

OR operation on binary strings in c giving half output as wrong

int stringXor(char *str1,char *str2)
{
int num1=0,num2=0;
for (int i = 0; i<strlen(str1); i++)
{
num1=str1[i]-'0';
num2=str2[i]-'0';
num1 = num1 | num2;
str1[i]=(char)num1;
//printf("%d",str1[i]);
}
int count=0;
for(int j=0;j<strlen(str1);j++)
{
if(str1[j]==1)
count++;
}
return count;
}
I don't know what the error is, but or operation is not successful on each char of the string.
If you want a function that will return the number of positions that contain a 1 in either string, consider writing a simpler function that does just that. For example:
int CountOnes( char *str1, char *str2 )
{
int count = 0;
int len = strlen( str1 ); // we assume that strlen(str1) == strlen(str2)
for ( int i = 0; i < len; i++ )
{
if ( str1[ i ] == '1' || str2[ i ] == '1' )
count++;
}
return count;
}
Note that this function will not include the side effect of changing str1 as yours currently does.
To store the resulting OR'd string to str1, change the line
if ( str1[ i ] == '1' || str2[ i ] == '1' )
to
str1[ i ] = ( ( str1[ i ] - '0' ) | ( str2[ i ] - '0' ) ) + '0';
if ( str1[ i ] == '1' )
count++;

Resources