A program that displays the characters which appeared least/most often - c

I've just written the code which is supposed to display the most/least (depending on a switch choice) appearing character. It has to work with standard input, that is from keyboard as well as with a text file. It's crucial for this program to show all char that appeared most often. For example in the input "abbcc" it should display b and c.
It runs, but it doesn't show characters. The question is: why?
Here's the code:
a) main
int main (int argc, char *argv[]) {
int string;
int allChars[256] = {0};
while ( (string=getchar())!=EOF )
allChars[string]++;
if (argc < 2)
mostOften(allChars);
else {
switch (argv[1][1]) {
case 'm': case 'M':
mostOften(allChars);
break;
case 'l': case 'L':
leastOften(allChars);
break;
default:
mostOften(allChars);
break;
} //switch
} // else
} // main
b) sf.c
void mostOften(int *s) {
int i, j;
int max[256] = {0} ;
int max_count = 1;
for (i=0; i<256; i++) {
if (s[i]) {
if (s[i] > max_count) {
for (j=0; j<256; j++)
max[j]=0;
max[i]=1;
max_count = s[i];
} // 2nd_if
else if (s[i] == max_count)
max[i]=1;
else
continue;
} // 1st_if
} //1st_for
printf("The most appearing characters are: ");
for (i=0; i<256; i++) {
if (max[i])
putchar(s[i]);
} //2nd_for
}
void leastOften(int *s) {
int i, j;
int min[256] = {0} ;
int min_count = 1000;
for (i=0; i<256; i++) {
if (s[i]) {
if (s[i] < min_count) {
for (j=0; j<256; j++)
min[j]=0;
min[i]=1;
min_count = s[i];
} // 2nd_if
else if (s[i] == min_count)
min[i]=1;
} // 1st_if
} //1st_for
printf("The least appearing characters are: ");
for (i=0; i<256; i++) {
if (min[i])
putchar(s[i]);
} //2nd_for
}
Thank you.
EDIT1: deleted the mistake in the description
EDIT2: changed from putchar(min[i]), putchar(max[i]) to putchar(s[i])

In your code for mostOften, i is the index to s, an that is the character itelf. So when you print out the list of characters that occur most often, you should print the character i instead of max[i]:
for (i = 0; i < 256; i++) {
if (max[i]) putchar(i);
}
Another approach that doesn't require zeroing out the whole array is to make a contiguous list of characters. The length of the list is variable and kept in a separate variable, nmax. When you find a new maximum, just set the length of the array to zero. Don't worry about the array contents; max is only guaranteed to have sensible data up to nmax:
void mostOften(int *s)
{
int max[256]; // list of characters
int nmax = 0; // actual length of max array
int max_count = 0;
int i;
for (i = 0; i < 256; i++) {
if (s[i] && s[i] >= max_count) {
if (s[i] > max_count) nmax = 0;
max[nmax++] = i;
max_count = s[i];
}
}
for (i = 0; i < nmax; i++) printf("'%c'\n", max[i]);
}

change
printf("The most appearing characters are: ");
for (i=0; i<256; i++) {
if (max[i])
putchar(s[i]);
} //2nd_for
to
printf("The most appearing characters are: ");
for (i=0; i<256; i++) {
if (max[i])
putchar(i);
} //2nd_for
since you generated s[i] as s[<char-value>] = <num-occurances-of-value>.

Related

Numbers in char array printing as random characters

So I'm writing a somewhat simple C program that is supposed to take a string of characters separated by semicolons as input. The program is then supposed to sort the strings by length and print them to the console.
Ex: abc;12;def;1234
The issue I'm having is that any numbers that are entered end up being printed as random symbols and I'm not sure why. I'm taking in input in this function:
void get_strings(char** c)
{
while (scanf("%[^;]s", c[numStrings]) != EOF)
{
getchar();
numStrings += 1;
}
}
Since scanf is looking for strings, if numbers are entered, are they stored as the 'character form' of those numbers, or should I be casting somehow?
Here's the rest of the code:
int numStrings = 0;
void sort_strings(char** c)
{
for (int i = 0; i < numStrings; i++)
{
for (int j = 0; j < numStrings - i; j++)
{
if (strlen(c[j]) > strlen(c[j + 1]))
{
char temp[1000];
strcpy(c[j], temp);
strcpy(c[j + 1], c[j]);
strcpy(temp, c[j + 1]);
}
}
}
}
void show_strings(char** c)
{
for (int i = 0; i < numStrings; i++)
{
if (printf("%s\n", c[i]) != EOF) break;
}
}
int main()
{
char wordLen[100][1000];
char* word2[100];
for (int i = 0; i < 100; i++)
{
word2[i] = wordLen[i];
}
char** words = word2;
get_strings(words);
sort_strings(words);
show_strings(words);
return 0;
}
The parsing code is incorrect:
void get_strings(char **c) {
while (scanf("%[^;]s", c[numStrings]) != EOF) {
getchar();
numStrings += 1;
}
}
the scanf() format contains an extra s that does not match the input.
the return value of scanf() should be compared to 1 to ensure successful conversion. Conversion failure produces EOF only at end of file, otherwise it produces 0 and the contents of c[numStrings] will be indeterminate.
conversion stops at the first character ;, this character stays in the input stream, but it is read by getchar(), yet if there is an empty field, the corresponding conversion would fail and the contents of the array would be indeterminate.
you should not use a global variable for the number of strings read. You should instead return this number.
The sorting code is incorrect too:
the inner loop runs one index too far: j + 1 must be less than numStrings for all runs.
the arguments to strcpy are passed in the wrong order.
strcpy should not be used at all, you should just swap the pointers.
show_strings() always stops after the first line as printf will return the number of characters printed.
You can fix the reading loop this way:
#include <stdio.h>
#include <string.h>
int get_strings(char **c, int maxStrings) {
int numStrings = 0;
while (numStrings < maxStrings) {
switch (scanf("%999[^;]", c[numStrings])) {
case 1:
getchar();
numStrings += 1;
break;
case 0:
if (getchar() == ';') {
c[numStrings] = '\0';
numStrings += 1;
}
break;
case EOF:
return numStrings;
}
}
}
void sort_strings(char **c, int count) {
for (int i = 0; i < count; i++) {
for (int j = 0; j < count - i - 1; j++) {
if (strlen(c[j]) > strlen(c[j + 1])) {
char *temp = c[j];
c[j] = c[j + 1];
c[j + 1] = temp;
}
}
}
}
void show_strings(char **c, int count) {
for (int i = 0; i < count; i++) {
printf("%s\n", c[i]);
}
}
int main(void) {
char words[1000][100];
char *wordPtrs[100];
int numStrings;
for (int i = 0; i < 100; i++) {
wordPtrs[i] = words[i];
}
numStrings = get_strings(wordPtrs, 100);
sort_strings(wordPtrs, numStrings);
show_strings(wordPtrs, numStrings);
return 0;
}

trying to use strcmp in if function for counting anagrams in a sentence

hii guys i need a serious help
i m trying to write a code for finding anagrams in input sentence
but when the if function is getting strcmp it stops and its not accepting the condition. any body know why is that happening
Basically my code supposed to do two things one is taking a sentence from the user and making the words appear in the Backwoods order two Its need to take the whole sentence and look for anagrams ( anagram means that there is the same letters but in a different order for example this and shit are anagrams) thank you very much for your help :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
int index_for_word_start, words_num = 1,amount_of_letters;
int i, j, k;
char inpot_Sentence[1001], temp_letters;
char **words,**sorting_words;
int counter = 0,counter_max_for_anegram=0;
printf_s("Please enter the sentence, and then press Enter:\n");
gets(inpot_Sentence);
/////////////////////////////makeing the sentence backwards///////////////////////
for (i = 0; inpot_Sentence[i] != '\0'; i++) //loop for counting how many words(it will be use to know how many pointer we need)
{
if (inpot_Sentence[i] == ' ')
{
words_num++;
}
}
words = (char **)malloc(sizeof(char *)*words_num); //malloc for pointers that point on the pointer of the word
index_for_word_start = 0;
for (j = 0; j<words_num; j++)
{
for (i = index_for_word_start; inpot_Sentence[i] != ' '; i++)
{
if (!inpot_Sentence[i]) //if the user didnt put any word(break)
{
break;
}
}
words[j] = (char*)malloc(sizeof(char)*(i - index_for_word_start + 1)); //malloc of pointers that point on each word
strncpy_s(words[j], i - index_for_word_start+1, &inpot_Sentence[index_for_word_start], i - index_for_word_start); //copy the words from inpot sentence to array
words[j][i - index_for_word_start] = 0; //puts '\0' after the word copy ends
index_for_word_start = i + 1;
}
printf_s("\nThe reverse sentence is:\n");
for (i = words_num - 1; i >= 0; i--) //print the words in backwards Sequence
{
printf("%s ", words[i]);
}
putchar('\n');
i = 0;
/////////////////////anegrams check///////////////////////
for (j = 0; j < words_num; j++) //loops that Arrange the array by haski value
{
amount_of_letters = strlen(words[j]);
for ( i = 0; i < amount_of_letters; i++)
{
for (k = 0; k < amount_of_letters; k++)
{
if (words[j][i]<words[j][k])
{
temp_letters = words[j][i];
words[j][i] = words[j][k];
words[j][k] = temp_letters;
}
}
}
printf_s("this is words %s\n", words[j]);
}i = 0;
for ( j = 0; j < words_num-1; j++)
{
for ( i = 0; i < words_num-1; i++)
{
if (!strcmp(words[j],words[i]) && (i!=j) && (strcmp(words[j],"\0")))
{
counter++;
words[i] = 0;
}
else
{
break;
}
}
if (counter>counter_max_for_anegram)
{
counter_max_for_anegram = counter;
}
counter = 0;
}
printf_s("%d\n", counter_max_for_anegram);
for ( j = 0; j < words_num; j++)
{
free(words[j]);
}
free(words);
}
#include <stdio.h>
#include <string.h>
int check_anagram(char[],char[]);
int main()
{
char a[100],b[100];
int flag;
puts("Enter the first string");
fgets(a,100,stdin);
a[strcspn(a, "\r\n")] = '\0';
puts("Enter the second string");
fgets(b,100,stdin);
b[strcspn(b, "\r\n")] = '\0';
flag=check_anagram(a,b);
if(flag)
printf("%s and %s are anagrams",a,b);
else
printf("%s and %s are not anagrams",a,b);
}
int check_anagram(char a[], char b[])
{
int first[26]={0},second[26]={0},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 0;
}
return 1;
}

Trying to search the index of the certain pattern through a string, but looks like -1 always be the output #c

It is a program about user input text and pattern. And use a function to return the value of index of the pattern. If pattern cannot be found, return -1;For some reason I keep getting -1 for return value;
Here is my code:
#include<stdio.h>
#include<string.h>
int contains(const char *text,const char *pattern){
int lengthT,lengthP,i;
int j = 0;
for(i = 0; i < 10; i++){//get the length of pattern
if(pattern[i] == '\0'){
lengthP = i;
break;
}
}
for(i = 0;i < 100; i++){//get the length of text
if(text[i] == '\0'){
lengthT = i;
break;
}
}
for(i = 0;i < lengthT;i++){
if(text[i] == pattern[0]){
for(j = 1;j <= lengthP + 1;j++){
if(text[i+j] == pattern[j]){
if(j >= lengthP){
return i;
}
continue;
}
}
}
return -1;
}
}
int main(){
const char text[100];
const char pattern[10];
printf("Enter the text: ");
scanf("%s",&text);
printf("Enter the pattern: ");
scanf("%s",&pattern);
printf("Pattern %s occurs in %s at the location %d.\n",pattern,text,contains(text,pattern));
return 0;
}
You have placed the return -1; at wrong position. It should be placed outside the for loop iterating across the text otherwise the function will directly return -1 if the first letter of text and pattern are not same.
Also, after correcting return statement, I found out that your logic was somewhat wrong.Here is code that is correct according to me.
#include<stdio.h>
#include<string.h>
int contains(const char *text,const char *pattern){
int lengthT,lengthP,i;
int j = 0;
lengthP = strlen(pattern);
lengthT = strlen(text);
for(i = 0;i < lengthT;i++){
if(text[i] == pattern[0]){
printf(" f1");
for(j = 1;j <lengthP;j++){
if(text[i+j] == pattern[j]){
if(pattern[j+1]== '\0'){
return i;
}
continue;
}
}
}
}
return -1;
}
int main(){
const char text[100];
const char pattern[10];
printf("Enter the text: ");
scanf("%s",&text);
printf("Enter the pattern: ");
scanf("%s",&pattern);
printf("Pattern %s occurs in %s at the location %d.\n",pattern,text,contains(text,pattern));
return 0;
}

obtaining ASCII values of input chars in c

I was intending to create a simple function that would take a string as its input and output the equivalent of that string in ASCII. Plz help..
void cls(){
system("cls");
}
void getAscii(){
cls();
text(4);
char a[94]={' ','!','"','#','$','%','&',"'",'(',')','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','#',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[',"'\'",']','^','_','`','a','b',
'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','{','|','}','~'};
while(1){
char x[5000], *exitMsg = "quit";
gets(x);
if(strcmp(x, exitMsg) == 0){
break;
}else{
int i = 0;
for(i = 0; i < strlen(x); i++){
int j = 0;
for(j = 0; j < 94; j++){
if(x[i] == a[j]){
int xa = (a[j] + 32);
printf("%d", &xa);
}
}
}
printf("\n");
}
}
}
A char is just an one byte number. When it represents an ascii character it is actually just the number for it. For example when you say char x = 'A', you are essentially saying char x = 65. The one byte in memory representing x really stores the number 65. If you did x+1 you would get 66 or 'B' depending on how you print it. When you tell it to print a char it will look up the ascii table and print the character. If you tell it to print a decimal it will print 65. For example:
char x = 'A';
printf("%d", x);
This will print 65. You do not need a conversion table to look up the ascii values.
No need for ascii arrays and another loop inside your code.
This
for(i = 0; i < strlen(x); i++){
int j = 0;
for(j = 0; j < 94; j++){
if(x[i] == a[j]){
int xa = (a[j] + 32);
printf("%d", &xa);
}
}
}
can be simplified to
for(i = 0; i < strlen(x); i++) {
printf("%d", x[i]);
}
There are a few errors in your code :
You have used "" a few times instead of ''. Correct this.For special situations use the escape sequence i.e, for writing the \ character use '\\' or for ' character use '\''.
The total number of elements are 95 not 94.
Remove &xa from printf and use xa.
No Need of adding 32 to xa.
The corrected code is:
#include<stdio.h>
#include<process.h>
#include<string.h>
void cls(){
system("cls");
}
void Ascii(){
cls();
// text(4); //uncomment this if it does something useful
char a[95]={' ','!','"','#','$','%','&',' ','(',')','*','+',',','-','.','/','0','1','2','3','4','5','6','7','8','9',':',';','<','=','>','?','#',
'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[','\\',']','^','_','`','a','b',
'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','{','|','}','~'};
while(1){
char x[5000], *exitMsg = "quit";
gets(x);
if(strcmp(x, exitMsg) == 0){
break;
}else{
int i = 0;
for(i = 0; i < strlen(x); i++){
int j = 0;
for(j = 0; j < 94; j++){
if(x[i] == a[j]){
int xa = (a[j] );
printf("%d ", xa);
}
}
}
printf("\n");
}
}
}
ALTHOUGH You require none of this.
Try this:
void cls(){
system("cls");
}
void Ascii(){
cls();
while(1){
char x[5000], *exitMsg = "quit";
gets(x);
if(strcmp(x, exitMsg) == 0){
break;
}else{
int i = 0;
for(i = 0; i < strlen(x); i++){
int xa = (x[i] );
printf("%d ", xa);
}
}
printf("\n");
}
}

Anagram Solver, array[26] not working correctly

I've nearly finished my anagram solver program where I input two strings and get the result of whether they are anagrams of each other. For this example i'm using 'Payment received' and 'Every cent paid me'.
The problem i'm getting is when I output the letterCount arrays, letterCount1 is incorrect (it doesn't think there is a character 'd' but there is.) but letterCount2 is correct.
Can anyone see a problem with this because i'm completely baffled?
#include <stdio.h>
#include <string.h>
int checkAnagram(char string1[], char string2[])
{
int i;
int count = 0, count2 = 0;
int letterCount1[26] = {0};
int letterCount2[26] = {0};
for(i = 0; i < strlen(string1); i++)
{
if(!isspace(string1[i]))
{
string1[i] = tolower(string1[i]);
count++;
}
}
for(i = 0; i < strlen(string2); i++)
{
if(!isspace(string2[i]))
{
string2[i] = tolower(string2[i]);
count2++;
}
}
if(count == count2)
{
for(i = 0; i < count; i++)
{
if(string1[i] >='a' && string1[i] <= 'z')
{
letterCount1[string1[i] - 'a'] ++;
}
if(string2[i] >='a' && string2[i] <= 'z')
{
letterCount2[string2[i] - 'a'] ++;
}
}
printf("%s\n", string1);
for(i = 0; i < 26; i++)
{
printf("%d ", letterCount1[i]);
printf("%d ", letterCount2[i]);
}
}
}
main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
if(checkAnagram(string1, string2) == 1)
{
printf("%s", "Yes");
} else
{
printf("%s", "No");
}
}
That's because your count holds the count of non-space characters, but you keep the strings with the spaces.
For example, the string "hello world" has 11 characters, but if you run it through the loops your count will be 10 (you don't count the space). However, when you later go over the strings and count the appearance of each letter, you will go over the first 10 characters, therefore completely ignoring the last character - a 'd'.
To fix it, you need to go over all characters of the string, and only count the alphanumeric ones.
I fixed it for you:
#include <stdio.h>
#include <string.h>
int checkAnagram(char string1[], char string2[])
{
int i;
int count = 0, count2 = 0;
int letterCount1[26] = {0};
int letterCount2[26] = {0};
int len1 = strlen(string1);
int len2 = strlen(string2);
for(i = 0; i < len1; i++)
{
if(!isspace(string1[i]))
{
string1[i] = tolower(string1[i]);
count++;
}
}
for(i = 0; i < len2; i++)
{
if(!isspace(string2[i]))
{
string2[i] = tolower(string2[i]);
count2++;
}
}
if(count == count2)
{
for (i=0; i<len1; i++)
if (!isspace(string1[i]))
letterCount1[string1[i]-'a']++;
for (i=0; i<len2; i++)
if (!isspace(string2[i]))
letterCount2[string2[i]-'a']++;
int flag = 1;
for(i = 0; flag && i < 26; i++)
if (letterCount1[i] != letterCount2[i])
flag = 0;
return flag;
}
return 0;
}
main()
{
char string1[100];
char string2[100];
gets(string1);
gets(string2);
if(checkAnagram(string1, string2) == 1)
{
printf("%s", "Yes");
} else
{
printf("%s", "No");
}
}
First, don't calculate an string's length inside a loop. I extracted them into len1 and len2 variables.
Second, your loop was wrong! You shouldn't go up to count, you should go up to that string's length.
Third, you didn't return anything from checkAnagram function.

Resources