I need to check if a given string is a Palindrome or mini-Palindrome.
Palindrome length will be 2 or more, the function need to ignore spaces and ignore the differences of upper and lower alphabet.
if the string is Palindrome the function will transfer the indexes of the start and the end of him and will return 1 else return 0.
example1: "My gym" the function will transfer low=0 high=5 and 1
example2: "I Love ANNA" the function will transfer low=7 high=10 and 1
example3: "I love Pasta" return 0.
Also i can’t use functions from librarys other then string.h stdlib.h stdio.h.
I tried to write like this:
int i;
int size = strlen(str);
i = 0;
while (str[i] != '\0')
{
if (str[i] == ' ')
{
i++;
continue;
}
//-------------------
if (str[i] >= ‘a’ && str[i] <= ‘z’)
str[i] = str[i] - 32;
if (str[size-1] >= ‘a’ && str[size-1] <= ‘z’)
str[size-1] = str[size-1] - 32;
//-------------------
if (str[i] == str[size-1])
{
*low = i;
*high = size-1;
return 1;
}
else
{
size--;
i++;
}
}
return 0;
But it isnt working well, i cant figure how to do it with the example 2
Here goes. Will this help you
#define LOWER(a) (((a) >=' A' && (a) <= 'Z') ? ((a) - 'A' +'a') : (a))
#define MYCMP(a,b) (LOWER(a) == LOWER(b))
int is_palidrome(char *s) {
int start = 0;
int end = strlen(s) - 1;
for (; s[start] // Not end of line
&& end >=0 // Not run over the from of the line
&& start < end // Still not got to the middle
&& MYCMP(s[start], s[end]) == 1; // They are still equal
start++, end--) { //Nowt }
};
return (start >= end);
}
I made a program. It works only if the string contains letters and spaces. You can modify it to work for other characters.
#include <stdio.h>
#include <string.h>
#define SIZE 100
int isPalindrome( char *s, size_t l );
int main() {
char str[SIZE];
size_t i, j, len, pldrm = 0;
fgets(str, SIZE, stdin);
len = strlen(str);
for(i = 0; i < len; i++) if( str[i] != ' ' && !((str[i] >= 'a' && str[i] <= 'z') || (str[i] >= 'A' && str[i] <= 'Z')) ) goto the_end;
for(i = 0; i < len-1; i++) {
if( str[i] != ' ' ) {
for(j = i+1; j < len; j++) {
if( (pldrm = isPalindrome(&str[i], j-i+1)) ) {
str[j+1] = '\0';
goto the_end;
}
}
}
}
the_end:
pldrm ? printf("A palindrome has been found from the position %zu till the position %zu.\n\nThe palindrome is: %s\n", i, j, &str[i]) : puts("No palindromes");
return 0;
}
int isPalindrome( char *s, size_t l )
{
static const char az[26] = "abcdefghijklmnopqrstuvwxyz", AZ[26] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int isPldrm = 1, spc = 0; // used to skip spaces within the palindrome
for(size_t i = 0; i < l/2; i++) {
for(size_t j = 0; j < 26; j++) {
if( s[i] == az[j] || s[i] == AZ[j] ) {
while( s[l-1-i-spc] == ' ' ) ++spc;
if( s[l-1-i-spc] != az[j] && s[l-1-i-spc] != AZ[j] ) {
isPldrm = 0;
goto thats_it;
}
break;
}
}
}
thats_it:
return isPldrm;
}
Also, it finds only the first palindrome in the input. Doesn't check for further palindromes.
Related
I was trying this pattern matching method in C but whenever I give all the input, the vscode terminal waits for a while and just stops the program without any warnings/message. Can anyone point to what is wrong here?
#include <stdio.h>
#include <string.h>
int main()
{
char STR[100], PAT[100], REP[100], ANS[100];
int i, m, j, k, flag, slP, slR, len;
i = m = k = j = flag = len = 0;
printf("\nMain String: ");
gets(STR);
printf("\nPattern String: ");
gets(PAT);
slP = strlen(PAT);
printf("\nReplace String: ");
gets(REP);
slR = strlen(REP);
while (STR[i] != '\0')
{
if (STR[i] = PAT[j])
{
len = 0;
for (k = 0; k < slP; k++)
{
if (STR[k] = PAT[k])
len++;
}
if (len == slP)
{
flag = 1;
for (k = 0; k < slR; k++, m++)
ANS[m] = REP[k];
}
}
else
{
ANS[m] = STR[i];
m++;
i++;
}
}
if (flag == 0)
{
printf("\nPattern not found!");
}
else
{
ANS[m] = '\0';
printf("\nResultant String: %s\n", ANS);
}
return 0;
}
There are multiple problems in the code:
using gets() is risky, this function was removed from the C Standard because it cannot be used safely.
if (STR[i] = PAT[j]) copied the pattern to the string. You should use:
if (STR[i] == PAT[j])
similarly, if (STR[k] = PAT[k]) is incorrect. You should compare PAT[k] and STR[i + k]:
if (STR[i + k] == PAT[k])
you should test for buffer overflow for the output string as replacing a short string by a larger one may produce a string that will not fit in ANS
you do not increment i properly.
Here is a modified version:
#include <stdio.h>
int getstr(const char *prompt, char *dest, int size) {
int c, len = 0;
printf("%s", prompt);
while ((c = getchar()) != EOF && c != '\n') {
if (len + 1 < size)
dest[len++] = c;
}
if (size > 0)
dest[len] = '\0';
printf("\n");
if (c == EOF && len == 0)
return -1;
else
return len;
}
int main() {
char STR[100], PAT[100], REP[100], ANS[100];
int i, m, k, flag;
if (getstr("Main String: ", STR, sizeof STR) < 0)
return 1;
if (getstr("Pattern String: ", PAT, sizeof PAT) < 0)
return 1;
if (getstr("Replace String: ", REP, sizeof REP) < 0)
return 1;
i = m = flag = 0;
while (STR[i] != '\0') {
if (STR[i] == PAT[0]) { // initial match
// compare the rest of the pattern
for (k = 1; PAT[k] != '\0' && PAT[k] == STR[i + k]; k++)
continue;
if (PAT[k] == '\0') { // complete match
flag = 1;
// copy the replacement string
for (k = 0; REP[k] != '\0'; k++) {
if (m + 1 < sizeof ANS)
ANS[m++] = REP[k];
}
i += k; // skip the matching characters
continue;
}
}
// otherwise copy a single character
if (m + 1 < sizeof ANS)
ANS[m++] = STR[i];
i++;
}
ANS[m] = '\0';
if (flag == 0) {
printf("Pattern not found!\n");
} else {
printf("Resultant String: %s\n", ANS);
}
return 0;
}
so this is my function. My main focus is to get the character frequencies and the highest character frequency.
The function below (get_letter_frequencies) is supposed to get a string example ("I am a big boy") and return the character frequencies and the highest character frequency.
The Function should return
i - 2
a - 2
m - 1
b - 2
g - 1
o - 1
y - 1
Highest character frequency would be " iab "
My problem is with the get_letter_frequencies function. What should I arrange from the function in order to return the above output?
void get_letter_frequencies(const char *text, size_t len, int freq[26], int *max_freq)
{
for(int i = 0; i<len; i++)
{
if(text[i] != ' ' || !(is_sentence_terminator(text[i]))) //this condition is set in order to ignore the spaces and the sentence terminators (! ? .)
{
if(text[i] >= 'a' && text[i] <= 'z')
{
freq[text[i] - 'a']++;
}
}
}
for(int j = 0; j < 26; j++)
{
if(freq[j] >= 1)
{
*max_freq = freq[j];
}
}
This function below(is_sentence_terminator). Here the function checks whether the sentence finishes with a " ! ? or . " if it does not finish with one of the terminators then it is not a sentence and ignores it.
int is_sentence_terminator(char ch)
{
if(ch == 33 || ch == 46 || ch == 63)
{
return 1;
}else
{
return 0;
}
}
There are some issues in your code:
there is no need to test for special characters, comparing text[i] to 'a' and 'z' is sufficient for ASCII systems.
in the second loop, you should update *max_freq only if freq[j] is greater than the current value, not 1. *max_freq should be initialized to 0 before the loop.
In the calling code, you would also
print the letters whose frequency is non 0.
print all letters with the maximum frequency using one final loop.
Here is a modified version:
void get_letter_frequencies(const char *text, size_t len, int freq[26], int *max_freq) {
for (int i = 0; i < 26; i++)
freq[i] = 0;
for (int i = 0; i < len; i++) {
if (text[i] >= 'a' && text[i] <= 'z') {
freq[text[i] - 'a']++; // assuming ASCII
}
}
*max_freq = 0;
for (int i = 0; i < 26; i++) {
if (*max_freq < freq[i]) {
*max_freq = freq[i];
}
}
}
My program is designed to allow the user to input a string and my program will output the number of occurrences of each letters and words. My program also sorts the words alphabetically.
My issue is: I output the words seen (first unsorted) and their occurrences as a table, and in my table I don't want duplicates. SOLVED
For example, if the word "to" was seen twice I just want the word "to" to appear only once in my table outputting the number of occurrences.
How can I fix this? Also, why is it that i can't simply set string[i] == delim to apply to every delimiter rather than having to assign it manually for each delimiter?
Edit: Fixed my output error. But how can I set a condition for string[i] to equal any of the delimiters in my code rather than just work for the space bar? For example on my output, if i enter "you, you" it will out put "you, you" rather than just "you". How can I write it so it removes the comma and compares "you, you" to be as one word.
Any help is appreciated. My code is below:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
const char delim[] = ", . - !*()&^%$##<> ? []{}\\ / \"";
#define SIZE 1000
void occurrences(char s[], int count[]);
void lower(char s[]);
int main()
{
char string[SIZE], words[SIZE][SIZE], temp[SIZE];
int i = 0, j = 0, k = 0, n = 0, count;
int c = 0, cnt[26] = { 0 };
printf("Enter your input string:");
fgets(string, 256, stdin);
string[strlen(string) - 1] = '\0';
lower(string);
occurrences(string, cnt);
printf("Number of occurrences of each letter in the text: \n");
for (c = 0; c < 26; c++){
if (cnt[c] != 0){
printf("%c \t %d\n", c + 'a', cnt[c]);
}
}
/*extracting each and every string and copying to a different place */
while (string[i] != '\0')
{
if (string[i] == ' ')
{
words[j][k] = '\0';
k = 0;
j++;
}
else
{
words[j][k++] = string[i];
}
i++;
}
words[j][k] = '\0';
n = j;
printf("Unsorted Frequency:\n");
for (i = 0; i < n; i++)
{
strcpy(temp, words[i]);
for (j = i + 1; j <= n; j++)
{
if (strcmp(words[i], words[j]) == 0)
{
for (a = j; a <= n; a++)
strcpy(words[a], words[a + 1]);
n--;
}
} //inner for
}
i = 0;
/* find the frequency of each word */
while (i <= n) {
count = 1;
if (i != n) {
for (j = i + 1; j <= n; j++) {
if (strcmp(words[i], words[j]) == 0) {
count++;
}
}
}
/* count - indicates the frequecy of word[i] */
printf("%s\t%d\n", words[i], count);
/* skipping to the next word to process */
i = i + count;
}
printf("ALphabetical Order:\n");
for (i = 0; i < n; i++)
{
strcpy(temp, words[i]);
for (j = i + 1; j <= n; j++)
{
if (strcmp(words[i], words[j]) > 0)
{
strcpy(temp, words[j]);
strcpy(words[j], words[i]);
strcpy(words[i], temp);
}
}
}
i = 0;
while (i <= n) {
count = 1;
if (i != n) {
for (j = i + 1; j <= n; j++) {
if (strcmp(words[i], words[j]) == 0) {
count++;
}
}
}
printf("%s\n", words[i]);
i = i + count;
}
return 0;
}
void occurrences(char s[], int count[]){
int i = 0;
while (s[i] != '\0'){
if (s[i] >= 'a' && s[i] <= 'z')
count[s[i] - 'a']++;
i++;
}
}
void lower(char s[]){
int i = 0;
while (s[i] != '\0'){
if (s[i] >= 'A' && s[i] <= 'Z'){
s[i] = (s[i] - 'A') + 'a';
}
i++;
}
}
I have the solution to your problem and its name is called Wall. No, not the type to bang your head against when you encounter a problem that you can't seem to solve but for the Warnings that you want your compiler to emit: ALL OF THEM.
If you compile C code with out using -Wall then you can commit all the errors that people tell you is why C is so dangerous. But once you enable Warnings the compiler will tell you about them.
I have 4 for your program:
for (c; c< 26; c++) { That first c doesn't do anything, this could be written for (; c < 26; c++) { or perhaps beter as for (c = 0; c <26; c++) {
words[i] == NULL "Statement with no effect". Well that probably isn't what you wanted to do. The compiler tells you that that line doesn't do anything.
"Unused variable 'text'." That is pretty clear too: you have defined text as a variable but then never used it. Perhaps you meant to or perhaps it was a variable you thought you needed. Either way it can go now.
"Control reaches end of non-void function". In C main is usually defined as int main, i.e. main returns an int. Standard practice is to return 0 if the program successfully completed and some other value on error. Adding return 0; at the end of main will work.
You can simplify your delimiters. Anything that is not a-z (after lower casing it), is a delimiter. You don't [need to] care which one it is. It's the end of a word. Rather than specify delimiters, specify chars that are word chars (e.g. if words were C symbols, the word chars would be: A-Z, a-z, 0-9, and _). But, it looks like you only want a-z.
Here are some [untested] examples:
void
scanline(char *buf)
{
int chr;
char *lhs;
char *rhs;
char tmp[5000];
lhs = tmp;
for (rhs = buf; *rhs != 0; ++rhs) {
chr = *rhs;
if ((chr >= 'A') && (chr <= 'Z'))
chr = (chr - 'A') + 'a';
if ((chr >= 'a') && (chr <= 'z')) {
*lhs++ = chr;
char_histogram[chr] += 1;
continue;
}
*lhs = 0;
if (lhs > tmp)
count_string(tmp);
lhs = tmp;
}
if (lhs > tmp) {
*lhs = 0;
count_string(tmp);
}
}
void
count_string(char *str)
{
int idx;
int match;
match = -1;
for (idx = 0; idx < word_count; ++idx) {
if (strcmp(words[idx],str) == 0) {
match = idx;
break;
}
}
if (match < 0) {
match = word_count++;
strcpy(words[match],str);
}
word_histogram[match] += 1;
}
Using separate arrays is ugly. Using a struct might be better:
#define STRMAX 100 // max string length
#define WORDMAX 1000 // max number of strings
struct word {
int word_hist; // histogram value
char word_string[STRMAX]; // string value
};
int word_count; // number of elements in wordlist
struct word wordlist[WORDMAX]; // list of known words
I am writing a program where I am taking string as an input, here I need to remove spaces , ignore alphabets and use only numerals.
I am able to achieve removing spaces and alphabets, but i can only use single digits and not multiple digits.
Example:Input string:"adsf 12af 1 a123c 53c2m34n"
Here I need to use the input as "12 1 123 54234" required for my application.
It will be great some one could share the logic or the sample code for the same.
Thanks in advance
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int pullOut(const char *str, int array[], int *size){
const char *p = str, *endp;
int pull, count = 0, max = *size, num;
do{
endp=strchr(p, ' ');
if(endp == NULL)
endp=strchr(p, '\0');
for(num=pull=0; p != endp; ++p){
if(isdigit(*p)){
num = num * 10 + *p - '0';
pull = 1;
}
}
if(pull && count < max)
array[count++] = num;
while(*p == ' ')
++p;//skip sapce
}while(*endp != '\0');
return *size = count;
}
int main(void){
char input[] = "adsf 12af 1 a123c 53c2m34n abc def";
int i, arr[128] = { 0 }, arr_num = sizeof(arr)/sizeof(int);
pullOut(input, arr, &arr_num);
for(i = 0; i < arr_num ; ++i)
printf("%d\n", arr[i]);
return 0;
}
int i = 0;int j = 0;
while (input[i])
{
if (input[i] == ' ' || (input[i] >= '0' && input[i] <= '9'))
newString[j++] = input[i];
i++;
}
newString[j] = '\0';
If you do this, you'll copy only numerics and space into newString. I let you do all the memory alloc stuff.
here is your func:
void remove_func(char *str)
{
int i;
i = 0;
while(str[i])
{
if(str[i] >= '0' && str[i] <= '9')
{
putchar(str[i]);
i++;
}
else if(str[i] == ' ' && str[i + 1] != ' ')
{
putchar(str[i]);
i++;
}
else
i++;
}
}
What about this one:
char * getNumbers(const char *src, char *dst)
{
int j=0,i=0;
while (i < strlen(src))
{
if (src[i] >= '0' && src[i] <= '9')
{
dst[j++]=src[i++];
}
else
{
// skip duplicates spaces
if (j > 0 && src[i] == ' ' && dst[j-1] != ',') dst[j++]=',';
i++;
}
}
// remove the trailing ',' if exists
if (j > 0 && dst[j-1] == ',') j--;
dst[j]='\0';
return dst;
}
char src[] = "adsf 12af 1 a123c 53c2m34n";
char dst[sizeof(src)];
getNumbers(src, dst);
printf("'%s' -> '%s'\n", src, dst);
output:
'adsf 12af 1 a123c 53c2m34n' -> '12,1,123,53234'
I am trying to implement the rot13-algorithm in C.
But since I am not very familiar with that language, I have some problems with my code right here.
Basically, I want to rotate every letter in args[] to 13 positions up.
But this code seems to be pretty sluggish:
#include <stdio.h>
char[] rotate(char c[]) {
char single;
int i;
int alen = sizeof(c)/sizeof(c[0]);
char out[alen];
for(i=0;i<=alen;i+=1) {
if(c[i]>='a' && (c[i]+13)<='z'){
out[i] = c[i]+13;
}
}
return out;
}
int main(int argc, char *argv[]) {
printf("The given args will be rotated\n");
int i;
char rotated[sizeof(argv)/sizeof(argv[0])];
rotated = rotate(argv);
/* printing rotated[] later on */
return 0;
}
I know there a lot of holes here - could you show me how to fix this?
Thanks a lot guys, I solved the problem with this code
#include <stdio.h>
int rot13(int c){
if('a' <= c && c <= 'z'){
return rot13b(c,'a');
} else if ('A' <= c && c <= 'Z') {
return rot13b(c, 'A');
} else {
return c;
}
}
int rot13b(int c, int basis){
c = (((c-basis)+13)%26)+basis;
return c;
}
int main() {
printf("The given args will be rotated");
int c;
while((c = getchar()) != EOF){
c = rot13(c);
putchar(c);
}
return 0;
}
How #Michael said this char out[alen] is not accepted by the compiler because you can't declare an array size with a non constant value. Another problem of your code is the for loop for( i = 0; i < = alen; i+=1 ) the arrays start on 0 so if you do the for until the lenght's position you will be out of the array.
About the code:
You must use a pointer to the start of the string as argument of the function, because You can't return arrays in C (But you can return pointers ).
Your if( str[i] >= 'a' && (str[i]+13) <='z') is incorrect because you will convert some letters into symbols take a look.
________
--------------------------!
void rotate( char * str )
{
int i = 0;
/* You do this until you find a '\0' */
for( i = 0; str[ i ] != '\0' ; i++ ){
/* Use the pointer notation if you passed a pointer. */
/* If the letter is between a and m you can simply sum it. */
if( *( str + i ) >= 'a' && *( str + i ) < 'n')
*( str + i ) += 13;
/* If the letter is between the n and z you have to do the opposite.*/
else if( *( str + i ) >= 'n' && *( str + i ) <= 'z')
*( str + i ) -= 13;
}
}
Size of arrays in C must be set at compile time, so you can't use non constant expression for array size.
Consider the below implementation:
// in place rotate
void rotate(char *str)
// str must be a zero-terminated string
{
int i =0;
// loop until str itself is not NULL and str[i] is not zero
for(i=0;str && str[i]; ++i) // ++i is a pre-increment
{
if(str[i] >= 'a' && (str[i]+13) <='z')
{
str[i] = str[i]+13; // modifying str in place
}
}
}
Then your main() can look like this:
int main(int argc, char *argv[])
{
printf("The given args will be rotated: %s\n", argv[1]);
rotate(argv[1]);
printf("Rotated: %s\n", argv[1]);
return 0;
}
Update More advanced version of the transform that takes care of case when str[i] + 13 > 'z'
for(i=0;str && str[i]; ++i) // ++i is a pre-increment
{
// ignore out of range chars
if (str[i] < 'a' || str[i] > 'z') continue;
// rotate
for (off = 13; off > ('z' - str[i]); )
{
off-= (1 + 'z' - str[i]);
str[i] = 'a';
}
str[i]+=off;
}
This function can encode/decode to/from rot13 string. It's compatible with VIM's g? rot13 encoder.
void rot13 (char *s) {
if (s == NULL)
return;
int i;
for (i = 0; s[i]; i++) {
if (s[i] >= 'a' && s[i] <= 'm') { s[i] += 13; continue; }
if (s[i] >= 'A' && s[i] <= 'M') { s[i] += 13; continue; }
if (s[i] >= 'n' && s[i] <= 'z') { s[i] -= 13; continue; }
if (s[i] >= 'N' && s[i] <= 'Z') { s[i] -= 13; continue; }
}
}