Finding the longest and shortest string in an inputted array - c

This is my first time using S.O but Im having trouble with my simple program. Im learning C and Im trying to sort an array of 10 strings (that the user inputs) to find the largest and smallest string and print that on screen at the end, as well as the length of the string. My maximum length is running fine however Im having difficulty when trying to find the minimum length, it just keeps saying " The smallest word is '≡■`☻♦' with 4 characters." I have tried to create a nested loop for the minimum length so that it compares each string in the array against the next as well as the minimum that is stored in the minLength variable. I have no clue why these random symbols are appearing and where its getting this from. Any advice would be much appreciated! Thank you
#include <stdio.h>
#include <string.h>
int main()
{
int maxLength = 0;
int maxIndex = 0;
int minIndex = 0;
char word_length[10][20];
printf("Please type 10 words: --------------------- \n \n");
/*USER ENTERS 10 WORDS*/
for (i = 0; i < 10; i++)
{
scanf("%s", &word_length[i]);
}
/*SEARCH FROM INDEX POINTER 0-10*/
for (i = 0; i < 10; i++)
{
/*NEW VARIABLE LENGTH IS UPDATED TO LENGTH OF EACH STRING HELD IN EACH POINTER IN WORD_LENGTH ARRAY*/
int length1 = strlen(word_length[i]);
/*IF THE NEW LENGTH IS BIGGER THAN THE PREVIOUS MAXIMUM LENGTH, THE MAXIMUM LENGTH SCORE IS UPDATED*/
/*THE MAXINDEX VARIABLE KEEPS A RECORD OF WHICH ARRAY POSITION THIS STRING IS HELD IN*/
if (length1 > maxLength)
{
maxLength = length1;
maxIndex = i;
}
/*NEW VARIABLE LENGTH IS UPDATED TO LENGTH OF EACH STRING HELD IN EACH POINTER IN WORD_LENGTH ARRAY*/
int length2 = strlen(word_length[i]);
int next_length2 = strlen(word_length[++i]);
int minLength = strlen(word_length[1]);
/*IF THE NEW LENGTH IS SMALLER THAN THE PREVIOUS MINIMUM LENGTH, THE MINIMUM LENGTH SCORE IS UPDATED*/
/*THE MININDEX VARIABLE KEEPS A RECORD OF WHICH ARRAY POSITION THIS STRING IS HELD IN*/
if (length2 < next_length2)
{
if (length2 < minLength)
{
minLength = length2;
minIndex = i;
}
}
}
/*THE BIGGEST WORD IS DISPLAYED ON SCREEN USING THE MAXINDEX POINTER*/
printf("The biggest word is '%s' with %d characters\n", word_length[maxIndex], maxLength);
printf("The smallest word is '%s' with %d characters\n", word_length[minIndex], minLength);
return 0;
}

For starters this call of scanf
scanf("%s",&word_length[i]);
should be rewritten at least like
scanf("%s", word_length[i]);
Though it would be safer to write
scanf("%19s", word_length[i]);
The both for loops like this
for (i=0;i<11;i++)
use an incorrect condition.
You have to write
for ( i=0; i < 10;i++)
The variable minLength is not declared in the block scope of the function main.
In this the for loop used for searching a string with the minimal length there is used a locally declared variable minLength
for (i = 0; i < 11; i++)
{
/*NEW VARIABLE LENGTH IS UPDATED TO LENGTH OF EACH STRING HELD IN EACH POINTER IN WORD_LENGTH ARRAY*/
int length2 = strlen(word_length[i]);
int next_length2 = strlen(word_length[++i]);
int minLength = strlen(word_length[1]);
^^^^^^^^^^^^^
There is no need to use two for loops. It is enough to use one loop.
It can look the following way
size_t maxIndex = 0;
size_t minIndex = 0;
size_t maxLength = strlen( word_length[0] );
size_t minLength = strlen( word_length[0] );
for ( size_t i = 1; i < 10; i++ )
{
size_t length = strlen( word_length[i] );
if ( maxLength < length )
{
maxLength = length;
maxIndex = i;
}
else if ( length < minLength )
{
minLength = length;
mibIndex = i;
}
}
printf("The biggest word is '%s' with %zu characters\n", word_length[maxIndex], maxLength);
printf("The smallest word is '%s' with %zu characters\n", word_length[minIndex], minLength);

Related

Inconsistent output given by same code on different C compilers

Different compilers are giving different outputs for the same logic in my algorithm.
I wrote the following code for a C code exercise.
The code checks for the longest string in a string vector.
But the same logic gives two different outputs.
Here's what is happening. I have no idea what I did wrong.
First version - without a printf() inside the if condition
Here the if (j > longest) just attributes new values for int longest and int index.
#include <stdio.h>
int main(void) {
char *vs[] = {"jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd"};
int longest, index = 0;
/* i is the index for elements in *vs[].
* "jfd" is 0, "kj" is 1... */
for (int i = 0; i < sizeof(*vs); i++) {
/* j if the index for string lengths in vs[].
* for "jfd", 'j' is 0, 'f' is 1... */
for (int j = 0; vs[i][j] != '\0'; j++) {
/* if j is longer than the previous longest value */
if (j > longest) {
longest = j;
index = i;
}
}
}
printf("Longest string = %s\n", vs[index]);
return 0;
}
I ran it on https://replit.com/. It gave the unexpected output for longest string of "jfd". https://replit.com/#Pedro-Augusto33/Whatafuck-without-printf?v=1
Second version - with a printf() inside the if condition
Now I just inserted a printf() inside the if (jf > longest) condition, as seen in the code block bellow.
It changed the output of my algorithm. I have no idea how or why.
#include <stdio.h>
int main(void) {
char *vs[] = {"jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd"};
int longest, index = 0;
/* i is the index for elements in *vs[].
* "jfd" is 0, "kj" is 1... */
for (int i = 0; i < sizeof(*vs); i++) {
/* j if the index for string lengths in vs[].
* for "jfd", 'j' is 0, 'f' is 1... */
for (int j = 0; vs[i][j] != '\0'; j++) {
/* if j is longer than the previous longest value */
if (j > longest) {
printf("Whatafuck\n");
longest = j;
index = i;
}
}
}
printf("Longest string = %s\n", vs[index]);
return 0;
}
I also ran it on https://replit.com/. It gave the expected output for longest string of "usjkfhcs". https://replit.com/#Pedro-Augusto33/Whatafuck-with-printf?v=1
Trying new compilers
After replit.com giving two different outputs, I tried another compiler to check if it also behaved strangely. https://www.onlinegdb.com/online_c_compiler gives random outputs. Sometimes it's "jfd", sometimes it's "usjkfhcs". https://onlinegdb.com/iXoCDDena
Then I went to https://www.programiz.com/c-programming/online-compiler/ . It always gives the expected output of "usjkfhcs".
So, my question is: why are different compilers behaving so strangely with my algorithm? Where is the flaw of my algorithm that makes the compilers interpret it different?
The code does not make sense.
For starters the variable longest was not initialized
int longest, index = 0;
So using it for example in this statement
if (j > longest) {
invokes undefined behavior.
In this for loop
for (int i = 0; i < sizeof(*vs); i++) {
the expression sizeof( *vs ) is equivalent to expression sizeof( char * ) and yields either 4 or 8 depending on the used system. It just occurred such a way that the array was initialized with 8 initializers. But in any case the expression sizeof( *vs ) does not provide the number of elements in an array and its value does not depend on the actual number of elements.
Using the if statement within the for loop in each iteration of the loop
for (int j = 0; vs[i][j] != '\0'; j++) {
/* if j is longer than the previous longest value */
if (j > longest) {
longest = j;
index = i;
}
}
Also does not make sense. It does not calculate the exact length of a string that is equal to j after the last iteration of the loop. So in general such a loop shall not be used for calculating length of a string.
Consider a string for example like "A". Using this for loop you will get that its length is equal to 0 while its length is equal to 1..
It seems you are trying to find the longest string a pointer to which stored in the array.
You could just use standard C string function strlen declared in header <string.h>. If to use your approach with for loops then the code can look the following way
#include <stdio.h>
int main(void)
{
const char *vs[] = { "jfd", "kj", "usjkfhcs", "nbxh", "yt", "muoi", "x", "rexhd" };
const size_t N = sizeof( vs ) / sizeof( *vs );
size_t longest = 0, index = 0;
for ( size_t i = 0; i < N; i++ )
{
size_t j = 0;
while ( vs[i][j] != '\0' ) ++j;
if ( longest < j )
{
longest = j;
index = i;
}
}
printf( "Longest string = %s\n", vs[index] );
printf( "Its length = %zu\n", longest );
return 0;
}

Boyer Moore replace more than one pattern

I am working on a string search and replace project. I can only change 1 of the target pattern in the sentence. But I can find both.
Example: just do it. you will do it.
find: do
replace: think
expected---> just think it. you will think it.
what actually happened ---> just do it. you will think it.
How can I replace both of them?
I read the sentence from file input.txt
# include <limits.h>
# include <string.h>
# include <stdio.h>
#include <sys/time.h>
# define NO_OF_CHARS 256
# define MAX 10000
int sum = 0;
int control = 0;
// A utility function to get maximum of two integers
int max (int a, int b) { return (a > b)? a: b; }
// The preprocessing function for Boyer Moore's bad character heuristic
void badCharHeuristic( char *str, int size, int badchar[NO_OF_CHARS]) {
int i;
// Initialize all occurrences as -1
for (i = 0; i < NO_OF_CHARS; i++)
badchar[i] = -1;
// Fill the actual value of last occurrence of a character
for (i = 0; i < size; i++)
badchar[(int) str[i]] = i;
}
/* A pattern searching function that uses Bad Character Heuristic of Boyer Moore Algorithm */
void search( char *txt, char *pat,char temp3[MAX],int k,char*r) {
int m = strlen(pat);
int n = strlen(txt);
char src[MAX],p[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int badchar[NO_OF_CHARS],i,leng,l,count;
char v;
/* Fill the bad character array by calling the preprocessing function badCharHeuristic() for given pattern */
badCharHeuristic(pat, m, badchar);
leng = strlen(pat);
strcpy(tempP,r);
//strcat(tempP,"</mark>");
leng = strlen(pat);
l = strlen(txt);
int s = 0; // s is shift of the pattern with respect to text
while(s <= (n - m)) {
int j = m-1;
/* Keep reducing index j of pattern while characters of pattern and text are matching at this shift s */
while(j >= 0 && pat[j] == txt[s+j]) {
count++;
j--;
}
/* If the pattern is present at current shift, then index j will become -1 after the above loop */
if (j < 0) {
//printf("pattern occurs at shift = %d\n", s);
/* Shift the pattern so that the next character in text
aligns with the last occurrence of it in pattern.
The condition s+m < n is necessary for the case when
pattern occurs at the end of text */
printf("The desired pattern was found starting from %d. line at position %d\n",k,s+1);
strncpy(temp, txt, s);
temp[s] = '\0';
//strcat(temp,"<mark>");
control++;
strcat(temp,tempP);
for(i=0;i<MAX;i++) {
if((s+leng+i)<strlen(txt))
temp2[i] = txt[s+leng+i];
else
temp2[i] = v;
}
strcat(temp,temp2);
strcpy(temp3,temp);
s += (s+m < n)? m-badchar[txt[s+m]] : 1;
}
else
/* Shift the pattern so that the bad character in text
aligns with the last occurrence of it in pattern. The
max function is used to make sure that we get a positive
shift. We may get a negative shift if the last occurrence
of bad character in pattern is on the right side of the
current character. */
s += max(1, j - badchar[txt[s+j]]);
}
sum +=count;
}
/* Driver program to test above funtion */
int main() {
char txt[MAX],p[MAX],r[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int k = 1;
FILE *input = fopen("input.txt","r");
FILE *output = fopen("output.txt","w");
printf("Enter the text in which pattern is to be searched:");
fgets(p, MAX, stdin);
printf("Enter the text in which pattern is to be replaced:");
fgets(r, MAX, stdin);
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
p[strlen(p)-1]='\0';
temp[1]='a';
while(!feof(input)){
if(fgets (txt, MAX, input)!=NULL) {
txt[strlen(txt)-1] = '\0';
search(txt, p,temp,k,r);
if(temp[1]!='a') {
fprintf(output,"%s\n",temp);
temp[1]='a';
}
else
fprintf(output,"%s\n",txt);
}
k++;
}
if(control==0) {
printf("\nThe pattern was not found in the given text\n\n");
}
gettimeofday(&tv2, NULL);
printf ("Total time = %f seconds\n", (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 + (double) (tv2.tv_sec - tv1.tv_sec));
fclose(input);
fclose(output);
printf("The number of character comparison: %d\n",sum);
return 0;
}

How to check first letter of one string with last letter of another string inside of same char array

How can I complete the function canArrangeWords() ?
Question : Given a set of words check if we can arrange them in a list such that the last letter of any word and first letter of another word are same. The input function canArrangeWords shall contain an integer num and array of words arr. num denotes the number of word in the list (1<=num<=100). arr shall contain words consisting of lower case letters between 'a' - 'z' only . return 1 if words can be arranged in that fashion and -1 if cannot.
Input : 4 pot ten nice eye
output : 1
input : 3 fox owl pond
output: -1
Please help me complete this program .
**
#include<stdio.h>
#include<string.h>
int canArrangewords(int,char [100][100]);
void main(){
int n ,count=0 , i ;
char arrayS[100][100];
scanf("%d",&n);
for (i = 0; i < n; ++i)
{
scanf("%s",arrayS[i]);
}
for(i=0;i<n;i++)
{
printf("%s",arrayS[i]);
printf("\n");
}
printf("%c\n",arrayS[2][4]);
canArrangewords(n , arrayS);
}
int canArrangewords(int n,char arrayS[100][100]){
int i , j ;
for ( i = 0; i < n; i++)
{
for ( j = i+1 ; j < strlen(arrayS[j+1]); i++)
{
int flag = strlen(arrayS[j+1]) - 1;
int temp = strcmp(arrayS[i][0],arrayS[j][flag]);
}
}
}
}
Well, first of all think of the way you can reach that answer.
If you only need to know if they can or can not be arranged and you do not have to do so your self you can use an empty array of int array[26] for each letter a-z.
The rule is that from all the first and last letters for all the words only two MAY appear an odd amount of times - the first letter of first word in list and the last letter in the last word in the list, the rest MUST appear an even amount of times. I would add a check to make sure the letters are lowercase as well. good luck!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MINASCII 97
#define LETTERS 26
void UpdateArray(char letter, int* arr)
{
if(arr[letter - MINASCII] == 0)
{
++arr[letter - MINASCII];
}
else
{
--arr[letter - MINASCII];/*for each second time same letter is seen reduce back to zero */
}
}
int canArrangewords(int wordNum, char* wordArr[])
{
int arr[LETTERS] = {0};
int i = 0;
int count = 0 ;
char first;
char last;
char* string;
for (i= 0; i< wordNum; ++i)
{
string = wordArr[i];
first = string[0];
last = string[strlen(string)-1];
UpdateArray(first, &arr[0]);
UpdateArray(last, &arr[0]);
}
for(i = 0; i< LETTERS; ++i)
{
count+=arr[i];
}
if(count == 2 || count == 0)/*either once each or twice -see word1 example in main*/
{
return 1;
}
return -1;
}
int main()
{
int i = 0;
char* words[] = {"pot", "ten", "nice", "eye"};
char* words1[] = {"pot", "ten", "nip"};
char* words2[] = {"fox", "owl", "pond"};
i = canArrangewords(4,words);
printf("%d\n", i);
i = canArrangewords(3,words1);
printf("%d\n", i);
i = canArrangewords(3,words2);
printf("%d\n", i);
return 0;
}
Change your array of words into an array of pointers to words. Then you can simply exchange the pointers.
To speed things up, instead of a pointer to a word, have it point to a structure:
struct WORD {
char *firstchar; // begin of word
char *lastchar; // last char of word
} *words[100]; // array of 100 pointers to words
To read the words:
char buf[100];
for (i = 0; i < n; ++i)
{
scanf("%s",buf);
int len= strlen(buf);
words[i]= malloc(sizeof(struct WORDS));
words[i]->firstchar= malloc(len+1);
strcpy(words[i]->firstchar, buf);
words[i]->lastchar= words[i]->firstchar + len-1;
}
Now compare and sort:
if (*words[i]->lastchar == *words[j]->firstchar) {
struct WORDS *tmp= words[i+1];
words[i+1]= words[j];
words[j]= tmp;
}
Do this in a loop, a kind of bubble sort. I leave that to you.

C program - largest word in a 2d array string [duplicate]

I wrote a function that finds the longest string in a 2d array, it works, partially. My problem is that it takes the first longest string that it finds without checking the other ones.
For example, the following list of strings:
eke
em
ekeke
eme
e
ememeememe
emem
ekekee
eooeeeeefe
eede
My function catches "ekeke" (the third string from the list) as the longest instead of "ememeememe ".
Here is my function:
void length(char str[][MAX])
{
int i = 0;
for(i = 1; i < LEN; i++)
{
if(strlen(str[i]) > strlen(str[i-1]))
{
if(strlen(str[i]) > strlen(str[i+1]))
{
printf("%s", str[i]);
break;
}
}
}
}
LEN is a constant, his value is 10.
MAX is a constant, his value is 50.
The strings are given by the user.
Thanks.
You are only comparing the previous and next strings. You need to check the lengths of all the strings.
void length(char str[][MAX])
{
size_t longest = strlen(str[0]);
szie_t j = 0;
for(size_t i = 1; i < LEN; i++)
{
size_t len = strlen(str[i]);
if(longest < len)
{
longest = len;
j = i;
}
}
printf("%s", str[j]);
}
I am assuming you have at least 1 string and handle corner cases (if user inputs less than LEN strings etc -- depends on how you fill the str with strings).

Finding the longest string in a 2d array in C

I wrote a function that finds the longest string in a 2d array, it works, partially. My problem is that it takes the first longest string that it finds without checking the other ones.
For example, the following list of strings:
eke
em
ekeke
eme
e
ememeememe
emem
ekekee
eooeeeeefe
eede
My function catches "ekeke" (the third string from the list) as the longest instead of "ememeememe ".
Here is my function:
void length(char str[][MAX])
{
int i = 0;
for(i = 1; i < LEN; i++)
{
if(strlen(str[i]) > strlen(str[i-1]))
{
if(strlen(str[i]) > strlen(str[i+1]))
{
printf("%s", str[i]);
break;
}
}
}
}
LEN is a constant, his value is 10.
MAX is a constant, his value is 50.
The strings are given by the user.
Thanks.
You are only comparing the previous and next strings. You need to check the lengths of all the strings.
void length(char str[][MAX])
{
size_t longest = strlen(str[0]);
szie_t j = 0;
for(size_t i = 1; i < LEN; i++)
{
size_t len = strlen(str[i]);
if(longest < len)
{
longest = len;
j = i;
}
}
printf("%s", str[j]);
}
I am assuming you have at least 1 string and handle corner cases (if user inputs less than LEN strings etc -- depends on how you fill the str with strings).

Resources