How can I convert this method to become recursive? - c

Method checks for the amount of each character and if its even for every character, it returns 1. Otherwise, it returns 0. String is passed via str[]. chars[] has its every value set to one at the start. It's hard to picture this becoming recursive, any help on teaching is appreciated.
int recursionCheckEven(int i, int j, char str[], int chars[20]) {
for (i = 0; i < strlen(str); i+=2) {
int count = 0;
for (j = i; j < strlen(str); j+=2) {
if (str[i] == str[j] && chars[j] == 1) {
count++;
chars[i] = 2;
chars[j] = 2;
}
}
if (count % 2 != 0) {
chars[i] = 0;
}
}
for (int k = 0; k < 20; k++) {
if (chars[k] == 0) {
return 0;
break;
}
}
return 1;
}
How I call this:
for (unsigned int i = 0; i < stringcount; i++) {
int chars[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
if(recursionCheckEven(0, 0, strings[i], chars)) {
printf("The %dth string has even number of characters\n", i);
}
}

You can use a loop to go through the characters in a non-recursive way (this is recommended). The idea of recursion is to avoid using a loop (which is actually not recommended and wastes stack memory and causes other problems).
For recursive check, you can use pointers the check each element, then go to the next element and use the same function.
To help you get started, this is a recursive function which takes a string and counts the number of each character.
int recursive(int total, char* ptr, char ch)
{
if (*ptr == '\0')
return total;
if (*ptr == ch)
total++;
return recursive(total, ptr + 1, ch);
}
int main(void)
{
char *str = "111";
char ch = '1';
int total = recursive(0, str, ch);
printf("total of char %c in %s: %d\n", ch, str, total);
return 0;
}

Related

Problem with counting elements in the list of names

I have made one program, where you enter a few characters (10 max). It makes you a list, count average length of surnames, tell about how much different names. But the problem is, when I enter the last number (10) - it sorts me it incorrectly (like 1, 10, 2, 3, 4, 5, 6, 7, 8, 9). Beneath I will present my code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct people {
char num[2];
char surname[20];
char name[10];
} peoples[10], c;
int main()
{
int i, j, k = 0, l = 0, m = 0, n = 0;
float s = 0;
char str[100];
system("chcp 1251 > nul");
for (i = 0, j = 0; i < 10; i++, j++)
{
printf("Enter number, surname, name %d of your human: ", i + 1);
gets(str);
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].num[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != ' ')
{
peoples[j].surname[k] = str[n];
}
else
break;
n++;
k++;
}
n++;
k = 0;
while (str[n] != '\n')
{
if (str[n] != '\0')
{
peoples[j].name[k] = str[n];
}
else
break;
n++;
k++;
}
n = 0;
k = 0;
}
for (i = 0; i < 10; i++)
{
for (j = i + 1; j < 10; j++)
{
if (!strcmp(peoples[i].name, peoples[j].name))
m = 1;
}
if (m == 0)
l++;
m = 0;
s = s + strlen(peoples[i].surname);
}
for (i = 0; i < 9; i++)
for (j = 0; j < 9; j++)
if (strcmp(peoples[j].num, peoples[j+1].num) > 0)
{
c = peoples[j+1];
peoples[j+1] = peoples[j];
peoples[j] = c;
}
for (i = 0; i < 10; i++)
{
printf("%s ", peoples[i].num);
printf("%s ", peoples[i].name);
printf("%s ", peoples[i].surname);
printf("\n");
}
printf("\nYou have %d different names\n", l);
printf("Avarege lenght of surname is = %f\n", s / 10);
}
If you want to give numeric input, then use actual numeric data.
Change the num field to become an int instead of a single-character string:
struct people {
int num;
char surname[20];
char name[10];
};
Use fgets to read the line:
fgets(str, sizeof str, stdin);
[Error checking left as exercise for reader]
Then use e.g. sscanf for parse your string:
sscanf(str, "%d %s %s", &peoples[j].num, &peoples[j].name, &peoples[j].name);
[Error checking left as exercise for reader]
And finally, instead of doing your own sorting use the standard qsort function:
qsort(peoples, 10, sizeof(struct people), &compare_people_num);
With the comparison function being something like this:
int compare_people_num(const void *a, const void *b)
{
const struct people *p1 = a;
const struct people *p2 = b:
return p1->num - p2->num; // Change order to reverse sort
}
Using sscanf and qsort will make your code much simpler and easier to understand.

String manipulation (variable output with the same input)

Maybe some property is passing unnoticed to me, but when 'i' is 1 it just freeze. When i input whatever string, 'j' variable goes to 700 or 2000 in different executions. The code goal is to output repetitive letters if you input "cheese" the output should be "eee". What am i doing wrong?
#include <stdio.h>
char * repeticoes(char *s) {
int index = 0;
for (int i = 0;( s[i] != '\0'); i++) //problem starts when i is > 0
{
for (int j = 0; ( s[j] != '\0'); j++)
{
if (s[i] == s[j])
{
printf("%c == %c\ni %d j %d\n", s[i], s[j],i,j);
s[index++] = s[i];
}
else
{
printf("not happening %c != %c\ni %d j %d\n", s[i],s[j],i,j);
}
}
}
s[++index] = '\0';
return s;
}
main() {
char input[21];
printf("str 1\n");
fgets(input, 20, stdin);
repeticoes(input);
printf("duplicated letters %s\n", input);
}
You need to start the inner loop at the next character after the one being processed in the outer loop, otherwise you'll process the same pair of characters twice, as well as testing a character against itself when i == j.
You should also break out of the inner loop as soon as you find a match. You'll find later matches in a future iteration of the outer loop. Otherwise you'll process the same pair twice again.
And you shouldn't increment index before assigning the null character after the loop. It was already incremented when adding the repetition.
#include <stdio.h>
char * repeticoes(char *s) {
int index = 0;
for (int i = 0;( s[i] != '\0'); i++) //problem starts when i is > 0
{
for (int j = i+1; ( s[j] != '\0'); j++)
{
if (s[i] == s[j])
{
printf("%c == %c\ni %d j %d\n", s[i], s[j],i,j);
s[index++] = s[i];
break;
}
else
{
printf("not happening %c != %c\ni %d j %d\n", s[i],s[j],i,j);
}
}
}
s[index] = '\0';
return s;
}
int main() {
char input[21];
printf("str 1\n");
fgets(input, 20, stdin);
repeticoes(input);
printf("duplicated letters %s\n", input);
}
With an array of letters to count and an array of counts. Once the letters have been counted, loop through the input again and set the letters that have a count greater than one.
#include <stdio.h>
void repeticoes ( char *s) {
char tocount[] = "abcdefghijklmnopqrstuvwxyz";
size_t len = sizeof tocount;
size_t index = 0;
int count[len];
for (int j = 0; j < len; j++) {
count[j] = 0;
}
for (int i = 0;( s[i] != '\0'); i++) {
for (int j = 0; j < len; j++) {
if ( s[i] == tocount[j]) {
count[j]++;
}
}
}
for (int i = 0;( s[i] != '\0'); i++) {
for (int j = 0; j < len; j++) {
if ( s[i] == tocount[j] && 1 < count[j]) {
s[index] = s[i];
index++;
}
}
}
s[index] = '\0';
}
int main ( void) {
char input[21];
printf("str 1\n");
fgets(input, 20, stdin);
repeticoes(input);
printf("duplicated letters %s\n", input);
return 0;
}

C Program to count substrings

Why does my program always skip the last substring count?
eg1. String: dbdbsnasdb dbdxx
Substring: db
count: 4 (no error)
eg2. String: dbdbsnasmfdb
Substring: db
count: 2 (supposed to be 3)
** #include <stdio.h> only
int countSubstr(char string[], char substring[]) {
int i, j;
int count = 0;
int subcount = 0;
for (i = 0; i <= strlen(string);) {
j = 0;
count = 0;
while ((string[i] == substring[j])) {
count++;
i++;
j++;
}
if (count == strlen(substring)) {
subcount++;
count = 0;
} else
i++;
}
return subcount;
}
and why must I declare my j and count to be 0 in the for loop? is it because j has to remain as 0 (substring remains the same) whenever it loops?
Your inner loop (while) can continue to compare well past the null terminators in either strings.
You need to stop it as soon as one of the strings reach their terminating null character.
Your outer loop condition has an off-by-one error. But you don't need strlen call anyway. Just iterate until the null character.
You can also move the strlen(substring) outside the loop to avoid potentially recalculating it.
A better version might look like:
int countSubstr(char string[], char substring[])
{
int subcount = 0;
size_t sub_len = strlen(substring);
if (!sub_len) return 0;
for (size_t i = 0;string[i];) {
size_t j = 0;
size_t count = 0;
while (string[i] && string[j] && string[i] == substring[j]) {
count++;
i++;
j++;
}
if (count == sub_len) {
subcount++;
count = 0;
}
else {
i = i - j + 1; /* no match, so reset to the next index in 'string' */
}
}
return subcount;
}
There are some issues in your code:
The loop for (i = 0; i <= strlen(string);) recomputes the length of the string once per iteration of the loop and you iterate one time too far. You should instead write: for (i = 0; string[i] != '\0';)
The second loop may run beyond the end of the string, and produce a value of count that is loo large: it will produce at least 3 for the second example as the null terminator is counted in all cases. This explains why you get an incorrect count of matches. The behavior is actually undefined as you are reading beyond the end of both strings.
Here is an corrected version:
int countSubstr(char string[], char substring[]) {
int len = strlen(string);
int sublen = strlen(substring);
int i, j, count = 0;
for (i = 0; i <= len - sublen; i++) {
for (j = 0; j < sublen && string[i + j] == substring[j]; j++)
continue;
if (j == sublen)
count++;
}
return count;
}
Note that the number of occurrences of the empty string in any given string will come out as one plus the length of the string, which does make sense.
Note also that this code returns 2 for countSubstr("bbb", "bb") which may of may not be what you expect. The accepted answer returns 1, which is arguable.
This works for all edge-cases I tested
#include <stdio.h>
int countSubstr(char string[], char substring[])
{
int count = 0;
size_t i = 0;
while(string[i])
{
int match = 1;
size_t j = 0;
while (substring[j])
{
match &= substring[j] == string[i + j];
j++;
}
count += match;
i++;
}
return count;
}
Here are some test cases:
void test(char name[], int expected, char string[], char substring[]){
int actual = countSubstr(string, substring);
char* status = (actual == expected)? "PASS" : "FAIL";
printf("%s: %s\nActual: %d\nExpected: %d\n\n",name,status,actual,expected);
}
int main(void) {
test("Two empty strings", 0, "", "");
test("Empty substring", 19, "sub str sub str sub", "");
test("Empty string", 0, "", "sub");
test("Case 1", 4, "dbdbsnasdb dbdxx", "db");
test("Case 2", 3, "dbdbsnasmfdb", "db");
test("No match", 0, "dbdbsnasmfdb", "dxb");
test("Inner matching", 3, "abababa", "aba");
test("Identity test", 1, "a", "a");
return 0;
}
In your while loop, you haven't check if you get past the string length.
edit:
Remember that in C all string have a '\0' at the end but in your while loop you don't check it.
On your particular example we get (starting at last db):
i = 10, j = 0, count = 1 (check for 'd')
i = 11, j = 1, count = 2 (check for 'b')
i = 12, j = 2, count = 3 (check for '\0')
i = 13, j = 3, count = 3 (exit loop)
count = 3 is different than strlen(substring) == 2
-> no increase on subcount
for (i = 0; i <= strlen(string);)
Must be
for (i = 0; i < strlen(string);)
Use two for instead a very complex loop becouse it's more easy to debug .

why the last number in doted decimal is not converted to binary?

#include<stdio.h>
#include<string.h>
#include <math.h>
long long convertDecimalToBinary(int n);
int main() {
int verify;
long long bip, dip;
char str1[100];
printf("Enter dotted decimal ip address :\n");
scanf("%s",str1);
verify = bin_verify(str1);
seperate(str1);
return 0;
}
int bin_verify(char str1[]) {
int i;
for(i = 0; i < strlen(str1); i++) {
if((str1[i] < 255) && (str1[i] > 0)) {
return 1;
}
}
}
// function to get first decimal no sepreted
int seperate(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
//goto one;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s1 = atoi(a);
s1 = convertDecimalToBinary(s1);
printf("Binary Format of IP :\n");
printf("%d.",s1);
seperate2(str1);
return 0;
}
// function to get second decimal no sepreted
int seperate2(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
//goto one;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s2 = atoi(a);
s2 = convertDecimalToBinary(s2);
printf("%d.",s2);
seperate3(str1);
return 0;
}
// function to get third decimal no sepreted
int seperate3(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
//goto one;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s3 = atoi(a);
s3 = convertDecimalToBinary(s3);
printf("%d.",s3);
seperate4(str1);
return 0;
}
// function to get fourth decimal no sepreted
int seperate4(char str1[]) {
int s1, s2, s3, s4;
int i, j, k = 0, m, cnt = 0, cnt1 = 0, pos = 0;
char a[4], str2[100];
for(i = 0; i < strlen(str1); i++) {
pos = cnt;
if(str1[i] == '.') {
k = i;
pos = cnt;
for(j = 0; j < i; j++) {
a[j] = str1[k-cnt];
cnt = cnt - 1;
}
break;
}
else {
cnt++;
}
}
for(m = 0; m <= pos; m++) {
str1++;
}
s4 = atoi(a);
s4 = convertDecimalToBinary(s4);
printf("%d\n",s4);
return 0;
}
//to convert decimal to binary
long long convertDecimalToBinary(int n)
{
//printf("%d", n);
long long binaryNumber = 0;
int remainder, i = 1,step=0;
while (n!=0)
{
remainder = n%2;
// printf("Step %d: %d/2, Remainder = %d, Quotient = %d\n", step++, n, remainder, n/2);
n /= 2;
binaryNumber += remainder*i;
i *= 10;
}
return binaryNumber;
}
output:
Enter dotted decimal ip address :
192.15.7.4
Binary Format of IP :
11000000.1111.111.0
I want to convert ip address to binary but,
It always return 0 as binary of last decimal number.
why it is not performing seperate4() function?
What you have done wrong is already listed in the comments but you are doing it overly complicated, nearly Rube-Goldberg like. It is quite simple and can be done without any complicated tricks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// ALL CHECKS OMMITTED!
char *int8_to_bin(int n, char *buf)
{
int i = 8;
// we need an unsigned integer for the bit-juggling
// because of two's complement numbers.
// Not really needed here because the input is positive
unsigned int N;
// check for proper size
if (n < 0 || n > 255) {
return NULL;
}
// is safe now
N = (unsigned int) n;
// we work backwards here, least significant bit first
// but we want it least significant bit last.
while (i--) {
// make a (character) digit out of an integer
buf[i] = (char) (N & 0x1) + '0';
// shift one bit to the right and
// drop the least significant bit by doing it
N >>= 1;
}
// return the pointer to the buffer we got (for easier use)
return buf;
}
int main(int argc, char **argv)
{
// keeps the intermediate integer
int addr;
// command-line argument, helper for strtol() and int8_to_bin()
char *s, *endptr, *cp;
// buffer for int8_to_bin() to work with
// initialize to all '\0';
char buf[9] = { '\0' };
// array holding the end-result
// four 8-character groups with three periods and one NUL
char binaddr[4 * 8 + 3 + 1];
// iterator
int i;
if (argc < 2) {
fprintf(stderr, "Usage: %s dotted_ipv4\n", argv[0]);
exit(EXIT_FAILURE);
}
// set a pointer pointing to the first argument as a shortcut
s = argv[1];
// the following can be done in a single loop, of course
// strtol() skips leading spaces and parses up to the first non-digit.
// endptr points to that point in the input where strtol() decided
// it to be the first non-digit
addr = (int) strtol(s, &endptr, 0);
// work on copy to check for NULL while keeping the content of buf
// (checking not done here)
cp = int8_to_bin(addr, buf);
// if(cp == NULL)...
// copy the result to the result-array
// cp has a NUL, is a proper C-string
strcpy(binaddr, cp);
// rinse and repeat three times
for (i = 1; i < 4; i++) {
// skip anything between number and period,
// (or use strchr() to do so)
while (*endptr != '.'){
endptr++;
}
// skip the period itself
endptr++;
// add a period to the output
strcat(binaddr, ".");
// get next number
addr = (int) strtol(endptr, &endptr, 0);
cp = int8_to_bin(addr, buf);
// if(cp == NULL)...
strcat(binaddr, cp);
}
printf("INPUT: %s\n", s);
printf("OUTPUT: %s\n", binaddr);
exit(EXIT_SUCCESS);
}
We don't need a complicated parsing algorithm, strtol() does it for us, we just need to find the next period ourselves. The size of all in- and output is known and/or can be easily checked if they are inside their limits--e.g.: no need for tedious and error-prone memory allocations, we can use fixed size buffers and strcat().
There is a principle, that holds not only in the Navy but also in programming: KISS.

Print out the longest substring in c

Suppose that we have a string "11222222345646". So how to print out subsequence 222222 in C.
I have a function here, but I think something incorrect. Can someone correct it for me?
int *longestsubstring(int a[], int n, int *length)
{
int location = 0;
length = 0;
int i, j;
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
{
if (a[i] != a[j])
{
if (i - j >= *length)
{
*length = i - j;
location = j;
}
j = i;
}
}
return &a[location];
}
Sorry,I don't really understand your question.
I just have a little code,and it can print the longest sub string,hope it can help.
/*breif : print the longest sub string*/
void printLongestSubString(const char * str,int length)
{
if(length <= 0)
return;
int i ;
int num1 = 0,num2 = 0;
int location = 0;
for(i = 0; i< length - 1; ++i)
{
if(str[i] == str[i+1])
++num2;//count the sub string ,may be not the longest,but we should try.
else
{
if(num2 >num1)//I use num1 store the sum longest of current sub string.
{ num1 = num2;location = i - num2;}
else
;//do nothing for short sub string.
num2 = 0;
}
}
for(i = location;str[i]== str[num1];++i)
printf("%c",str[i]);
printf("\n");
}
int main()
{
char * str = "1122222234566";
printLongestSubString(str,13);
return 0;
}
From your code it appears you want to return the longest sub-sequence (sub-string). Since I'm relearning C I thought I would give it a shot.
I've used strndup to extract the substring. I'm not sure how portable it is but I found an implementation if needed, just click on the link. It will allocate memory to store the new cstring so you have to remember to free the memory once finished with the substring. Following your argument list, the length of the sub-string is returned as the third argument of the extraction routine.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len);
int main()
{
char str[] = "11222234555555564666666";
size_t substr_len = 0;
char *substr = extract_longest_subsequence(str, sizeof(str), &substr_len);
if (!substr)
{
printf("Error: NULL sub-string returned\n");
return 1;
}
printf("original string: %s, length: %zu\n", str, sizeof(str)-1);
printf("Longest sub-string: %s, length: %zu\n", substr, substr_len);
/* Have to remember to free the memory allocated by strndup */
free(substr);
return 0;
}
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len)
{
if (str == NULL || str_len < 1 || longest_len == NULL)
return NULL;
size_t longest_start = 0;
*longest_len = 0;
size_t curr_len = 1;
size_t i = 0;
for (i = 1; i < str_len; ++i)
{
if (str[i-1] == str[i])
{
++curr_len;
}
else
{
if (curr_len > *longest_len)
{
longest_start = i - curr_len;
*longest_len = curr_len;
}
curr_len = 1;
}
}
/* strndup allocates memory for storing the substring */
return strndup(str + longest_start, *longest_len);
}
It looks like in your loop that j is supposed to be storing where the current "substring" starts, and i is the index of the character that you are currently looking at. In that case, you want to change
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
to
for (i = 0, j = 0; i <= n-1; i++)
That way, you are using i to store which character you're looking at, and the j = i line will "reset" which string of characters you are checking the length of.
Also, a few other things:
1) length = 0 should be *length = 0. You probably don't actually want to set the pointer to point to address 0x0.
2) That last line would return where your "largest substring" starts, but it doesn't truncate where the characters start to change (i.e. the resulting string isn't necessarily *length long). It can be intentional depending on use case, but figured I'd mention it in case it saves some grief.

Resources