Why my program does not print true result in C - c

I've found a code about finding longest string in an array and print it with strrev(); function.
My code works successfully, but if my first string was larger than other strings my program does not understand.
This is my prototype:
void LongStr(char str[][50],int n);
and This is my Main() function:
int main()
{
char str[size][wsize];
int n;
printf("\n How many words to accept:- ");
scanf("%d",&n);
printf("\n Enter %d words:- \n \n",n);
for(int i = 0; i < n; i++)
scanf("%s", str[i]);
LongStr(str,n);
return 0;
}
and this is my LongStr(); function:
void LongStr(char str[][50],int n)
{
int Max = strlen(str[0]);
int len;
int c;
for(int i = 1; i < n; i++)
{
len = strlen(str[i]);
if( len > Max )
{
c = i;
Max = len;
}
}
printf("\n The longest string with reverse model is: \"%s\" \n \n",strrev(str[c]));
}
Example:
FirstString
SecondLongestString
ThirdString
output: strrev("SecondLongestString");
Example:
FirstString
SecondString
ThirdLongestString
output: strrev("SecondLongestString");
Example:
FirstLongestString
SecondString
ThirdString
output: crash!
Thanks.

If the longest string is the first c is never initialized, which makes it garbage and most likely a huge number to index the array.
You should initialize it to 0:
void LongStr(char str[][50],int n)
{
int Max = strlen(str[0]);
int len;
int c = 0;
// ...
}
PS: although this problem doesn't occur with len, I'd say it's probably good practise to initialize it to something too. In other words, initializing all variables is a good thing. However, I haven't code in C in a long time and I'm not sure if this is the norm.

Really simple it's just a missing piece in your code
int Max = strlen(str[0]);
int len;
int c;
You need to give the c a value that why it's not working because it doesn't have a base value so try to change your code to
int Max = strlen(str[0]);
int len;
int c = 0; // base value of 0

Related

scanf does not work with &str when str is defined as char str[100]

Please, can someone tell me what is the problem in my syntax. I want to find the duplicate letters in a word. it is working properly if I declare a character array here itself but not working with scanf.
#include<stdio.h>
// Finding the duplicate alphabets in a string
int length(char str[]) //Finding the length of the string
{
int len;
while(str[len]!='\0')
{
len++;
}
return len;
}
void duplicate(char str[],int n)
{
int i,j,flag;
for(i=0;i<=n-2;i++) //Selecting the alphabet for comparison
{
flag=0;
if(str[i]!='\0')
{
for(j=i+1;j<=n-1;j++) //comparison of alphabets
{
if(str[j]==str[i])
{
flag=1;
str[j]=0;
}
}
if(flag==1)
{
printf("%c is the duplicate character\n",str[i]);
}
}
}
}
int main()
{
char str[100];
scanf("%s",&str);
int n= length(str);
duplicate(str,n);
}
The problems that I noticed:
main: scanf("%s",&str); is the wrong type for str (char (*)[100]) and should be scanf("%s", str);. char str[100] uses a magic 100 value, instead #define STR_LEN 99 so you can do char str[STR_LEN + 1]. The way you use scanf is subject to buffer overflow instead you should use scanf("%" str(STR_LEN) "s", STR_LEN, str) and you need #define str(s) xstr(s) and #define xstr(s) #s. I suggest using fgets instead.
length: int len; is uninitialized and should be int len = 0; (len is not a great variable name as it's usually 1 bigger than last index, but you use it to index with). Why did you write your own instead of using strlen? As you only return values 0 or great, consider using unsigned instead of int for the type of i and the return value.
duplicate (minor issue): it's good practice to minimize variable scope so for(int i = 0; ... and declare flags where you initilize it. You should technically ensure that n > INT_MIN + 1 for underflow, or change type to an unsigned value, or just calculate it yourself internally.
You can also create an array of counts for each letter. Initialized to 0, and add 1 as you find each letter. Then report the letters with count > 1. This would be a O(n) algorithm instead of the original O(n^2).
#include <limits.h>
#define CHARS (UCHAR_MAX+1)
void duplicate(char *str) {
unsigned char counts[CHARS] = { 0 }; // 0, 1 or 2 for 2+
for(unsigned i=0; str[i]; i++) {
char *c = counts + (unsigned) str[i];
*c += *c <= 1;
}
for(unsigned i=0; i<CHARS; i++) {
if(counts[i] > 1) {
printf("%c is the duplicate character\n", (char) i);
}
}
}
As advised, always ensure that your local variables are initialized before attempting to use them. As for your problem, if your sole desire is to find duplicate strings then you could approach it this way:-
#include<stdio.h>
#define CHAR_SIZE 100
int length(char[]);
void duplicate(char[], int);
// Finding the duplicate alphabets in a string
int length(char str[]) //Finding the length of the string
{
int len = 0;
while(str[len] !='\0')
len++;
return len;
}
//find duplicates
void duplicate(char str[],int n)
{
for(int i =0; i < n; i++)
for(int j=i+1; j<n; j++)
if(str[i] == str[j])
printf("%c is the duplicate character\n",str[i]);
}
//test case
int main()
{
char str[CHAR_SIZE];
puts("Enter string\n");
scanf("%s",str);
int n= length(str);
printf("len of entered str is %d\n\n", n);
duplicate(str,n);
}

Longest palindrome in a string and it's length

I have a program that is supposed to go through a string identify possible palindromes, check if it is a palindrome and then return the length from palindromelength() or -1 if it is not, and print out the longest palindrome of the string.
The program is compiling but the output is wrong.
This is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int palindromelength(char *str, int i, int j){
char *start = str;
char *end = str + j;
while(start < end){
if(*start != *end)
return -1;
start++;
end--;
}
return j-i+1;
}
void ispalindrome(char *str){
int length = 1, max = 1, start =0, i, j;
for(i=0; i<= strlen(str) -2; i++){
for(j= 1; j <= strlen(str)-1; j++){
if(abs(i-j) > 1){
length = palindromelength(str, i, j);
if( length> max){
max = length;
start = i;
}
}
}
}
if(max > 1){
printf("Largest palindrome is ");
for( ; start <= j; start++){
printf("%c", str[start]);
start++;
}
}
else
printf("No palindromes in string.");
}
int main(void) {
char a[50];
char *a2;
printf("Enter a string\n");
scanf("%[^\n]", a);
int length = strlen(a) + 1;
a2 = (char*)malloc(length*sizeof(char));
strcpy(a2, a);
free (a2);
char *a3 = &a;
ispalindrome(a3);
return 0;
}
I have tried the palindromelength() separately with a simple string, "aracecar". palindrimelength(a3, 0, 4) returns -1 so that is right, palindromelength(a3, 0, 3) returns 3 so that is right, but palindromelength(a3, 1, 7) returns -1, which is wrong. I double checked my function with other ones on stack overflow and it seems right, what could be the problem?
As for the second function ispalindrome() is there a better way I could write that one? It just seems kind of messy right know.
I am a newbie, therefore I may not have yet learned some more advanced/sophisticated variations I could take to solve this.
I presume int i is the starting index of the string and int j is the ending index. If that is so, have a closer look at the first line of your palindromelength() function. Could the function ever start from somewhere other than index 0?
As for ways to do the ispalindrome() function, there are many algorithms out there to check whether or not an input is a palindrome, I would suggest having a look around and finding out different methods. If your way works, great! probably the cleanest way is to use recursion although that can take some thinking.

How to count a specific character in an array and also call the function?

I am trying to make a program to count a specific character in an array. I got the program working how I think it should be working, however it was all in my main function and I wanted to break it out of there but I seem to be having an issue with doing so. My code when it was all in main was:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char array[100];
int i = 0;
int a_counter = 0;
printf("Enter an array: \n");
scanf("%[^\n], array);
printf("Array is: %s\n", array);
for( i = 0; array[i] != '\0'; i++)
{
if (array[i] == 'A')
a_counter++;
}
printf("Number of A's: %d\n, a_counter);
}
In the code above, if I enter AAABCDEF, the result would tell me that there are 3 A's.
Now, I want to get this out of main and also not limit the character to only being an 'A'. I wanted to to count whatever character I set the function call with. My attempt to do so was this:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char array[100];
printf("Enter an array: \n");
scanf("%[^\n], array);
printf("Array is: %s\n", array);
countletter(array, 'A');
countletter(array, 'L'); //I want to call function and add
//whatever letter I felt like it
return 0;
}
void countletter(char(array), char x)
{
int i = 0;
int count = 0;
for (i = 0; array[&i] != '\0'; i++)
if(array[&i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
so if I called the countletter function, I wanted it to count the specific letter I sent it to count but my outputs were not even close. My outputs seemed to always be zero, and if I entered a specific array, it would put me in an infinite input mode. It seems that I am still confused on pointers and passing and calling functions.
The function you have written is wrong
void countletter(char *array, char x)
{
int i = 0;
int count = 0;
for (i = 0; array[i] != '\0'; i++)
if(array[i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
Also before main, you have to declare the function
void countletter(char *array, char x);
Instead of defining
void countletter(char(array), char x)
{
int i = 0;
int count = 0;
for (i = 0; array[&i] != '\0'; i++)
if(array[&i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
you should define:
void countletter(char array[], char x) // OR void countletter(char* array, char x)
{
int i = 0;
int count = 0;
for (i = 0; array[i] != '\0'; i++)
if(array[i] == x)
count++;
printf("Number of %c's: %d\n", x, count);
}
Moreover its a good practice to always pass size with an array or string. So probably below is the better function prototype.
void countletter(char array[], int size, char x)
There are two errors int he code:
void countletter(char(array), char x)
and
for (i = 0; array[&i] != '\0'; i++)
if(array[&i] == x)
The correct lines are:
void countletter(char* array, size_t size, char x)
and
for (i = 0; (i < size) && (array[i] != '\0'); i++)
if(array[i] == x)
You have to pass the entire array (by passing pointer to its first element in my example) and you have to work as usual (exactly as you did in the first monolithic version).
You must also pass the array size and take it into account when working with the array.
I would personally prefer this syntax for dealing with pointers.
void countLetter(char *array, char x) {...}
And for iterating through the array
for(i=0; *(array+i) != '\0'; i++)
Similarly for comparing
if(*(array+i) == x)
Internally, array[i] gets converted in *(array+i), so you can choose whatever you want.
The problem with your code is your method
countletter(char(array), char x)
This method is expecting two characters as parameters, where as you are passing a pointer and a character.
Second one is
array[&i]
For accessing ith element of an array, you should use something like array[i].

Reverse string with external function

I recently started a course in Programming in C. I got an assignment where I'm going to make an external function with this declaration:
void reverse(char *array, int numberOfChars)
My code looks like this at the moment. The problem is that the code will just reverse the first half of the word, and keep the second half as normal.
#include <stdio.h>
#include <string.h>
void reverse(char *array, int numberOfChars) {
int i = 0;
int j = 0;
for (i = numberOfChars - 1; i >= 0; i--) {
array[j] = array[i];
j = j + 1;
}
}
#define NAMESIZE 100
int main() {
char word[NAMESIZE];
int length;
printf("Enter a word: ");
scanf("%s", word);
getchar();
length = strlen(word);
reverse(word, length);
printf("%s\n", word);
}
Even when you use an intermediate variable, your code will reverse the string twice, leaving it as it was. A small change to the code compares i with j as well as using a temporary variable to do the swap.
int i, j = 0;
char temp;
for(i = numberOfChars-1; i > j; i--){
temp = array[j];
array[j] = array[i];
array[i] = temp;
j = j + 1;
}
Your function has a classic problem: you are reversing the string in place. You overwrite the characters at the start of the string with the characters from the end. The initial characters are lost by the time you reach the mid point. You should instead swap the characters from both ends and stop at the mid point.
You are going to need a secondary char array to reverse the string.Try like this:
#include <stdio.h>
#include <string.h>
#define NAMESIZE 100
void reverse(char *arr,int numberOfChars);
int main()
{
char word[NAMESIZE];
printf("Enter a word: ");
scanf("%s",word);
getchar();
size_t length=strlen(word);
reverse(word,length);
printf("%s\n",word);
}
void reverse(char *arr,int numberOfChars)
{
char buffer[NAMESIZE];
int j = 0,i = numberOfChars;
while( i-- )
buffer[j++] = arr[i];
buffer[j] = '\0';
strcpy(arr,buffer);
}
A simple way to prevent overwriting your array is to copy your array into a temporary one and write the reversed readed temporary array into the other.
If you want to have an unknown array size at compilation to reverse, I recommend you to use a heap array (see man malloc) instead of stack one to prevent segmentation fault if numberOfChars is too hight.

C - Find most frequent element in char array

i'm developing a little function to display the most frequent character in a (char) array.
This is what I've accomplished so far, but I think i'm on the wrong way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char test[10] = "ciaociaoci";
max_caratt(test, 10);
}
int max_caratt(char input[], int size)
{
int i;
char max[300];
max[0] = input[0];
for (i=0; i<size; i++)
{
if(strncmp(input,input[i],1) == 1)
{
printf("occourrence found");
max[i] = input[i];
}
}
}
Any help?
Actually, the correct code is this.
It's just a corrected version of IntermediateHacker's below snippet.
void main()
{
int array[255] = {0}; // initialize all elements to 0
char str[] = "thequickbrownfoxjumpedoverthelazydog";
int i, max, index;
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// Find the letter that was used the most
max = array[0];
index = 0;
for(i = 0; str[i] != 0; i++)
{
if( array[str[i]] > max)
{
max = array[str[i]];
index = i;
}
}
printf("The max character is: %c \n", str[index]);
}
The easiest way to find the most common character is to create an int array of 255 and just increment the arraly element that corresponds to the character. For example: if the charcter is 'A', then increment the 'A'th element (if you look at any ascii table you will see that the letter 'A' has a decimal value of 65)
int array[255] = {0}; // initialize all elements to 0
char str[] = "The quick brown fox jumped over the lazy dog.";
int i, max, index;
// Now count all the letters in the sentence
for(i = 0; str[i] != 0; i++)
{
++array[str[i]];
}
// Find the letter that was used the most
max = array[0];
index = 0;
for(i = 0; str[i] != 0; i++)
{
if( array[i] > max)
{
max = array[i];
index = i;
}
}
printf("The max character is: %c \n", (char)index);
You're passing a (almost) string and a char to strncmp(). strncmp() takes two strings (and an integer). Your program shouldn't even compile!
Suggestion: increase the warning level of your compiler and mind the warnings.
You may want to look at strchr() ...
Assuming an input array of 0-127, the following should get you the most common character in a single pass through the string. Note, if you want to worry about negative numbers, shift everything up by +127 as needed...
char mostCommonChar(char *str) {
/* we are making the assumption that the string passed in has values
* between 0 and 127.
*/
int cnt[128], max = 0;
char *idx = str;
/* clear counts */
memset((void *)cnt, 0, sizeof(int) * 128);
/* collect info */
while(*idx) {
cnt[*idx]++;
if(cnt[*idx] > cnt[max]) {
max = *idx;
}
idx++;
}
/* we know the max */
return max;
}
If you don't need to preserve the input array, you could sort the input array first, then find the longest contiguous run of a single character. This approach is slower, but uses less space.
I made a working version using structs. It works fine, I guess, but I think there's a MUCH better way to write this algorithm.
#include <stdio.h>
#include <stdlib.h>
struct alphabet {
char letter;
int times;
};
typedef struct alphabet Alphabet;
void main() {
char string[300];
gets(string);
Alphabet Alph[300];
int i=0, j=0;
while (i<=strlen(string)) {
while(j<=300) {
if(string[i] != Alph[j].letter) {
Alph[i].letter = string[i];
Alph[i].times = 1;
}
else {
Alph[j].times++;
}
j++;
}
j=0;
i++;
}
int y,max=0;
char letter_max[0];
for (y=0; y<strlen(string); y++) {
printf("Letter: %c, Times: %d \n", Alph[y].letter, Alph[y].times);
if(Alph[y].times>max) {
max=Alph[y].times;
letter_max[0]=Alph[y].letter;
}
}
printf("\n\n\t\tMost frequent letter: %c - %d times \n\n", letter_max[0], max);
}
I saw you all creating big arrays and "complex" stuff so here I have easy and simple code xD
char most_used_char (char s[]) {
int i; //array's index
int v; //auxiliary index for counting characters
char c_aux; //auxiliary character
int sum = 0; //auxiliary character's occurrence
char c_max; //most used character
int max = 0; //most used character's occurrence
for (i = 0; s[i]; i++) {
c_aux = s[i];
for (v = 0; s[v]; v++)
if (c_aux == s[v]) sum++; /* responsible cycle for counting
character occurrence */
if (sum > max) { //checks if new character is the most used
max = sum;
c_max = c_aux;
}
sum = 0; /* reset counting variable so it can counts new
characters occurrence */
}
return c_max; //this is the most used character!
}

Resources