Cancel the loop when the if condition is not true - c

I'm trying to write a program that does Run-Length-Encoding. I wrote the program but I want to cancel the entire loop when there is a non-alphabet character in input. I mean, it should give an output like "The input is not valid!".
I tried several if conditions but every time it encodes the alphabet characters till the non-alphabet character, and then skip that character and continue to encode. Where and how should I put the if statement?
int main() {
int i, txtLen=0, count;
char text[100];
printf("Please enter a text to RLE:\n");
scanf("%s", text);
while (text[i] != '\0') {
txtLen++;
i++;
}
for (i=0; i<txtLen; i++) {
printf("%c", text[i]);
count = 1;
while (text[i+1] == text[i]){
count++;
i++;
}
if (count != 1) {
printf("%d", count);
}
}
return 0;
}
When I tried to put if statements, the input and output were like that:
Input: aa?aaabbb
Output: a2a3b3
Please do not give any suggestions or comments for other parts of my code.

int main(void) {
int i, txtLen=0, count;
char text[100];
printf("Please enter a text to RLE:\n");
scanf("%s", text);
while (text[i] != '\0') {
// check if the value of each char if it is within the alphabetical range of char
if((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z')) {
printf("False Format\n");
break;
}
txtLen++;
i++;
}
for (i=0; i<txtLen; i++) {
printf("%c", text[i]);
count = 1;
while (text[i+1] == text[i]){
count++;
i++;
}
if (count != 1) {
printf("%d", count);
}
}
return 0;
}

Related

Substituting an input according to a key provided by the user. Now it compiles fine and does what it's supposed to do as well

It's supposed to do the following
Ask for input : Stack (e.g)
Ask for key : qwertyuioplkjhgfdsazxcvbnm (e.g)
Convert into cipher text : Azqel
Here's the new updated code:
//Encrypting user input by using 26 character long alphabetic key provided by user
#include <stdio.h>
#include <string.h>
int main(){
char key[26];
char text[1000];
//Prompt user for key
do{
printf("Provide a 26 character long key : ");
scanf("%s", key);
//If key is empty, exit code
if(strlen(key) == 0){
printf("Error: Empty input");
return 1;
}
//If key is incomplete, prompt user again for complete key
if(strlen(key)!= 26){
printf("Error: Incomplete key\n");
}
}while(strlen(key) != 26);
//If key has values other than alphabets, exit code
for(int i= 0, n= strlen(key); i<n; i++){
if((key[i]< 'a' || key[i]> 'z') && (key[i]< 'A' || key[i]> 'Z')){
printf("Error: Invalid key");
return 2;
}
}
//If key has repeated values, exit code
for(int i= 0; i< strlen(key); i++){
for(int j= i+ 1; key[j]!= '\0'; j++){
int x, y;
if(islower(key[i])){
x = key[i] - 'a';
}
else {
x = key[i] - 'A';
}
if(islower(key[j])){
y = key[j] - 'a';
}
else {
y = key[j] - 'A';
}
if(x == y){
printf("Error: Repeated characters in key");
return 3;
}
}
}
//Prompt user for input
printf("Plaintext : ");
scanf("%s", text);
//If input is empty, exit code
if(strlen(text) == 0){
printf("Error: Empty input");
return 4;
}
printf("Ciphertext: ");
for(int i= 0, n= strlen(text); i< n; i++){
//Encrypting small letters
if(text[i] >= 'a' && text[i] <= 'z'){
printf("%c", key[text[i]-'a']);
}
//Encrypting capital letters
else if(text[i] >= 'A' && text[i] <= 'Z'){
printf("%c", key[text[i]-'A']-('a'-'A'));
}
//Printing characters other than alphabets
else{
printf("%c", text[i]);
}
}
return 0;
}
The bug where code was treating lower case characters and upper case characters differently even if they were same has been fixed now.
If the key is for example : qwertyuioplkjhgfdsazxcvbmM (it has the letters 'm' and 'M' but they were being treated as different characters)
you can try this:
#include <stdio.h>
#include <string.h>
int main(){
char s[1000];
char t[26];
printf("Text: ");
scanf("%s", s);
printf("Key: ");
scanf("%s", t);
for(int i= 0, n= strlen(s); i< n; i++){
if(s[i] >= 'a' && s[i] <= 'z') printf("%c", t[s[i]-'a']);
else printf("%c", t[s[i]-'A'] + ('A'-'a'));
}
return 0;
}
and as said in the comments, try not to use numbers like 97 and 122, use 'a' and 'z' instead.
and for the bug mentioned in the updated code, instead of a simple check like key[j] == key[i] do this
int x, y;
if(islower(key[i])) x = key[i] - 'a';
else x = key[i] - 'A';
if(islower(key[j])) y = key[j] - 'a';
else y = key[j] - 'A';
if(x == y){
printf("Error: Repeated characters in key");
return 3;
}
or you can use a bool check[26], traverse the key, make the value of a character true if(islower(key[i])) check[key[i]-'a'] = true; else check[key[i]-'A'] = true; and lastly check whether the entire bool array is true.

Infinite loop in C counting spaces

I'm writing a program to count spaces and vowels and it didnĀ“t work, I think I did an infinite loop.I'll show you my code:
int contar_p(char a[100]) {
int i = 0, spaces = 1;
while (a[i] != '\0' && i < 100) {
if (a[i] == ' ') {
spaces += 1;
i++;
}
}
return spaces;
}
int contar_v(char b[100]) {
int i = 0, counter = 0;
while (b[i] != '\0' && i < 100) {
if (b[i] == 'a' || b[i] == 'e' || b[i] == 'i' || b[i] == 'o' || b[i] == 'u') {
counter += 1;
}
i++;
}
return counter;
}
int main(void){
char phrase[100];
int words = 0, vowels = 0;
printf("write a phrase ");
gets(phrase);
palabras = contar_p(phrase);
vocales = contar_v(phrase);
printf("%d\n", words);
printf("%d", vowels);
return 0;
}
The loop
while (a[i]!='\0'&&i<100){
if(a[i]==' '){
spaces+=1;
i++;
}
}
is an infinite loop. Place i++ outside the if. Change it to
while (a[i]!='\0'){ // No need of condition i < 100
if(a[i]==' '){
spaces+=1;
}
i++;
}
Maybe another approach will help you to understand things easier, i'm mean you do know that there are A,E,I,O,U also and not only a,e,i,o,u. You should never use gets instead use fgets, anyway take a look at the following program:
#include <stdlib.h>
#include <stdio.h>
void countVowels(char* array){
int i,j,v;
i=0;
int count = 0;
char vowel[]={'a','e','i','o','u','A','E','I','O','U'};
while(array[i]!='\0'){
for(v=0;v<10;v++){
if (array[i]==vowel[v]){
j=i;
while(array[j]!='\0'){
array[j]=array[j+1];
j++;
}
count++;
i--;
break;
}
}
i++;
}
printf("Found %d Vowels\n",count);
}
void contar_p(char a[100]) {
int i = 0, spaces = 0;
for(i=0;a[i]!='\0';i++){
if(a[i]==' ')
spaces++;
}
printf("Found %d Spaces\n",spaces);
}
int main(void){
char a[]="aa bb EOU cc ii";
countVowels(a);
contar_p(a);
return 0;
}
Output:
Found 7 Vowels
Found 4 Spaces

How to separate sentence into words in C using array

I am trying to write program, which take text and seperate it into sentences.
Input:
Hi, my name is John.
Output:
Hi,
my
name
is
John.
Code
int main ()
{
int str[200];
int i = 0;
puts ("Enter text. Do not forget to put dot at the end.");
do {
str[i] = getchar();
i++;
} while (str[i-1] != '.');
printf("\n");
int k, lenght = 0; //lenght -- the lenght of single word
for (i=0; str[i] != '.'; i++) {
if (str[i] == ' ' || str[i] == '.') {
printf ("\n");
k = i - lenght;
do {
putchar (str[k]);
k++;
} while (str[k] != ' ');
lenght = 0;
}
lenght++;
}
printf ("\n stop");
return 0;
}
If you try to run or if you can see, there is an error. It does not output last word.
I tried to put there this cycle:
do {
if (str[i] == ' ') {
printf("\n");
k=i-lenght;
do {
putchar(str[k]);
k++;
}while(str[k] != ' ');
lenght=0;
}
lenght++;
i++;
}while(str[i+1] != '.');
But its the same cycle... I also tried to make function:
void word (char *c,int index, int lenght ) {
printf ("\n");
int i = index - lenght;
do {
putchar (c[i]);
i++;
} while (c[i] != ' ');
return;
}
and I called it instead of do-while cycle (in the "if section " of the code):
for (i=0; str[i] != '.'; i++) {
if (str[i] == ' ' || str[i] == '.') {
word(str, i, lenght);
lenght = 0;
}
lenght++;
}
What surpriced me was, that the function was "outputting" only the firs Word in sentence. If the first word was "John" it output "John" "ohn" "hn".
So there is not just one question...
How to remake/repaire the cycle/function to output what I want - all of the words in the sentence?
Why it does not work? Well I know the answer - beacouse thy cycle is built to end on character ' ', but not the '.', but when I tried to change it, it output one more random character after dot.
Just please dont blame me for the code, I am just begginer trying to learn something. I know its not a Masterpiece and I can and I will make it shorter before I finish it.
The reason it doesn't print the last word is that, as soon as it reads it and finds the '.', the for-loop terminates so it doesn't process and output that word.
You could change the for-loop condition to look for the terminating '\0' instead, that should fix it.
#include<stdio.h>
int main ()
{
char str[200];
int i = 0;
puts ("Enter text:");
gets(str);
int k, length = 0;
printf("So the words are:\n");
while(str[i]!='\0')
{
if (str[i] == ' ') {
k = i - length;
do {
putchar (str[k]);
k++;
} while (str[k] != ' ');
printf ("\n");
length = (-1);
}
else if (str[i+1] == '\0') {
k = i - length;
do {
putchar (str[k]);
k++;
} while (str[k] != '\0');
length = 0;
}
length++;
i++;
}
return 0;
}

It's still crashing, where am I going wrong?

(Edited to add this bit) I'm writing a program where it reads in a string of characters, then counts the frequency of each letter in the string and outputs the number of times each letter or non-letter occurs.
I was using tolower() but this was creating a problem.
I've changed it so I'm now using a loop to lower the case. Unfortunately the program is still crashing on me and I can't spot the problem.
I've run through each function to make sure I don't have anything loose. I've got the new line element being removed but when I run it through, I type in something as simple as "hello" and it crashes out.
#include <stdio.h>
#include <string.h>
void read(char letterfreq[], int STRSIZE)
{
printf("The capacity of the string array is %d\n", STRSIZE-1);
printf("Please enter your string:\n");
letterfreq[strlen(letterfreq) - 1] = '\0';
return;
}
void lowerCase(char letterfreq[], int STRSIZE)
{
}
}
void countFreq(int counter[], int COUNT, char letterfreq[], int STRSIZE)
{
int c = 0;
int i;
for(i = 0; i < STRSIZE; i++)
}
else
if((letterfreq[i] < 'a') || (letterfreq[i] > 'z'))
{
counter[COUNT-1]++;
}
}
}
return;
}
void printFreq(int counter[], int COUNT)
{
int c;
printf("Here is the letter frequency of your string:\n");
for(c = 0; c < COUNT; c++)
printf("There were also %d special characters in the string.\n", counter[26]);
return;
}
char promptReset(char reset)
{
printf("Would you like to calculate the letter frequency of another string? (Y/N)\n");
scanf("%c%*c", &reset);
do
{
readString(letterfreq, STRSIZE);
lowerCase(letterfreq, STRSIZE);
countFreq(counter, COUNT, letterfreq, STRSIZE);
printFreq(counter, COUNT);
reset = promptReset(reset);
}while(reset == 'y' || 'Y');
return(0);
}
Here(in function lowerCase):
letterfreq[i] = letterfreq[i] - 32;
you need to add 32 to convert the character into uppercase. Look at the ASCII table to know why.
Here(in function countFreq):
for(i = 0; i < STRSIZE; i++)
{
while(letterfreq[i] != '\0')
{
if(letterfreq[i] >= 'a' && letterfreq[i] <= 'z')
{
counter[c]++;
c++;
}
else
if((letterfreq[i] < 'a') || (letterfreq[i] > 'z'))
{
counter[COUNT-1]++;
}
}
}
the for loop doesn't make any sense. Remove it. Then, the while loop never ends as you don't increment i. You need i++; at the end of the while loop.
Here:
if(letterfreq[i] >= 'a' && letterfreq[i] <= 'z')
{
counter[c]++;
c++;
}
counter[c]++ won't count the frequency of each character. You need
counter[letterfreq[i]-'a']++;
for that. c is not needed. Remove it from the function.
Also, as #iharob has mentioned in a comment,
}while(reset == 'y' || 'Y');
should be
}while(reset == 'y' || reset == 'Y');
Fixed program:
#include <stdio.h>
#include <string.h>
const int COUNT = 27;
const int STRSIZE = 100;
void readString(char letterfreq[], int STRSIZE)
{
printf("The capacity of the string array is %d\n", STRSIZE-1);
printf("Please enter your string:\n");
fgets(letterfreq, STRSIZE, stdin);
letterfreq[strlen(letterfreq) - 1] = '\0';
//return; Not required
}
void lowerCase(char letterfreq[], int STRSIZE)
{
int i;
for(i = 0; i < STRSIZE; i++)
{
if(letterfreq[i] >= 'A' && letterfreq[i] <= 'Z')
{
letterfreq[i] = letterfreq[i] + 32; //Add instead of subtract
}
//i++; You already increment i from the loop
}
}
void countFreq(int counter[], int COUNT, char letterfreq[], int STRSIZE)
{
int i=0; // You forgot to initialize i with 0
while(letterfreq[i] != '\0')
{
if(letterfreq[i] >= 'a' && letterfreq[i] <= 'z')
{
counter[letterfreq[i]-'a']++;
}
else if((letterfreq[i] < 'a') || (letterfreq[i] > 'z')) //is always true; Use `else`
{
counter[COUNT-1]++;
}
i++; //You forgot this
}
//return; Not required
}
void printFreq(int counter[], int COUNT)
{
int c;
printf("Here is the letter frequency of your string:\n");
for(c = 0; c < COUNT-1; c++) //See change here too
{
printf("%c \t %d \n", c + 'a', counter[c]);
}
printf("There were also %d special characters in the string.\n", counter[26]);
//return; Not required
}
char promptReset(char reset)
{
printf("Would you like to calculate the letter frequency of another string? (Y/N)\n");
scanf("%c%*c", &reset);
return(reset);
}
int main()
{
char letterfreq[STRSIZE];
char reset = '\0'; //Always initialize variables to prevent unexpected behavior
int counter[COUNT];
printf("Welcome to the Letter Frequency program\n");
do
{
memset(counter,0,sizeof(counter)); //Initializing counter with zeros
memset(letterfreq,'\0',sizeof(letterfreq)); //Do the same for letterfreq
readString(letterfreq, STRSIZE);
lowerCase(letterfreq, STRSIZE);
countFreq(counter, COUNT, letterfreq, STRSIZE);
printFreq(counter, COUNT);
reset = promptReset(reset);
}while(reset == 'y' || reset == 'Y'); //Changed
return(0);
}

How can I implement my anagram and palindrome functions to check the words input by a user?

I got some help earlier fixing up one of the functions I am using in this program, but now I'm at a loss of logic.
I have three purposes and two functions in this program. The first purpose is to print a sentence that the user inputs backwards. The second purpose is to check if any of the words are anagrams with another in the sentence. The third purpose is to check if any one word is a palindrome.
I successfully completed the first purpose. I can print sentences backwards. But now I am unsure of how I should implement my functions to check whether or not any words are anagrams or palindromes.
Here's the code;
/*
* Ch8pp14.c
*
* Created on: Oct 12, 2013
* Author: RivalDog
* Purpose: Reverse a sentence, check for anagrams and palindromes
*/
#include <stdio.h>
#include <ctype.h> //Included ctype for tolower / toupper functions
#define bool int
#define true 1
#define false 0
//Write boolean function that will check if a word is an anagram
bool check_anagram(char a[], char b[])
{
int first[26] = {0}, second[26] = {0}, c = 0;
// Convert arrays into all lower case letters
while(a[c])
{
a[c] = (tolower(a[c]));
c++;
}
c = 0;
while(b[c])
{
b[c] = (tolower(b[c]));
c++;
}
c = 0;
while (a[c] != 0)
{
first[a[c]-'a']++;
c++;
}
c = 0;
while (b[c] != 0)
{
second[b[c]-'a']++;
c++;
}
for (c = 0; c < 26; c++)
{
if (first[c] != second[c])
return false;
}
return true;
}
//Write boolean function that will check if a word is a palindrome
bool palindrome(char a[])
{
int c=0, j, k;
//Convert array into all lower case letters
while (a[c])
{
a[c] = (tolower(a[c]));
c++;
}
c = 0;
j = 0;
k = strlen(a) - 1;
while (j < k)
{
if(a[j++] != a[k--])
return false;
}
return true;
}
int main(void)
{
int i = 0, j = 0, k = 0;
char a[80], terminator;
//Prompt user to enter sentence, store it into an array
printf("Enter a sentence: ");
j = getchar();
while (i < 80)
{
a[i] = j;
++i;
j = getchar();
if (j == '!' || j == '.' || j == '?')
{
terminator = j;
break;
}
else if(j == '\n')
{
break;
}
}
while(a[k])
{
a[k] = (tolower(a[k]));
k++;
}
k = 0;
while(k < i)
{
printf("%c", a[k]);
k++;
}
printf("%c\n", terminator);
//Search backwards through the loop for the start of the last word
//print the word, and then repeat that process for the rest of the words
for(j = i; j >= 0; j--)
{
while(j > -1)
{
if (j == 0)
{
for(k=j;k<i;k++)
{
printf("%c", a[k]);
}
printf("%c", terminator);
break;
}
else if (a[j] != ' ')
--j;
else if (a[j] == ' ')
{
for(k=j+1;k<i;k++)
{
printf("%c", a[k]);
}
printf(" ");
break;
}
}
i = j;
}
//Check if the words are anagrams using previously written function
for( i = 0; i < 80; i++)
{
if (a[i] == ' ')
{
}
}
//Check if the words are palindromes using previously written function
return 0;
}
I was thinking that perhaps I could again search through the array for the words by checking if the element is a space, and if it is, store from where the search started to the space's index-1 in a new array, repeat that process for the entire sentence, and then call my functions on all of the arrays. The issue I am seeing is that I can't really predict how many words a user will input in a sentence... So how can I set up my code to where I can check for anagrams/palindromes?
Thank you everyone!
~RivalDog
Would be better,if you first optimize your code and make it readable by adding comments.Then you can divide the problem in smaller parts like
1.How to count words in a string?
2.How to check whether two words are anagrams?
3.How to check whether a word is palindrome or not?
And these smaller programs you could easily get by Googling. Then your job will be just to integrate these answers. Hope this helps.
To check anagram, no need to calculate number of words and comparing them one by one or whatever you are thinking.
Look at this code. In this code function read_word() is reading word/phrase input using an int array of 26 elements to keep track of how many times each letter has been seen instead of storing the letters itself. Another function equal_array() is to check whether both array a and b (in main) are equal (anagram) or not and return a Boolean value as a result.
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
void read_word(int counts[26]);
bool equal_array(int counts1[26],int counts2[26]);
int main()
{
int a[26] = {0}, b[26] = {0};
printf("Enter first word/phrase: ");
read_word(a);
printf("Enter second word/phrase: ");
read_word(b);
bool flag = equal_array(a,b);
printf("The words/phrase are ");
if(flag)
printf("anagrams");
else
printf("not anagrams");
return 0;
}
void read_word(int counts[26])
{
int ch;
while((ch = getchar()) != '\n')
if(ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z')
counts[toupper(ch) - 'A']++;
}
bool equal_array(int counts1[26],int counts2[26])
{
int i = 0;
while(i < 26)
{
if(counts1[i] == counts2[i])
i++;
else
break;
}
return i == 26 ? true : false;
}

Resources