A program to remove common alphabets from character array - c

void main()
{
int i, j, k,flag=1;
char key[10], keyword[10];
gets(key);
i=0;
j=0;
while(key[i]!='\0') {
k=0;
while(keyword[k]!='\0') {
if(key[i]==keyword[k]) {
i++;
flag=0;
break;
}
k++;
}
if(flag==1) {
keyword[j]=key[i];
j++;
i++;
}
flag=1;
}
}
Here I tried to copy unique alphabets from array to another array ..means duplicate alphabet should not copied in another array..it shows right output but along with that it shows some garbage values like smiley or something till the length of original input array(i.e.key[])

You need to add a terminator to the unique character string both at the time it is initialized, and every time a new letter is added:
#include <stdio.h>
int main() {
int i = 0, j = 0;
char redundant[10], unique[10] = { '\0' };
gets(redundant);
while (redundant[i] != '\0') {
int k = 0, flag = 1;
while (unique[k] != '\0') {
if (redundant[i] == unique[k]) {
flag = 0;
break;
}
k++;
}
if (flag) {
unique[j++] = redundant[i];
unique[j] = '\0';
}
i++;
}
printf("%s -> %s\n", redundant, unique);
return(0);
}
OUTPUT
% ./a.out
warning: this program uses gets(), which is unsafe.
aardvark
aardvark -> ardvk
%
Now let's consider a different approach that wastes some space to simplify and speed up the code:
#include <stdio.h>
#include <string.h>
int main() {
unsigned char seen[1 << (sizeof(char) * 8)] = { 0 }; // a flag for every ASCII character
char redundant[32], unique[32];
(void) fgets(redundant, sizeof(redundant), stdin); // gets() is unsafe
redundant[strlen(redundant) - 1] = '\0'; // toss trailing newline due to fgets()
int k = 0; // unique character counter
for (int i = 0; redundant[i] != '\0'; i++) {
if (!seen[(size_t) redundant[i]]) {
unique[k++] = redundant[i];
seen[(size_t) redundant[i]] = 1; // mark this character as seen
}
}
unique[k] = '\0'; // terminate the new unique string properly
printf("%s -> %s\n", redundant, unique);
return 0;
}
Instead of a second, inner loop to search if a letter has been copied already, we use an array of flags (boolean), where the letter is the index, to determine if the letter has been processed.
Another thing you might want to think about is whether to treat upper and lower case differently or fold them into one.

Related

How can I fix my program to not crash if I run any character that is not alphabetical?

So I am trying to write code that will allow me to count the number of letters a user has entered.
My code runs well if I simply type one word.
The moment that I include any character that is not a letter, my terminal stops working.
What can I do to fix it?
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
int count_letters(string text);
int main(void)
{
string text = get_string("text? ");
int letters = count_letters(text);
printf("%i letters\n", letters);
}
int count_letters(string text)
{
int i = 0;
do
{
if (isalpha(text[i]))
{
i++;
}
else if (isspace(text[i]))
{
i = + 0;
}
else
{
i = +0;
}
} while (text[i] != 0);
return i;
}
i is the do ... while counter, do not use it to count the number of letters, use another variable, something like:
int count_letters(string text)
{
int i = 0, letters = 0;
do
{
if (isalpha((unsigned char)text[i]))
{
letters++;
}
i++;
}
while (text[i] != 0);
return letters;
}
Notice that with your approach the loop is also testing the NUL terminator in an empty string, use a while loop instead to exit the loop as soon as the NUL is found:
int count_letters(string text)
{
int letters = 0;
while (*text)
{
if (isalpha((unsigned char)*text))
{
letters++;
}
text++;
}
return letters;
}
Consider what happens in your loop: i only increments when the character at text[i] is an alphabetic character. Otherwise it resets to zero.
Thus, the loop will never complete for a string that is not entirely alphabetic characters because the loop will "reset" to the beginning with ever non-alphabetic character.
We can increment an index from zero until the character at that index in the string is the null-terminator of zero (which is false in C).
int count_letters(string text) {
int count = 0;
for (int i = 0; text[i]; i++) {
if (isalpha(text[i])) count++;
}
return count;
}
We can however, use pointers to iterate over your string, taking advantage of the detection of the null terminator to terminate the loop. If each character is an alphabetic character, increment a counter. A for loop can handle giving you a temp pointer and initializing it, testing for termination of the loop and incrementing the pointer.
int count_letters(string text) {
int count = 0;
for (char *ch = text; *ch; ch++) {
if (isalpha(*ch)) count++;
}
return count;
}
As text is a pointer passed by value (being hidden by CS50's string typedef), it can be modified without affecting the original string as long as we don't dereference and modify the individual characters, so we can avoid the extra char pointer.
int count_letters(string text) {
int count = 0;
for (; *text; text++) {
if (isalpha(*text)) count++;
}
return count;
}
As pointed out in the comment, i cannot serve two purposes (index and counter) except for the special case of a string comprised of only letters.
Below is a compact function that counts 'hits' when isalpha() has returned a non-zero value (indicating the current letter is in the range "A-Za-z").
The unusual "!!" transforms the non-zero positive value into C's true (or false) having values of 1 (or 0) respectively. Thusly, the value of 1 or 0 is appropriately added to the accumulator to be returned to the caller.
int count_letters( string text ) {
int i = 0, cnt = 0;
if( text != NULL ) // trust is good, testing is better
while( text[i] )
cnt += !!isalpha( (unsigned char)text[i++] );
return cnt;
}
EDIT and Credit: #Aconcagua for pointing out the need for casting each char to unsigned char to avoid UB.

There's a space when I strcpy a string into another string

I have a kind of logical assignment here in my class. So my question is when I try to strcpy() a string into another string, There's a (like space) in my new string. I don't know how to delete that, perhaps my mistake. Please help me, thank you.
This program let's you type whatever letters or symbol on your keyboard and try to capture it and count the symbol. Then, return it.
Here's my code in C
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#define N 25
typedef char string[N];
int main(int argc, char *argv[])
{
int i,j;
int jumlah[10];
string inputan;
string temp;
int counter;
//Init
for(i=0;i<10;i++) {
jumlah[i]=0;
}
for(i=0;i<10;i++) {
temp[i]='-';
}
for(i=0;i<10;i++) {
inputan[i]='-';
}
do {
system("cls");
printf("\nMasukan kalimat: ");fflush(stdin);gets(inputan);
if(strcmpi(inputan,"0")!=0) {
strcpy(temp,inputan);
}
getch();
}while(strcmpi(inputan,"0")!=0);
printf("Hasil Analisa:\n\n");
for(i=0;i<10;i++) {
if(temp[i]!='-') {
char c = temp[i];
for(j=0;j<10;j++) {
if(temp[j]!='-') {
if(c == temp[j])
counter+=1;
}
}
jumlah[i] = counter;
counter = 0;
}
}
for(i=0;i<10;i++) {
if(temp[i]!=' ' && temp[i]!='-' && temp) {
printf("\t%c terdapat %d\n",temp[i],jumlah[i]);
}
}
getch();
}
And here's my console result:
So that's make the program will show the space symbol and count it.
And if I can ask again, how to display only one char if there's a symbol again in another index that have same symbol. Thx, forgive me if my English is not fluent.
The space(s) showing up at the end of your printout are because the list of test conditions you include:
if(temp[i]!=' ' && temp[i]!='-' && temp)
May be missing some additional conditions that need to be excluded:
1) added additional test: test[i] != 0
2) changed temp[i] != ' ' to !isspace(temp[i]), which will test against all white space.
Once these are added:
if(!isspace(temp[i]) && temp[i]!='-' && temp && (temp[i] != 0))
The text entered is printed only down to the last non-whitespace character.
Code modifications:
I added some other minor modifications to the following code that allowed the code to be compiled in my environment. Because my modifications use functions that are part of the C standard libraries, this should compile for you as well.
Changes also include expanding for(...) loops to accommodate the array sizes you created, enabling input up to N-1 characters as opposed to only 10. Most of what I did includes commented explanations.
int main(int argc, char *argv[])
{
int i,j;
//int jumlah[10];
int jumlah[N]; // probably meant to use N here?
string inputan = {0};
string temp = {0};
int counter = 0;// initialize
for(i=0;i<N;i++) {
jumlah[i]=0;
}
for(i=0;i<N-1;i++) {
temp[i]='-';
}
for(i=0;i<N-1;i++) {
inputan[i]='-';
}
do {
//system("cls"); This is fine, just does not work in my environment, so commented.
//printf("\nMasukan kalimat: ");fflush(stdin);gets(inputan);
printf("\nPut Sentence (or \"0\" to process): ");fflush(stdin);gets(inputan);// clarified instructions.
if(stricmp(inputan,"0")!=0) { //strcmpi
strcpy(temp,inputan);
}
//getch(); this (or getchar()) is really not necessary here to support
// the flow of your application.
}while(stricmp(inputan,"0")!=0);
printf("Hasil Analisa:\n\n");
for(i=0;i<N;i++) { //replace 10 with N
if(temp[i]!='-') {
char c = temp[i];
for(j=0;j<N;j++) { //replace 10 with N
if(temp[j]!='-') {
if(c == temp[j])
//counter+=1;
counter++; // var++ equivalent var += 1
}
}
jumlah[i] = counter;
counter = 0;
}
}
for(i=0;i<N;i++) {
//if(temp[i]!=' ' && temp[i]!='-' && temp) { // only spaces ?
if(!isspace(temp[i]) && temp[i]!='-' && temp && (temp[i] != 0)) { // temp[i] != 0, and exclude all white space
printf("\t%c terdapat %d\n",temp[i],jumlah[i]);
}
}
getchar(); //orig getch() not standard
}
Addressing your question: how to display only one char if there's a symbol again in another index that have same symbol.
Displaying a list of the characters used, and the number of times used might be better handled in a separate function. The one below can be adapted to be called in your original main function by inserting the following lines:
char *res = letterCounter("this is the string");
printf(res);
free(res);
Just under your existing line: printf("Hasil Analisa:\n\n");
(i.e. replace all your code under that line down to the getch(); function;
char * letterCounter(const char *string)
{
int i, j;
int len = strlen(string);
char *dup = StrDup(string);
if(!dup) return NULL;
int viewableAscii = '~' - '!'; /// range of ASCII from ! to ~ (33 - 126)
char buf[20];
char * results = calloc(100*strlen(string), 1);//ensure enough room
if(!results) return NULL;
/// caps 'A' == 65, 'Z' == 90
/// lowr 'a' == 97, 'z' == 122
/// all visable printables: 33 - 126
unsigned char characterUsageCounter[viewableAscii];
memset(characterUsageCounter, 0,viewableAscii);
for(i=0;i<len;i++)
{
for(j=0;j<viewableAscii;j++)
{
if(dup[i] == 33 + j)
{
characterUsageCounter[j]++;
}
}
}
for(i=0;i<viewableAscii;i++)
{
if(characterUsageCounter[i] > 0)
{
if(characterUsageCounter[i] == 1) sprintf(buf, "%c occurs %d time\n", i+33, characterUsageCounter[i]);
else sprintf(buf, "%c occurs %d times\n", i+33, characterUsageCounter[i]);
strcat(results, buf);
}
}
return results;
}
For example, if the string "this is the string" were passed as the argument to that function, the following would be output:

strings to arrays then print in c

I am trying to take a user inputted string and look at each code to see if it appears in another string of strings. So far my code works.
If the word is successfully found then the alpha representation is to be added to an array that will eventually be printed, but only if all codes were found.
I am having issues with what gets stored in my array that is going to be printed.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef char *string;
typedef char *alpha;
int main(void)
{
string morse[4]={".-", "-...","----.", ".."};
string alpha[4]={"A", "B", "9", "I"};
char prntArr[50];
char *input;
char *hold;
input = malloc(200);
hold = malloc(50);
int i=0;
int j=0;
int ret;
int x;
int w=0;
int z=0;
printf("please enter a string\n");
scanf("%[^\n]",input);
do{
if (input[i] !=' ')
{
hold[j] = input[i];
j++;
}
else
{
hold[j]='\0';
for (x=0;x<4;x++)
{
printf("value of x %d\n",x);
ret = strcmp(morse[x], hold);
if (ret==0)
{
printf("%s\n",alpha[x]);
prntArr[w]=*hold;
w++;
x=4;
}
else
{
ret=1;
printf("invalid Morse code!");
}
}
j = 0;
}
i++;
}while(input[i] !='\0');
for (z=0;z<50;z++)
{
printf("%c",prntArr[z]);
}
return 0;
free(input);
}
The problem you asked about is caused by the way prntArr is used in the program. It really should be an array of character pointers into the alpha array. Instead, it's manipulated as an array of characters into which the first character of each morse code element is stored. And when it's printed, the variable that tracks how much of the array is used is simply ignored.
Another problem is that your code uses spaces to break the codes but there won't necessarily be a space at the end of the line so a code might get missed. In the program below, I switched out scanf() for fgets() which leaves a newline character on the end of the input which we can use, like space, to indicate the end of a code.
Other problems: you print the invalid Morse code message at the wrong point in the code and you print it to stdout instead of stderr; you remember to free input but forget to free hold; you put code after return that never gets called.
Below is a rework of your code that addresses the above problems along with some style issues:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int main(void)
{
char *morse[] = {".-", "-...", "----.", ".."};
char *alpha[] = {"A" , "B" , "9" , "I" };
char *print_array[50];
int print_array_index = 0;
char hold[50];
int hold_index = 0;
char input[200];
int i = 0;
printf("please enter a string: ");
fgets(input, sizeof(input), stdin);
while (input[i] !='\0') {
if (input[i] ==' ' || input[i] == '\n')
{
hold[hold_index] = '\0';
bool found = false;
for (int x = 0; x < sizeof(morse) / sizeof(char *); x++)
{
if (strcmp(morse[x], hold) == 0)
{
print_array[print_array_index++] = alpha[x];
found = true;
break;
}
}
if (!found)
{
fprintf(stderr, "invalid Morse code: %s\n", hold);
}
hold_index = 0;
}
else
{
hold[hold_index++] = input[i];
}
i++;
}
for (int x = 0; x < print_array_index; x++)
{
printf("%s ", print_array[x]);
}
printf("\n");
return 0;
}
SAMPLE RUNS
> ./a.out
please enter a string: ----. -... .- ..
9 B A I
>
> ./a.out
please enter a string: .- --- ..
invalid Morse code: ---
A I
>

Program that checks if an array is a palindrome

I'm trying to create a program that checks if a given array/string is a palindrome or not and its not working. The program just prints "0" on every given array, even on palindromes.
int main()
{
char string[100]= {0};
char stringReverse[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
strcpy(stringReverse , string); // This function copies the scanned array to a new array called "stringReverse"
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// This while reverses the array and insert it to a new array called "stringReverse"
while(firstLetter < lastLetter)
{
temp = stringReverse[firstLetter];
stringReverse[firstLetter] = stringReverse[lastLetter];
stringReverse[lastLetter] = temp;
firstLetter++;
lastLetter--;
}
printf("%s %s", stringReverse, string);
if ( strcmp(stringReverse , string) == 0)
{
printf("1");
}
else
{
printf("0");
}
}
Lets say we implement a simple fun to do that
int check_palindrome (const char *s) {
int i,j;
for (i=0,j=strlen(s)-1 ; i<j ; ++i, --j) {
if (s[i] != s[j]) return 0; // Not palindrome
}
return 1; //Palindrome
}
I think this is far more simpler ;)
For the code posted in question:
Be aware of fgets(). It stops in the first '\n' or EOF and keeps the '\n' character.
So if you give radar for ex, the result string will be "radar\n", which doesn't match with "\nradar"
The Problem:
Let's say you enter the string RACECAR as input for your program and press enter, this puts a newline character or a '\n' in your buffer stream and this is also read as part of your string by fgets, and so your program effectively ends up checking if RACECAR\n is a palindrome, which it is not.
The Solution:
After you initialize lastLetter to strlen(string) - 1 check if the last character in your string (or the character at the lastLetter index is the newline character (\n) and if so, decrease lastLetter by one so that your program checks if the rest of your string (RACECAR) is a palindrome.
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
// Add these 2 lines to your code
// Checks if the last character of the string read by fgets is newline
if (string[lastLetter] == '\n')
lastLetter--;
fgets adds a '\n' at the end.
So if the user entered "aba", string contains "aba\n".
reverseString contains "\naba".
So it doesn't match.
After the fgets, add this code
int l = strlen(string) - 1;
string[l] = 0;
This will strip out the '\n' at the end before copying it to reverseString.
That aside, you can do this whole program inplace without the need of a second buffer or strcpy or strlen calls.
You have several issues in your code:
first you forgot the last closing brace };
then you forgot to remove the trailing \n (or maybe also \r under Windows) in string;
you don't need to revert the string into a new string; a one-pass check is enough:
Here is a working code:
#include <stdio.h>
#include <string.h>
int main()
{
char string[100]= {0};
int temp = 0;
int firstLetter = 0;
int lastLetter = 0;
printf("Please enter a word or a sentence: ");
fgets(string, 100, stdin);
firstLetter = 0;
lastLetter = strlen(string) - 1; //because in array, the last cell is NULL
while ((string[lastLetter]=='\n')||(string[lastLetter]=='\r')) {
lastLetter--;
}
// This while reverses the array and insert it to a new array called "stringReverse"
temp = 1;
while(firstLetter < lastLetter)
{
if (string[firstLetter] != string[lastLetter]) {
temp = 0;
break;
}
firstLetter++;
lastLetter--;
}
if ( temp )
{
printf("1");
}
else
{
printf("0");
}
}
You can do it by this simpleway also.
#include <stdio.h>
#include <string.h>
int main()
{
char string[10], revString[10];
printf("Enter string for reversing it...\n");
scanf("%s", string);
int stringLength = strlen(string);
for(int i = 0; string[i] != '\0'; i++, stringLength--)
{
revString[i] = string[stringLength - 1];
}
if(strcmp(string, revString) == 0)
printf("Given string is pelindrom\n");
else
printf("Given string is not pelindrom\n");
}
#include<stdio.h>
#include<string.h>`enter code here`
void fun(char *a);
int main ()
{
char p[100];
char *s=p;
printf("enter the string");
scanf("%[^\n]",s);
fun(s);
}
void fun(char *a)
{
if(*a && *a!='\n')
{
fun(a+1);
putchar(*a);
}
}
// use this approach better time complexity and easier work hope this helps

delete repetition in strings

i want to write code in c language to delete any character in string s1 which matches any character in the string s2 . using only for loops. that is my trial has failed -_- .
for example if s1="ahmed" and s2="omnia" should edit s1 to >> s1="hed"
#include <stdio.h>
#include <stdlib.h>
int i,j;
int k;
int counter=0;
int main()
{
char s1[100];
char s2[10];
char temp[100];
printf("\n enter string 1: ");
scanf("%s",s1);
printf("\n enter string 2: ");
scanf("%s",s2);
printf("\n%s",s1);
printf("\n%s",s2);
for(j=0;j<9;j++)
{
for(i=0;i<9;i++)
{
if(s1[i]!=s2[j]&&s1[i]!='\0')
{
temp[counter++]=s1[i]; //add unique items to temp
k=counter; //size
temp[counter]='\0';
}
}
}
for(i=0;i<k;i++)
{
s1[i]=temp[i];
}
printf("\nstring 1 after delete : ");
printf("%s",s1);
return 0;
}
how can i compare one item with nested items then achieve a condition ??
Why are you including the null character statements inside the if statement?
Try these two statements after the two for loops, like this. And please indent your code.
for(j=0;j<strlen(s1);j++) //Why is it 9 in your code? It should be the respective lengths
{
for(i=0;i<strlen(s2);i++)
{
if(s1[i]!=s2[j]&&s1[i]!='\0')
{
temp[counter++]=s1[i];
}
}
}
k=counter;
temp[counter]='\0';
and include:#include<string.h>
I don't see any coding errors here, only your logic is flawed.
This should work
for (j = 0; j < 9; j++)
{
for (i = 0; i < 9; i++)
{
if (s1[j] == s2[i] && s1[i] != '\0')
{
break;
}
else if (i == strlen(s2))
{
temp[counter++] = s1[j];
}
}
}
temp[counter] = '\0';
for (i = 0; i < counter; i++)
{
s1[i] = temp[i];
}
printf("\nstring 1 after delete : ");
printf("%s", s1);
In your original code you kept reading the original string from the beginning, instead of advancing the iterator each time.
So in the first iteration you compared 'ahmed' against 'omnia' which is fine.
In the second iteration though, you compared 'ahmed' against 'omnia', instead of 'hmed' against 'omnia', and that's why you got a large repetition of the original string in your output.
Also, I'd memset the memory of s1 and s2 first to 0.

Resources