C: Printing every possible string starting with 'a', recursive functions - c

I want to create a program that prints every possible string starting with the character 'a' with an arbitrary maximum length. For this example we'll use a maximum length of 4. A recursive function seemed like a good way to handle this however I'm really confused now as to why the recursive function won't print for example "ab"? It seems like the loop doesn't continue after recursive is called again.
int main ()
{
char *str = malloc(5* sizeof(char));
str[0] = 'a';
recursive(str, 1);
}
void recursive(char *string, int index)
{
// Max length of 4
if (index > 3)
return;
for(char c = 'a'; c <= 'j'; c++)
{
string[index] = c;
printf("str: %s\n", string);
recursive(string, index + 1);
}
}
While the result is close to what I want, notice that there's no "ab", "ac", "abc", "acb", basically any string of length 2 or 3 (other than aa/aaa). Every combination of length 4 (maximum) is getting printed though.
Any way to solve this? Thanks!

There's nothing wrong with your algorithm or recursion. The only thing you need is to shorten your string after your recursion step finishes (strings are ASCIIZ in C).
The fix is simple: you need to ensure there are zeroes in your allocated memory block, which is done by clearing its contents using memset (memory block whose pointer is returned by malloc contains garbage).
int main ()
{
size_t size = 5;
char* str = (char*)malloc(size);
memset(str, 0, size);
str[0] = 'a';
recursive(str, 1);
}
And then in your loop:
for (char c = 'a'; c <= 'j'; c++)
{
string[index] = c;
printf("str: %s\n", string);
recursive(string, index + 1);
string[index] = 0; // <-- revert last letter to zero
}

Related

Printing a reversed string/array in C

I'm trying to print a reversed string/array. I've used the following code and it seems to be able to give my second array, revString, values in the correct order from the first array string. I am also able to print individual characters in both arrays, and I'm able to print the entire string of the first array. However the revString array doesn't print at all. I'm wondering if I am missing a huge point here.
void reverseString(char string[]) {
int i = strlen(string);
int i_2 = 0;
revString arrayet
char revString[i + 1];
char *character;
while (i > -1) {
character = &string[i];
revString[i_2] = *character;
printf("%c", revString[i_2]);
i = i - 1;
i_2 = i_2 + 1;
}
revString[i_2] = '\0';
printf("%d\n", i_2);
printf("%s", revString);
}
The code gives now the following output with example string "Hello World";
dlrow olleH13
As you can see the final printf statement doesn't do anything
In C language indexing is 0 based. so, if you make a string of 10 length, the last character will be at index 9.
In your code, when you are assigning characters to revString, your code is trying to access string[len].
your code should be like this..
int i = strlen(string) - 1;
Your code reverses the string string including the null terminator at string[i]. The resulting array starts with a null terminator, hence printf outputs nothing.
Here is a modified version:
void reverseString(char string[]) {
int i = strlen(string);
int i_2 = 0;
char revString[i + 1];
char character;
while (i > 0) {
i = i - 1;
character = string[i];
revString[i_2] = character;
//printf("%c", revString[i_2]);
i_2 = i_2 + 1;
}
revString[i_2] = '\0';
printf("%d\n", i_2);
printf("%s", revString);
}
Output:
11
dlrow olleH

Design a Character Searching Function, While Forced to Use strchr

Background Information
I was recently approached by a friend who was given a homework problem to develop a searching algorithm. Before anyone asks, I did think of a solution! However, my solution is not what the teacher is asking for...
Anyway, this is an introductory C programming course where the students have been asked to write a search function called ch_search that is supposed to search an array of characters to determine how many times a specific character occurs. The constraints are what I don't understand...
Constraints:
The arguments are: array to search, character to search for, and length of the array being searched.
The function must use a for-loop.
The algorithm must use the strchr function.
Okay, so the first two constraints I can understand... but the 3rd constraint is what really gets me... I was initially thinking that we could just use a for-loop to iterate through the string from the beginning to the end, simply counting each instance of the character. When the student originally described the problem to me, I came up with (although incorrect) the solution:
Proposed Solution
int ch_search(char array_to_search[], char char_to_search_for, int array_size)
{
int count = 0;
for (int i = 0; i < array_size; i++)
{
// count each character instance
if (array_to_search[i] == char_to_search_for)
{
// keep incrementing the count
count++;
}
}
return count;
}
Then I was told that I had to specifically use the character position function (and apparently it has to be strchr and not strrchr so we can't start at the end I guess?)... I just don't see how that wouldn't be overcomplicating this. I don't see how that would help at all, especially counting from the beginning... Even strrchr might make a little more sense to me. Thoughts?
It's true that having the length of the array and having to use a for loop,
the most natural thing to do would be to iterate over every characters of the
source array. But you can also loop over the result of strchr like this:
int ch_search(char haystack[], char needle, int size)
{
int count = 0;
char *found;
for(; (found = strchr(haystack, needle)) != NULL; haystack = found + 1)
count++;
return count;
}
In this case you don't need the size of the array but the assignment doesn't say
that you have to use it. Obviously this solution requires the source to be '\0'-terminated.
I think the teacher wanted you to use strchr to navigate to the next occurrence of the char_to_search_for within a string:
int ch_search(char array_to_search[], char char_to_search_for, int array_size) {
int count = 0;
for (char *ptr = array_to_search ; ptr != &array_to_search[array_size] ; ptr++) {
ptr = strchr(ptr, char_to_search_for);
if (!ptr) {
break; // Character is not found
}
count++;
}
return count;
}
Note that array_to_search must be null-terminated in order to be used together with strchr solution above.
This sounds like your friend was given a trick question. The function gets an array of chars and the length of that array but is required to use strchr() even though that function only works on '\0' terminated strings (and there was not given any guaranty that the array is '\0' terminated).
You might thing that it would be fine to use strchr() on the array anyway and then compare the returned pointer to the given length of the array to check if it went past the end of the array. But there are two problems with that:
If strchr() searches past the end of the array, then you already have Undefined Behavior before getting to the check. The program might have crashed before returning from strchr(), the returned pointer might be some total garbage or you might get a pointer to an address a bit further in memory than the end of the array.
Even if the returned pointer is just to an address a bit further in memory than the end of the array, then there is the problem that comparing two pointers (or subtracting them to find the distance between the pointed addresses) is Undefined Behavior unless they're both pointing to parts of the same memory object (or one position past the end of the object). In this instance it means that checking if the returned pointer is within the bounds of the array is only defined behavior if the returned pointer is within the bounds of the array (or one past the end) making the check a bit useless.
The only solution to that is to make sure that strchr() is working with a '\0' terminated string. For example:
int ch_search(char array_to_search[], char char_to_search_for, int array_size)
{
char *buffer = malloc(array_size + 1);
// Add test here to check if malloc was succesful
strncpy(buffer, array_to_search, array_size);
buffer[array_size] = '\0';
int count = 0;
for (char *i = buffer; (i = strchr(i, char_to_search_for)) != NULL; i++) {
count++;
}
free(buffer);
return count;
}
strchr is a very convenient function to search for a char in a string.
Find and read more about strchr. This is my favorite function ever!
The C library function char *strchr(const char *str, int c) searches for the first occurrence of the character c (an unsigned char) in the string pointed to by the argument str.
Declaration
Following is the declaration for strchr() function.
char *strchr(const char *str, int c)
Parameters
str − This is the C string to be scanned.
c − This is the character to be searched in str.
Return value
Function returns a pointer to the first occurrence of the character c in the string str, or NULL if the character is not found.
Constraints:
1) The arguments are: array to search, character to search for, and
length of the array being searched.
This constrain gives the length of the array to be searched. The given array has to contain '\0' at some point. However the length of search search can be shorter and specified by the search_length.
Following compact solution takes this under account.
int ch_search(char array_to_search[], char char_to_search_for, int search_length)
{
int count = 0;
for(char *p = array_to_search; ;p++)
{
p = strchr(p, char_to_search_for);
if( p != NULL && (p - array_to_search < search_length) )
count++;
else
break;
}
return count;
}
Or equivalent ch_search2:
#include<stdio.h>
#include<string.h>
int ch_search(char array_to_search[], char char_to_search_for, int search_length)
{
int count = 0;
for(char *p = array_to_search; ;p++)
{
p = strchr(p, char_to_search_for);
if( p != NULL && (p - array_to_search < search_length) )
count++;
else
break;
}
return count;
}
// Your original function:
int ch_search1(char array_to_search[], char char_to_search_for, int array_size)
{
int count = 0;
for (int i = 0; i < array_size; i++){
// count each character instance
if (array_to_search[i] == char_to_search_for){
count++; // keep incrementing the count
}
}
return count;
}
int ch_search2(char array_to_search[], char char_to_search_for, int array_size)
{
int count = 0;
char *p = array_to_search;
for(;;)
{
p = strchr(p, char_to_search_for);
if( p != NULL )
{
if (p - array_to_search >= array_size) // we reached beyond
{
break;
}
else
{
count++;
p++;
}
}
else
break; // char not found
}
return count;
}
int main(void)
{
// the arr has to contain '\0' terminator but we can search within the specified length.
char arr[]={'1','1','2','2','1','1','3','3','3','1','4','4', '1','1','!','1','\0','1'};
char arr1[] = "zdxbab";
printf("count %d count %d \n",ch_search(arr , '1', 12),ch_search2(arr , '1', 12));
printf("count %d count %d \n",ch_search(arr1,'b',strlen(arr1)),ch_search2(arr1,'b',strlen(arr1)));
return 0;
}
Output:
count 5 count 5
count 2 count 2

First Not Repeating Character Code

Here is the question:
Write a solution that only iterates over the string once and uses O(1) additional memory, since this is what you would be asked to do during a real interview.
Given a string s, find and return the first instance of a non-repeating character in it. If there is no such character, return '_'.
And here is my code:
char firstNotRepeatingCharacter(char * s) {
int count;
for (int i=0;i<strlen(s);i++){
count=0;
char temp=s[i];
s[i]="_";
char *find= strchr(s,temp);
s[i]=temp;
if (find!=NULL) count++;
else return s[i];
}
if (count!=0) return '_';
}
I dont know what's wrong but when given an input:
s: "abcdefghijklmnopqrstuvwxyziflskecznslkjfabe"
the output is for my code is "g" instead of "d".
I thought the code should have escaped the loop and return "d" soon as "d" was found.
Thx in advance!!!
In your program, problem is in this statement-
s[i]="_";
You are assigning a string to a character type variable s[i]. Change it to -
s[i]='_';
At the bottom of your firstNotRepeatingCharacter() function, the return statement is under the if condition and compiler must be giving a warning for this as the function is supposed to return a char. Moreover, count variable is not needed. You could do something like:
char firstNotRepeatingCharacter(char * s) {
for (int i=0;i<strlen(s);i++){
char temp=s[i];
s[i]='_';
char *find= strchr(s,temp);
s[i]=temp;
if (find==NULL)
return s[i];
}
return '_';
}
But this code is using strchr inside the loop which iterates over the string so, this is not the exact solution of your problem as you have a condition that - the program should iterates over the string once only. You need to reconsider the solution for the problem.
May you use recursion to achieve your goal, something like - iterate the string using recursion and, somehow, identify the repetitive characters and while the stack winding up identify the first instance of a non-repeating character in the string. It's implementation -
#include <stdio.h>
int ascii_arr[256] = {0};
char firstNotRepeatingCharacter(char * s) {
char result = '-';
if (*s == '\0')
return result;
ascii_arr[*s] += 1;
result = firstNotRepeatingCharacter(s+1);
if (ascii_arr[*s] == 1)
result = *s;
return result;
}
int main()
{
char a[] = "abcdefghijklmnopqrstuvwxyziflskecznslkjfabe";
printf ("First non repeating character: %c\n", firstNotRepeatingCharacter(a));
return 0;
}
In the above code, firstNotRepeatingCharacter() function iterates over the string only once using recursion and during winding up of the stack it identifies the first non-repetitive character. I am using a global int array ascii_arr of length 256 to keep the track of non-repetitive character.
Java Solution:
Time Complexity: O(n)
Space Complexity: with constant space as it will only use more 26 elements array to maintain count of chars in the input
Using Java inbuilt utilities : but for inbuilt utilities time complexity is more than O(n)
char solution(String s) {
char[] c = s.toCharArray();
for (int i = 0; i < s.length(); i++) {
if (s.indexOf(c[i]) == s.lastIndexOf(c[i]))
return c[i];
}
return '_';
}
Using simple arrays. O(n)
char solution(String s) {
// maintain count of the chars in a constant space
int[] base = new int[26];
// convert string to char array
char[] input = s.toCharArray();
// linear loop to get count of all
for(int i=0; i< input.length; i++){
int index = input[i] - 'a';
base[index]++;
}
// just find first element in the input that is not repeated.
for(int j=0; j<input.length; j++){
int inputIndex = input[j]-'a';
if(base[inputIndex]==1){
System.out.println(j);
return input[j];
}
}
return '_';
}

Why is both my input array and output array corrupted when I try to implement a function to reverse the array?

I'm Programming in C, using Linux GCC Compiler. I'm very much new to programming.
I'm confused as to why my in[] char array would be changed at all in the function. Doesn't the code simply count the amount of subscripts in in[] and then copy its contents into out[] but backwards? How is it being changed in the function?
/*reverse in to out*/
void reverse(char in[], char out[]) {
int i, l,b;
b = i = l = 0;
while (in[i] != '\0')
++i;
for(l=i;l > 0; l--) {
in[l] = out[b];
++b;
}
return;
}
Your assignment statement is backwards.
in[l] = out[b];
Means "Assign the value in array out at index b to array in index l". This line should instead be
out[b] = in[l];
And BTW, you don't need an empty return statement, you can simply omit this in a void function.
for(l=i-1;l >= 0; l--) {
out[b] = in[l];
++b;
}
out[b] = '\0';
Four problems fixed: start at i-1, test for l>=0, reverse the assignment, and terminate out with a null character.
Also, a good idea is to use const when a function argument will not be changed. In this case, const char in[] would let you spot the assignment error because the compiler would give you a compile time error.
You can use strlen :
for(l=strlen(in), b=0; l>=0; l--)
out[b++] = in[l];
// ensure null terminated so strlen out works
out[b] = '\0';
This assumes out is wide enough for in AND in is null terminated

pointers and string parsing in c

I was wondering if somebody could explain me how pointers and string parsing works. I know that I can do something like the following in a loop but I still don't follow very well how it works.
for (a = str; * a; a++) ...
For instance, I'm trying to get the last integer from the string. if I have a string as const char *str = "some string here 100 2000";
Using the method above, how could I parse it and get the last integer of the string (2000), knowing that the last integer (2000) may vary.
Thanks
for (a = str; * a; a++) ...
This works by starting a pointer a at the beginning of the string, until dereferencing a is implicitly converted to false, incrementing a at each step.
Basically, you'll walk the array until you get to the NUL terminator that's at the end of your string (\0) because the NUL terminator implicitly converts to false - other characters do not.
Using the method above, how could I parse it and get the last integer of the string (2000), knowing that the last integer (2000) may vary.
You're going to want to look for the last space before the \0, then you're going to want to call a function to convert the remaining characters to an integer. See strtol.
Consider this approach:
find the end of the string (using that loop)
search backwards for a space.
use that to call strtol.
-
for (a = str; *a; a++); // Find the end.
while (*a != ' ') a--; // Move back to the space.
a++; // Move one past the space.
int result = strtol(a, NULL, 10);
Or alternatively, just keep track of the start of the last token:
const char* start = str;
for (a = str; *a; a++) { // Until you hit the end of the string.
if (*a == ' ') start = a; // New token, reassign start.
}
int result = strtol(start, NULL, 10);
This version has the benefit of not requiring a space in the string.
You just need to implement a simple state machine with two states, e.g
#include <ctype.h>
int num = 0; // the final int value will be contained here
int state = 0; // state == 0 == not parsing int, state == 1 == parsing int
for (i = 0; i < strlen(s); ++i)
{
if (state == 0) // if currently in state 0, i.e. not parsing int
{
if (isdigit(s[i])) // if we just found the first digit character of an int
{
num = s[i] - '0'; // discard any old int value and start accumulating new value
state = 1; // we are now in state 1
}
// otherwise do nothing and remain in state 0
}
else // currently in state 1, i.e. parsing int
{
if (isdigit(s[i])) // if this is another digit character
{
num = num * 10 + s[i] - '0'; // continue accumulating int
// remain in state 1...
}
else // no longer parsing int
{
state = 0; // return to state 0
}
}
}
I know this has been answered already but all the answers thus far are recreating code that is available in the Standard C Library. Here is what I would use by taking advantage of strrchr()
#include <string.h>
#include <stdio.h>
int main(void)
{
const char* input = "some string here 100 2000";
char* p;
long l = 0;
if(p = strrchr(input, ' '))
l = strtol(p+1, NULL, 10);
printf("%ld\n", l);
return 0;
}
Output
2000
for (a = str; * a; a++)...
is equivalent to
a=str;
while(*a!='\0') //'\0' is NUL, don't confuse it with NULL which is a macro
{
....
a++;
}
The loop you've presented just goes through all characters (string is a pointer to the array of 1-byte chars that ends with 0). For parsing you should use sscanf or better C++'s string and string stream.

Resources