Modifying a 2d Array within a recursive function, C - c

I'm trying to recursively modify a 2D char array (array of strings), but after the first recursive call the array returns blank even though the changes register in the base case
int main(int argc, const char * argv[]) {
int height;
printf("Enter the height of your triangle.\n");
scanf("%d", &height);
printf("Lets see if you were successful!\n");
fractalTriangle(height, 1);
}
void fractalTriangle (int height, int fractalLevel) {
//has to make the array and do the printing all in the same function
char trianglePattern [height][2 * height - 1];
if (fractalLevel == 0) {
int rowSize = 2 * height - 1;
char rowString[rowSize]; //string to store in pattern's array
int asteriskCount = 1; //number of asterisks printed in each row
int spaces = (rowSize - asteriskCount) / 2; //how many spaces need to be printed in this current row
int rowCount;
for (rowCount = 0; rowCount < height; rowCount++) {
char *ptr = trianglePattern[rowCount];
int counter = 0;
int astCounter = 0;
int spCounter = 0;
while (spCounter < spaces) {
if (counter == 0) {
strcpy(rowString, " ");
}
else {
strcat(rowString, " ");
}
counter++;
spCounter++;
}
while (astCounter < asteriskCount) {
if (counter == 0) {
strcpy(rowString, "*");
}
else {
strcat(rowString, "*");
}
counter++;
astCounter++;
}
spCounter = 0;
while (spCounter < spaces) {
strcat(rowString, " ");
spCounter++;
}
asteriskCount+=2;
spaces--;
strcpy(ptr, rowString);
//printf("%s\n", trianglePattern[rowCount]);
//printf("%s\n", rowString);
}
}
else {
fractalTriangle(height/2, fractalLevel - 1);
printf("%s\n", trianglePattern[0]);
printf("%s\n", trianglePattern[1]);
printf("%s\n", trianglePattern[2]);
printf("%s\n", trianglePattern[3]);
}
}
Why would the array reset? I can't imagine it'd be a scope issue since the array itself is declared within the function. The purpose is to print a fractal triangle so there's no need to pass a 2D array to the function, I just want to create the pattern recursively. I'm doing this bit by bit (recursion still incomplete)- right now I'm just testing to see whether the array holds from call-to-call.

Since you define the array inside the function scope, each function creates a new 2D character array on the stack. The function will operate on that instance of the 2D character array only. By the time the recursion exists, the original un-modified 2D character array is printed.
You need to define a character array outside of the recursive function, then pass that character array (or rather a pointer to it) into the recursive function.

I don't know what your code is supposed to do, but here's what it does:
Your first (outer) call to the recursive function (from main) is:
fractalTriangle(height, 1);
Inside the function, you skip the first if statement since fractalLevel == 1 and in the else part you call the function again, recursively, with fractalLevel == 0.
That call won't go into another recursive call, and won't print anything.
Once the recursive call returns, back in the first level (the one called from main), execution continues with:
printf("%s\n", trianglePattern[0]);
printf("%s\n", trianglePattern[1]);
printf("%s\n", trianglePattern[2]);
printf("%s\n", trianglePattern[3]);
but trianglePattern was not initialized at all (immediately went into the else part), so you print garbage.

Related

last number in a function array

I want to write a function where I have a given array and number N. The last occurrence of this number I want to return address. If said number cannot be found I want to use a NULL-pointer
Start of the code I've made:
int main(void) {
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
for (int i = 0; i <= 6; i++) {
if (ary[i] == 3) {
printf("%u\n", ary[i]);
}
}
return 0;
}
result in command prompt:
3
3
The biggest trouble I'm having is:
it prints all occurrences, but not the last occurrence as I want
I haven't used pointers much, so I don't understand how to use the NULL-pointer
I see many minor problems in your program:
If you want to make a function, make a function so your parameters and return types are explicit, instead of coding directly in the main.
C arrays, like in most languages, start the indexing at 0 so if there are N element the first has index 0, then the second has 1, etc... So the very last element (the Nth) has index N-1, so in your for loops, always have condition "i < size", not "i <= size" or ( "i <= size-1" if y'r a weirdo)
If you want to act only on the last occurence of something, don't act on every. Just save every new occurence to the same variable and then, when you're sure it was the last, act on it.
A final version of the function you describe would be:
int* lastOccurence(int n, int* arr, int size){
int* pos = NULL;
for(int i = 0; i < size; i++){
if(arr[i] == n){
pos = &arr[i]; //Should be equal to arr + i*sizeof(int)
}
}
return pos;
}
int main(void){
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
printf("%p\n", lastOccurence(3, ary, 6);
return 0;
}
Then I'll add that the NULL pointer is just 0, I mean there is literally the line "#define NULL 0" inside the runtime headers. It is just a convention that the memory address 0 doesn't exist and we use NULL instead of 0 for clarity, but it's exactly the same.
Bugs:
i <= 6 accesses the array out of bounds, change to i < 6.
printf("%u\n", ary[i]); prints the value, not the index.
You don't actually compare the value against n but against a hard-coded 3.
I think that you are looking for something like this:
#include <stdio.h>
int main(void)
{
int n = 3;
int ary[6] = { 1,3,7,8,3,9 };
int* last_index = NULL;
for (int i = 0; i < 6; i++) {
if (ary[i] == n) {
last_index = &ary[i];
}
}
if(last_index == NULL) {
printf("Number not found\n");
}
else {
printf("Last index: %d\n", (int)(last_index - ary));
}
return 0;
}
The pointer last_index points at the last found item, if any. By subtracting the array's base address last_index - ary we do pointer arithmetic and get the array item.
The cast to int is necessary to avoid a quirk where subtracting pointers in C actually gives the result in a large integer type called ptrdiff_t - beginners need not worry about that one, so just cast.
First of all, you will read from out of array range, since your array last element is 5, and you read up to 6, which can lead in segmentation faults. #Ludin is right saying that you should change
for (int i = 0; i <= 6; i++) // reads from 0 to 6 range! It is roughly equal to for (int i = 0; i == 6; i++)
to:
for (int i = 0; i < 6; i++) // reads from 0 to 5
The last occurrence of this number I want to return as address.
You are printing only value of 3, not address. To do so, you need to use & operator.
If said number cannot be found I want to use a NULL-pointer
I don't understand, where do you want to return nullpointer? Main function can't return nullpointer, it is contradictory to its definition. To do so, you need to place it in separate function, and then return NULL.
If you want to return last occurence, then I would iterate from the end of this array:
for (int i = 5; i > -1; i--) {
if (ary[i] == 3) {
printf("place in array: %u\n", i); // to print iterator
printf("place in memory: %p\n", &(ary[i])); // to print pointer
break; // if you want to print only last occurence in array and don't read ruther
}
else if (i == 0) {
printf("None occurences found");
}
}
If you want to return an address you need yo use a function instead of writing code in main
As you want to return the address of the last occurence, you should iterate the array from last element towards the first element instead of iterating from first towards last elements.
Below are 2 different implementations of such a function.
#include <stdio.h>
#include <assert.h>
int* f(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
int* p = a + sz;
do
{
--p;
if (*p == n) return p;
} while(p != a);
return NULL;
}
int* g(int n, size_t sz, int a[])
{
assert(sz > 0 && a != NULL);
// Iterate the array from last element towards first element
size_t i = sz;
do
{
--i;
if (a[i] == n) return &a[i];
} while (i > 0);
return NULL;
}
int main(void)
{
int n = 3;
int ary[] = { 1,3,7,8,3,9 };
size_t elements = sizeof ary / sizeof ary[0];
int* p;
p = g(n, elements, ary); // or p = f(n, elements, ary);
if (p != NULL)
{
printf("Found at address %p - value %d\n", (void*)p, *p);
}
else
{
printf("Not found. The function returned %p\n", (void*)p);
}
return 0;
}
Working on the specified requirements in your question (i.e. a function that searches for the number and returns the address of its last occurrence, or NULL), the code below gives one way of fulfilling those. The comments included are intended to be self-explanatory.
#include <stdio.h>
// Note that an array, passed as an argument, is converted to a pointer (to the
// first element). We can change this in our function, because that pointer is
// passed BY VALUE (i.e. it's a copy), so it won't change the original
int* FindLast(int* arr, size_t length, int find)
{
int* answer = NULL; // The result pointer: set to NULL to start off with
for (size_t i = 0; i < length; ++i) { // Note the use of < rather than <=
if (*arr == find) {
answer = arr; // Found, so set our pointer to the ADDRESS of this element
// Note that, if multiple occurrences exist, the LAST one will be the answer
}
++arr; // Move on to the next element's address
}
return answer;
}
int main(void)
{
int num = 3; // Number to find
int ary[6] = { 1,3,7,8,3,9 }; // array to search
size_t arrlen = sizeof(ary) / sizeof(ary[0]); // Classic way to get length of an array
int* result = FindLast(ary, arrlen, num); // Call the function!
if (result == NULL) { // No match was found ...
printf("No match was found in the array!\n");
}
else {
printf("The address of the last match found is %p.\n", (void*)result); // Show the address
printf("The element at that address is: %d\n", *result); // Just for a verification/check!
}
return 0;
}
Lots of answers so far. All very good answers, too, so I won't repeat the same commentary about array bounds, etc.
I will, however, take a different approach and state, "I want to use a NULL-pointer" is a silly prerequisite for this task serving only to muddle and complicate a very simple problem. "I want to use ..." is chopping off your nose to spite your face.
The KISS principle is to "Keep It Simple, St....!!" Those who will read/modify your code will appreciate your efforts far more than admiring you for making wrong decisions that makes their day worse.
Arrays are easy to conceive of in terms of indexing to reach each element. If you want to train in the use of pointers and NULL pointers, I suggest you explore "linked lists" and/or "binary trees". Those data structures are founded on the utility of pointers.
int main( void ) {
const int n = 3, ary[] = { 1, 3, 7, 8, 3, 9 };
size_t sz = sizeof ary/sizeof ary[0];
// search for the LAST match by starting at the end, not the beginning.
while( sz-- )
if( ary[ sz ] == n ) {
printf( "ary[ %sz ] = %d\n", sz, n );
return 0;
}
puts( "not found" );
return 1; // failed to find it.
}
Consider that the array to be searched is many megabytes. To find the LAST match, it makes sense to start at the tail, not the head of the array.
Simple...

HEAP CORRUPTION DETECTED: after normal block(#87)

I'm trying to do a program that get number of names from the user, then it get the names from the user and save them in array in strings. After it, it sort the names in the array by abc and then print the names ordered. The program work good, but the problem is when I try to free the dynamic memory I defined.
Here is the code:
#include <stdio.h>
#include <string.h>
#define STR_LEN 51
void myFgets(char str[], int n);
void sortString(char** arr, int numberOfStrings);
int main(void)
{
int i = 0, numberOfFriends = 0, sizeOfMemory = 0;
char name[STR_LEN] = { 0 };
char** arrOfNames = (char*)malloc(sizeof(int) * sizeOfMemory);
printf("Enter number of friends: ");
scanf("%d", &numberOfFriends);
getchar();
for (i = 0; i < numberOfFriends; i++) // In this loop we save the names into the array.
{
printf("Enter name of friend %d: ", i + 1);
myFgets(name, STR_LEN); // Get the name from the user.
sizeOfMemory += 1;
arrOfNames = (char*)realloc(arrOfNames, sizeof(int) * sizeOfMemory); // Change the size of the memory to more place to pointer from the last time.
arrOfNames[i] = (char*)malloc(sizeof(char) * strlen(name) + 1); // Set dynamic size to the name.
*(arrOfNames[i]) = '\0'; // We remove the string in the currnet name.
strncat(arrOfNames[i], name, strlen(name) + 1); // Then, we save the name of the user into the string.
}
sortString(arrOfNames, numberOfFriends); // We use this function to sort the array.
for (i = 0; i < numberOfFriends; i++)
{
printf("Friend %d: %s\n", i + 1, arrOfNames[i]);
}
for (i = 0; i < numberOfFriends; i++)
{
free(arrOfNames[i]);
}
free(arrOfNames);
getchar();
return 0;
}
/*
Function will perform the fgets command and also remove the newline
that might be at the end of the string - a known issue with fgets.
input: the buffer to read into, the number of chars to read
*/
void myFgets(char str[], int n)
{
fgets(str, n, stdin);
str[strcspn(str, "\n")] = 0;
}
/*In this function we get array of strings and sort the array by abc.
Input: The array and the long.
Output: None*/
void sortString(char** arr, int numberOfStrings)
{
int i = 0, x = 0;
char tmp[STR_LEN] = { 0 };
for (i = 0; i < numberOfStrings; i++) // In this loop we run on all the indexes of the array. From the first string to the last.
{
for (x = i + 1; x < numberOfStrings; x++) // In this loop we run on the next indexes and check if is there smaller string than the currnet.
{
if (strcmp(arr[i], arr[x]) > 0) // If the original string is bigger than the currnet string.
{
strncat(tmp, arr[i], strlen(arr[i])); // Save the original string to temp string.
// Switch between the orginal to the smaller string.
arr[i][0] = '\0';
strncat(arr[i], arr[x], strlen(arr[x]));
arr[x][0] = '\0';
strncat(arr[x], tmp, strlen(tmp));
tmp[0] = '\0';
}
}
}
}
After the print of the names, when I want to free the names and the array, in the first try to free, I get an error of: "HEAP CORRUPTION DETECTED: after normal block(#87)". By the way, I get this error only when I enter 4 or more players. If I enter 3 or less players, the program work properly.
Why does that happen and what I should do to fix it?
First of all remove the unnecessary (and partly wrong) casts of the return value of malloc and realloc. In other words: replace (char*)malloc(... with malloc(..., and the same for realloc.
Then there is a big problem here: realloc(arrOfNames, sizeof(int) * sizeOfMemory) : you want to allocate an array of pointers not an array of int and the size of a pointer may or may not be the same as the size of an int. You need sizeof(char**) or rather the less error prone sizeof(*arrOfNames) here.
Furthermore this in too convoluted (but not actually wrong):
*(arrOfNames[i]) = '\0';
strncat(arrOfNames[i], name, strlen(name) + 1);
instead you can simply use this:
strcpy(arrOfNames[i], name);
Same thing in the sort function.
Keep your code simple.
But actually there are more problems in your sort function. You naively swap the contents of the strings (which by the way is inefficient), but the real problem is that if you copy a longer string, say "Walter" into a shorter one, say "Joe", you'll write beyond the end of the allocated memory for "Joe".
Instead of swapping the content of the strings just swap the pointers.
I suggest you take a pencil and a piece of paper and draw the pointers and the memory they point to.

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 '_';
}

Filling in a String using sprintf, C

I'm trying to create an array of patterns for a triangle that I'm also printing to the console. I do this by creating a 2d char array where
char patterns [number_of_patterns][pattern_lengths]. I pass this to a function that takes the array patterns along with the height of the triangle I'm trying to make.
void printTriangle (int rows, char rowPatterns[][rows]) {
int initialSpaces = rows - 1;
int numberOfAsterisks = 1;
int i;
for (i = 0; i < rows; i++) {
char temp[rows];
int spaceCounter = 0;
int asteriskCounter = 0;
while (spaceCounter < initialSpaces) {
printf(" ");
sprintf(temp, " ");
spaceCounter++;
}
while (asteriskCounter < numberOfAsterisks) {
sprintf(temp, "*");
printf("*");
asteriskCounter++;
}
while (spaceCounter < initialSpaces) {
spaceCounter = 0;
sprintf(temp, " ");
spaceCounter++;
}
strcpy(rowPatterns[i], temp);
printf("\n");
initialSpaces--;
numberOfAsterisks+=2;
}
}
For every row of the triangle that I'm printing, I create a string for that row called temp. At the end of the for loop that prints the row to the console and sprintf's it to the array temp, I strcpy temp into patterns[i]. Then I go back to the top of the loop, reinitialize temp to make it fresh, and loop again until I have all my rows. Except for some reason sprint won't fill in my array temp. Is this incorrect use of the function, or does it have to do w my parameter passing?
sprintf always writes to the start of the string. To append, you can maintain a pointer to the end of the string:
char *ptr = rowpatterns[i];
ptr += sprintf(ptr, "*");
You might also hear the suggestion to use strcat - avoid that function. When building strings, repeated strcat is very slow and is a common source of performance issues in string code.

Reading correctly from a 2D char array in a function

I canĀ“t read from the char array
This is how I pass the string into my array for each test case and that works fine but passing the array is a problem. I looked it up here: Passing arrays and matrices to functions as pointers and pointers to pointers in C
I still get the warning that I compare between a pointer and an integer.
char klammern[MAX][STRING];
int i, test;
int ergebnis;
printf(" Test cases?:");
scanf("%d",&test);
getchar(); //catch Enter
for(i=0;i<test;i++)
{
fgets(klammern[i],30,stdin);
}
Here is how I pass the argument:
for(i=0;i<test;i++)
{
ergebnis = matching_brackets( klammern );
printf("%d ",ergebnis);
}
My function should count the numbers of brackets and return 1 if not all brackets are closed and 0 if everything is correct.
int matching_brackets(char (*klammern)[STRING])
{
int ergebnis, i;
int runde_klammern = 0;
for(i=0; *klammern[i] != '\n';i++)
{
if( *klammern[i] == '(')
{
runde_klammern++;
}
else if( *klammern[i] == ')')
{
runde_klammern--;
}
ergebnis = runde_klammern;
if ( ergebnis != 0)
{
return 1;
}
else
{
return 0 ;
}
While testing I saw that my for loop in the function read my array like this:
array [1][0]
array [2][0]
...
I want to loop the array like:
array[0][0]
array[0][1]
...
Edit: I do not get the compiler warning anymore after I fixed a typo in my function.
You have two problems, one is that your loop is wrong and the other is an operator precedence problem.
You should loop like e.g.
for (size_t i = 0; i < test; ++i)
{
for (size_t j = 0; klamern[i][j] != '\n'; ++j)
{
// Here `klamern[i][j]` is the current character
}
}
Note that you need to pass the test variable to the function as well.
The above loops also removes the second problem. (that *klamern[i] is seen by the compiler as *(klamern[i]) and not (*klamern)[i]).

Resources