Understanding returning values functions C - c

I'm trying to understand how the return value of a function works, through the following program that has been given to me,
It goes like this :
Write a function that given an array of character v and its dim, return the capital letter that more often is followed by its next letter in the alphabetical order.
And the example goes like : if I have the string "B T M N M P S T M N" the function will return M (because two times is followed by N).
I thought the following thing to create the function:
I'm gonna consider the character inserted into the array like integer thank to the ASCII code so I'm gonna create an int function that returns an integer but I'm going to print like a char; that what I was hoping to do,
And I think I did, because with the string BTMNMPSTMN the function prints M, but for example with the string 'ABDPE' the function returns P; that's not what I wanted, because should return 'A'.
I think I'm misunderstanding something in my code or into the returning value of the functions.
Any help would be appreciated,
The code goes like this:
#include <stdio.h>
int maxvolte(char a[],int DIM) {
int trovato;
for(int j=0;j<DIM-1;j++) {
if (a[j]- a[j+1]==-1) {
trovato=a[j];
}
}
return trovato;
}
int main()
{
int dim;
scanf("%d",&dim);
char v[dim];
scanf("%s",v);
printf("%c",maxvolte(v,dim));
return 0;
}
P.S
I was unable to insert the value of the array using in a for scanf("%c,&v[i]) or getchar() because the program stops almost immediately due to the intepretation of '\n' a character, so I tried with strings, the result was achieved but I'd like to understand or at least have an example on how to store an array of character properly.
Any help or tip would be appreciated.

There are a few things, I think you did not get it right.
First you need to consider that there are multiple pairs of characters satisfying a[j] - a[j+1] == -1
.
Second you assume any input will generate a valid answer. That could be no such pair at all, for example, ACE as input.
Here is my fix based on your code and it does not address the second issue but you can take it as a starting point.
#include <stdio.h>
#include <assert.h>
int maxvolte(char a[],int DIM) {
int count[26] = {0};
for(int j=0;j<DIM-1;j++) {
if (a[j] - a[j+1]==-1) {
int index = a[j] - 'A'; // assume all input are valid, namely only A..Z letters are allowed
++count[index];
}
}
int max = -1;
int index = -1;
for (int i = 0; i < 26; ++i) {
if (count[i] > max) {
max = count[i];
index = i;
}
}
assert (max != -1);
return index + 'A';
}
int main()
{
int dim;
scanf("%d",&dim);
char v[dim];
scanf("%s",v);
printf("answer is %c\n",maxvolte(v,dim));
return 0;
}

#include <stdio.h>
int maxvolte(char a[],int DIM) {
int hold;
int freq;
int max =0 ;
int result;
int i,j;
for(int j=0; j<DIM; j++) {
hold = a[j];
freq = 0;
if(a[j]-a[j+1] == -1) {
freq++;
}
for(i=j+1; i<DIM-1; i++) { //search another couple
if(hold==a[i]) {
if(a[i]-a[i+1] == -1) {
freq++;
}
}
}
if(freq>max) {
result = hold;
max=freq;
}
}
return result;
}
int main()
{
char v[] = "ABDPE";
int dim = sizeof(v) / sizeof(v[0]);
printf("\nresult : %c", maxvolte(v,dim));
return 0;
}

Related

Check for palindrome using stack in C

I'm new to C, and I've been given a question to write a program to check palindrome words.
I did the following code, it gives an output. but the output is always "No". The idea of what I did in this code is, I first divided the string and pushed them into one stack (stacka). then pushed the rest of the letters to another stack(stackb). Then I pop both of those stacks and check whether the letter returning from each pop function(of stacka and stackb) is equal or not. if not it will return 0.
below is the code.
Thank you in advance. Have a nice day!.
#include <stdio.h>
#include <string.h>
char stacka[5];
char stackb[5];
int topa = -1;
int topb = -1;
void pusha(char e) {
topa++;
stacka[topa] = e;
}
void pushb(char e) {
topb++;
stackb[topb] = e;
}
char popa() {
char e = stacka[topa];
topa--;
return e;
}
char popb() {
char e = stackb[topb];
topb--;
return e;
}
int palindrome(char str[]) {
int i, length = strlen(str);
int mid = length / 2;
for (i = 0; i < mid; i++) {
pusha(str[i]);
}
if (length % 2 != 0) {
i++;
}
for (i = length - 1; i >= mid; i--) {
pushb(str[i]);
}
int f;
for (f = mid; f >= 0; f--) {
char ele1 = popa();
char ele2 = popb();
if (ele1 != ele2)
return 0;
}
return 1;
}
int main() {
char str[] = "madam";
if (palindrome(str)) {
printf("Yes");
} else
printf("No");
}
At a first glance, I have found the following issues in your code.
if(length % 2 !=0)
{
i++;
}
for(i=length-1;i>=mid;i--)
{
pushb(str[i]);
}
Your if block does not make any impact on the code and it is unnecessary as well. for loop has an issue as well which can cause your problem.
Let me elaborate a bit. Let's say your input is "madam" and according to your solution, first for loop is doing ok.
int mid=length/2;
for(i=0;i<mid;i++)
{
pusha(str[i]);
}
As your input is "madam" your value for mid would be 2. so, the first stack will contain the letter, 'm', 'a'. This is alright up to this.
In the second for loop there is a issue,
for(i=length-1;i>=mid;i--)
{
pushb(str[i]);
}
According to this stack will contain 'm', 'a', 'd'.
Now I would say the correction here according to me. First of all, you remove the first if block, then do this modification on the second for loop.
for(i=length-1;i>mid;i--)
{
pushb(str[i]);
}
Then finally in last for loop,
for(f=mid-1;f>=0;f--)
{
char ele1=popa();
char ele2=popb();
if(ele1!=ele2)
return 0;
}
I have not compiled and run the code with my given corrections. But I think this will help you to figure out the issues with your code.
First u change the condition of for loop in palindrome function.
for(i=length-1;i>mid;i--)
{
pushb(str[i]);
}
தலைவா எனக்கு ஆங்கிலம் நல்லா வராது.
First u change the condition of for loop in palindrome function.
for(i=length-1;i>mid;i--)
{
pushb(str[i]);
}
Your program is correct.

LRS using C program

So I want to create a function using C to find the longest repeated non overlapping substring in a given string. For example: input banana. Output: an.
I was thinking using comparison of the array of the string and checking for repeats. Is that a viable approach? How would I be able to compare substrings with the rest of the strings. I want to avoid using suffix trees if possible
#include <stdio.h>
#include <string.h>
void stringcheck(char a[],int len, int s1, int s2)
{
int i=s1+1;
int j=s2+1;
if(j<=len&&a[i]==a[j])
{
printf("%c",a[i]);
stringcheck(a,len,i,j);
}
}
void dupcheck(char a[], int len, int start)
{
for(int i=start;i<len-1;i++)
{
for(int j=i+1;j<=len;j++)
{
if(a[i]==a[j])
{
printf("%c",a[i]);
stringcheck(a,len,i,j);
i=len;
}
}
}
}
int main()
{
char input[99];
scanf("%s",input);
int start=0;
int len =strlen(input);
dupcheck(input,len,start);
return 0;
}
Yes, this is a valid approach.
You can compare the string - character by character, that way no need to truly save a substring.
You can see a dynamic solution using c++ taking that approach here: https://www.geeksforgeeks.org/longest-repeating-and-non-overlapping-substring/
This solution can be converted to c without many changes.
Another variant if the option is to save the substring by its' indexes.
You can then compare it against the string, and save the max substring, however this will take O(n^3) when the above solution does it in O(n^2).
edit: I converted the solution to c:
#include <stdio.h>
#include <string.h>
void longestRepeatedSubstring(char * str, char * res)
{
int n = strlen(str);
int LCSRe[n+1][n+1];
int res_length = 0; // To store length of result
int i, j, index = 0;
// Setting all to 0
memset(LCSRe, 0, sizeof(LCSRe));
// building table in bottom-up manner
for (i=1; i<=n; i++)
{
for (j=i+1; j<=n; j++)
{
// (j-i) > LCSRe[i-1][j-1] to remove
// overlapping
if (str[i-1] == str[j-1] &&
LCSRe[i-1][j-1] < (j - i))
{
LCSRe[i][j] = LCSRe[i-1][j-1] + 1;
// updating maximum length of the
// substring and updating the finishing
// index of the suffix
if (LCSRe[i][j] > res_length)
{
res_length = LCSRe[i][j];
index = (i>index) ? i : index;
}
}
else
LCSRe[i][j] = 0;
}
}
// If we have non-empty result, then insert all
// characters from first character to last
// character of string
j=0;
if (res_length > 0) {
for (i = index - res_length + 1; i <= index; i++) {
res[j] = str[i-1];
j++;
}
}
res[j]=0;
}
// Driver program to test the above function
int main()
{
char str[] = "banana";
char res[20];
longestRepeatedSubstring(str, res);
printf("%s",res);
return 0;
}

How to "delete" every element in array by value in C

I have been trying to solve this problem for about 5 days..can't find any solution please send help. I am supposed to implement a function to "delete" every element in an array by value. Let's say my array is "Hello" and I want to delete every "l". So far I can only delete l once. By the way keep in mind I am not allowed to use pointers for this function...(we haven't learned that yet in my school) Here's my code:
#include <stdio.h>
#include <string.h>
void strdel(char array[], char c);
int main(void)
{
char source[40];
printf("\nStrdel test: ");
strcpy(source, "Hello");
printf("\nsource = %s", source);
strdel(source, 'l');
printf("\nStrdel: new source = %s", source);
return 0;
}
void strdel(char array[], char c)
{
int string_lenght;
int i;
for (string_lenght = 0; array[string_lenght] != '\0'; string_lenght++) {}
for (i = 0; i < string_lenght; i++) {
if (array[i] == c) {
for (i = i; array[i] != '\0'; ++i)
array[i] = array[i + 1];
}
}
}
Simple use 2 indexes, one for reading and one for writing. #Carl Norum
void strdel(char array[], char c) {
int read_index = 0;
int write_index = 0;
while (array[read_index] != '\0') {
if (array[read_index] != c) {
array[write_index] = array[read_index];
write_index++; // Only advance write_index when a character is copied
}
read_index++; // Always advance read_index
}
array[write_index] = '\0';
}
The has O(n) performance, much faster than using nested for() loops which is O(n*n).
Details:
OP: By the way keep in mind I am not allowed to use pointers for this function.
Note that array in void strdel(char array[], char c) is a pointer, even though it might look like an array.
int for array indexing is OK for learner and much code, yet better to use size_t. int may lack the range needed. Type size_t is an unsigned type that is neither too narrow nor too wide for array indexing needs. This becomes important for very long strings.
Your problem is related to using the variable i in both loops. So once the inner loop is executed, outer loop will terminate right after.
Use another variable for the inner loop.
void strdel(char array[], char c)
{
int string_lenght;
int i, j;
for (string_lenght = 0; array[string_lenght] != '\0'; string_lenght++) {}
for (i = 0; i < string_lenght; i++) {
if (array[i] == c) {
for (j = i; array[j] != '\0'; ++j) // Use variable j instead of i
array[j] = array[j + 1];
--i; // Decrement i to "stay" at the same index
--string_lenght; // As one character were just removed
}
}
}
The above shows how to make OPs approach work. For a better solution see the answer from #chux : https://stackoverflow.com/a/53487767/4386427

Outputs differing -- can't understand the logic

Basically I am creating an array 'string' with some values in it, creating another array ('auxstring'), and then storing all the values of the initial array in reverse order. Finally I print them out.
How come when I execute the program as is, I get garbage as the output? However, if I put another number in the 'string' array (ie: {3,1,1,3,4}) it works fine (outputs: 43113).
It also works fine if I add this line:
"printf("%d\n", sizeof(auxstring));"
right before the for loop.
I'm sure it's something very basic, but I would like to understand what is going on behind the scene and why adding a number at the end of the initial string, or putting that printf, somehow outputs the accurate numbers.
Thanks.
#include <stdio.h>
#include <string.h>
int main(void) {
int i=0, j, l;
char string[] = {3,1,1,3};
char auxstring[sizeof(string)];
for (j=(sizeof(auxstring) - 1); j >= auxstring[0]; j--) {
auxstring[j] = string[i];
i++;
}
for (l=0; l < sizeof(auxstring); l++) {
printf("%d",auxstring[l]);
}
return 0;
}
The condition in the for loop
for (j=(sizeof(auxstring) - 1); j >= auxstring[0]; j--) {
^^^^^^^^^^^^^^^^^^
does not make sense because at least the array auxstring is not initialized.
Also the loop is complicated because it uses two variables as indices.
Ans the variables i, j, l should have the type size_t - the type of the returned value of the operator sizeof.
The program can look the following way
#include <stdio.h>
int main(void)
{
char string[] = { 1, 2, 3, 4 };
char auxstring[sizeof( string )];
const size_t N = sizeof( string );
for ( size_t i = 0; i < N; i++ )
{
auxstring[i] = string[N - i - 1];
}
for ( size_t i = 0; i < N; i++ )
{
printf( "%d", auxstring[i] );
}
return 0;
}
Its output is
4321
The loop condition should be j >= 0.
Right now you compare against the uninitialized value in auxstring[0], which is indeterminate (and will seem random).

Using a returned value from a function in C

My goal is to make a Vigenere cipher. I am attempting to do this by getting the key from argv, getting the string from the user, then passing the message and key though a function I made which combined them and returns the new value before printing it. For some reason it is just printing the key. I think it has something to do with the new function and how I am trying to use the returned value. Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <cs50.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
int new_crypt;
int encrypt(string , int );
int main(int argc, string argv[])
{
if( argc != 2)
{
printf("Plese enter only one key");
return 1;
}
string message = GetString();
for(int i=0; i < strlen(message); i++)
{
int klen = strlen(argv[1]);
//repeats the key until the message is over
int key= argv[1][i%klen];
bool kupper = isupper(key);
bool klower = islower(key);
bool kalpha = isalpha(key);
if(kupper == true){
//ASCII value of A is 65. 'A' = 0 shifts
int k = key-65;
int new_crypt = encrypt(message, k);
printf("%c", new_crypt);
}
if(klower == true){
//ASCII value of 'a' is 97. 'a' = 0 shifts
int k = key- 97;
int new_crypt = encrypt(message, k);
printf("%c", new_crypt);
}
if(kalpha == false){
int k = 0;
int i = i-1;
int new_crypt = encrypt(message, k);
printf("%c", new_crypt);
}
}
printf("\n");
return 0;
}
int encrypt(string message, int k)
{
for(int i=0; i < strlen(message); i++)
{
bool upper = isupper(message[i]);
if(upper == true)
{ //Makes sure the message doesnt go past 'Z'.. If it does it mod 90 it / // and adds 65 ('A')
int crypt = (message[i]+ k) % 90;
if(crypt < 65)
{
int new_crypt = (crypt + 65);
return new_crypt;
}
else{
int new_crypt = crypt;
return new_crypt;
}
}
bool lower = islower(message[i]);
if(lower == true)
{
int crypt = (message[i]+ k) % 123;
if(crypt < 97)
{
int new_crypt = crypt + 97;
return new_crypt;
}
else{
int new_crypt = crypt;
return new_crypt;
}
}
bool alpha = isalpha(message[i]);
if(alpha == false)
{
int new_crypt = message[i];
return new_crypt;
}
}
return 0;
}
The loop in the encrypt function is completely useless, because there is no path through the loop-body without a return statement causing the loop to be terminated and control returned to the caller of encrypt. This makes that the program as a whole repeatedly encrypts the first character of the message with successive elements from the key.
The easiest way around this is to make the following changes
Remove the loop from the encrypt function
Pass, as an additional argument, the element from the message that you want to encrypt, making the signature
int encrypt(string message, int k, int i)
Some miscellaneous remarks:
The global variable new_crypt is not used anywhere. You can safely remove it. (You should avoid the use of global variables as much as reasonably possible).
Instead of using the magic number 65, you can also use the character literal 'A'. This has the advantage that you don't need a comment to explain the number 65 and that it is always the correct value for the capital A, even if you end up not using ASCII. (But see also the next bullet)
Your code assumes the letters A to Z (and a to z) have contiguous values (such that Z == A+26). This may happen to be the case for the English alphabet in the ASCII encoding, but it is not guaranteed for other language alphabets or encodings.

Resources