exercism Isogram challenge in C track - running locally but not in exercism - c

So I recently started with C at exercism page.
I currently facing a rather simple challenge.
Determine if a word or phrase is an isogram.
An isogram (also known as a "non-pattern word") is a word or phrase without a repeating letter, however spaces and hyphens are allowed to appear multiple times.
Examples of isograms:
lumberjacks
background
downstream
six-year-old
The word isograms, however, is not an isogram, because the s repeats.
There are 15 tests in total, of which one specific is not passed:
test_isogram_with_duplicated_hyphen
I guess test number 15 also passes because of some error I don't see
Here's the testing code:
#include "test-framework/unity.h"
#include "isogram.h"
#include <stdlib.h>
void setUp(void)
{
}
void tearDown(void)
{
}
static void test_empty_string(void)
{
TEST_ASSERT_TRUE(is_isogram(""));
}
static void test_null(void)
{
TEST_IGNORE(); // delete this line to run test
TEST_ASSERT_FALSE(is_isogram(NULL));
}
static void test_isogram_with_only_lower_case_characters(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("isogram"));
}
static void test_word_with_one_duplicated_character(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("eleven"));
}
static void test_word_with_one_duplicated_character_from_end_of_alphabet(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("zzyzx"));
}
static void test_longest_reported_english_isogram(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("subdermatoglyphic"));
}
static void test_word_with_duplicated_letter_in_mixed_case(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("Alphabet"));
}
static void test_word_with_duplicated_letter_in_mixed_case_lowercase_first(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("alphAbet"));
}
static void test_hypothetical_isogrammic_word_with_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("thumbscrew-japingly"));
}
static void
test_hypothetical_word_with_duplicated_character_following_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("thumbscrew-jappingly"));
}
static void test_isogram_with_duplicated_hyphen(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("six-year-old"));
}
static void test_made_up_name_that_is_an_isogram(void)
{
TEST_IGNORE();
TEST_ASSERT_TRUE(is_isogram("Emily Jung Schwartzkopf"));
}
static void test_duplicated_character_in_the_middle(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("accentor"));
}
static void test_same_first_and_last_characters(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("angola"));
}
static void test_word_with_duplicated_character_and_with_two_hyphens(void)
{
TEST_IGNORE();
TEST_ASSERT_FALSE(is_isogram("up-to-date"));
}
int main(void)
{
UnityBegin("test_isogram.c");
RUN_TEST(test_empty_string);
RUN_TEST(test_null);
RUN_TEST(test_isogram_with_only_lower_case_characters);
RUN_TEST(test_word_with_one_duplicated_character);
RUN_TEST(test_word_with_one_duplicated_character_from_end_of_alphabet);
RUN_TEST(test_longest_reported_english_isogram);
RUN_TEST(test_word_with_duplicated_letter_in_mixed_case);
RUN_TEST(test_word_with_duplicated_letter_in_mixed_case_lowercase_first);
RUN_TEST(test_hypothetical_isogrammic_word_with_hyphen);
RUN_TEST(test_hypothetical_word_with_duplicated_character_following_hyphen);
RUN_TEST(test_isogram_with_duplicated_hyphen);
RUN_TEST(test_made_up_name_that_is_an_isogram);
RUN_TEST(test_duplicated_character_in_the_middle);
RUN_TEST(test_same_first_and_last_characters);
RUN_TEST(test_word_with_duplicated_character_and_with_two_hyphens);
return UnityEnd();
}
This is my code:
#include "isogram.h"
#include <stdlib.h>
#include <stdio.h>
/* gives new char array from input, only small letters */
char* clean_words(char* ptr_input)
{
// new container; everything bigger than 27 is impossible to be an isogram
static char cleaned[27] = {"00000000000000000000000000"};
int i = 0, j = 0, k = 0;
for (int i = 0; ptr_input[i] != '\000'; i++)
{
k++;
}
for (i=0; i <= k; i++, j++)
{
if (ptr_input[i] > 64 && ptr_input[i] < 91)
{
cleaned[j] = ptr_input[i] + 32;
}
else if (ptr_input[i] > 96 && ptr_input[i] < 123)
{
cleaned[j] = ptr_input[i];
}
else
{
j--;
}
}
char* ptr_output = &cleaned[0];
return ptr_output;
}
bool is_isogram(char phrase[])
{
if(phrase == NULL)
{ return false; }
char* ptr_a = clean_words(phrase);
char ca_empty[27] = {"00000000000000000000000000"};
for(int i = 0; i <= 27; i++, ptr_a++){
// first element is always copied
if(i == 0){
ca_empty[i] = *ptr_a;
continue;
}
// '0' is sentinel, meaning the input word is finished => exit loop.
if(*ptr_a == '0' || *ptr_a == '\000')
{ break; }
// following elements only copied if different than current input char
int j = 0;
// loop copied for doubles, exit when found
for(;j<i;j++)
{
if(ca_empty[j] == *ptr_a){
return false;
}
}
// if none was found, copy new letter
ca_empty[i] = *ptr_a;
}
return true;
}
So basically I solve this in 2 steps. First, I will reduce any input to small letters only. Second, I copy letter by letter to a new container and test doubles before every copy process.
Yes, there are certainly fancier solutions, but I'd like to know if anyone can spot why I get FAILED on "six-year-old". Especially, when it is working locally. Thanks! :-)

So I figured it out by myself:
The problem is the helper function clean_words.
The char array cleaned is declared as static. That means it will keep its value even after the current block is finished.
When the tests run through, cleaned will still contain remaining letters of the input from other tests. The solution would be removing the static keywird or implementing a way to clean up the container, like
memset(cleaned, '0', 26);
From https://en.cppreference.com/w/c/language/storage_duration
static storage duration.
The storage duration is the entire execution of the program, and the value stored in the object is initialized only once, prior to main function. All objects declared static and all objects with either internal or external linkage that aren't declared _Thread_local (since C11) have this storage duration.

Related

Reuseable function for looping [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
Question:
I want to create a reusable function, because in my code much line that use same code structure
The code using for example if { if { `Only here's the different` } }. Of course the pattern not same as this, this using as an example.
I've been code using framework such as Laravel, there's a directive called as SLOT
Is there any way I can inject code in the middle of for loop? Or anything same as SLOT inside C programming
Sample code:
void functionname() {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
CODE INJECT HERE
}
}
}
Forget to mention before, a, b, c and so on from the coding above is getting from ITEM (i)
You should use a callback. i.e. you should send a function pointer (i.e. the address of the function you want to execute) and use that pointer to execute that function inside your loop.
In the example below, p is a pointer to a function taking a const char * for a parameter and returning an int.
int (*p)(const char *s) ;
NB: all functions passed as parameter, to be used as callback must have the same prototype (which is why such functions are often declared taking a generic pointer parameter void * to accept whatever you've got to send to the function).
So with your example and with functions taking void * as a parameter and returning void *, and with param defining a parameter that you want to feed to your function, this gives us the following code:
void functionname(void *(*func)(void *)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
func(&param);
}
}
}
you can call your function wiht whatever function respecting the prototype... For instance:
void *my_custom_function(void *param) {
...
}
...
functionname(my_custom_function);
...
As suggested in the comment by KamilCik, use function pointers:
void functionname(void *fx)(void)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
//CODE INJECT HERE
fx();
}
}
}
And use it like
void foo(void) { puts("foo() called"); }
void bar(void) { puts("bar() called"); }
int main(void) {
functionname(foo);
functionname(bar);
}
For a concrete example:
#include <stdio.h>
int a = 1;
int b = 2;
typedef void (*selector)(int, int *);
typedef void (*injector)(void);
void select1(int x, int *c) { printf("%s: %d\n", __func__, *c = x); }
void select2(int x, int *c) { printf("%s: %d\n", __func__, *c = x); }
void inject1(void) { printf("%s\n", __func__); }
void inject2(void) { printf("%s\n", __func__); }
void
functionname(size_t total_count, selector SELECT_THE_ITEM,
injector CODE_INJECT_HERE )
{
for (size_t i=0; i < total_count; i++) {
int c;
SELECT_THE_ITEM (i, &c);
if (a == b) return;
if (c) {
CODE_INJECT_HERE();
}
}
}
int
main(void)
{
functionname(2, select1, inject1);
functionname(3, select2, inject2);
}
You can do what you ask by defining your "CODE INJECT HERE" as the body of a function, and passing a pointer to that function:
void functionname(void (*inject)(void)) {
for (int i=0; i < total_count; i++) {
SELECT THE ITEM (i)
if (a == b) return;
if (c) {
inject();
}
}
}
void do_something(void) {
CODE INJECT HERE
}
void do_something_else(void) {
OTHER CODE INJECT HERE
}
int main(void) {
functionname(do_something));
functionname(do_something_else));
}
Do note, however, that this is not simple code injection in the same sense as a macro would provide. In particular, the executions of do_something() and do_something_else() will not see the local variables of main() or of functionname(), and the do_* functions can return only from themselves, not from a caller further up the chain. The former can be mitigated to some extent by passing parameters to the do_* functions (which they must be prepared to accept).
Another alternative would be to use a macro instead of a function to provide the common framework. It would look something like this:
#define frame_it(x) do { \
for (int i=0; i < total_count; i++) { \
SELECT THE ITEM (i) \
if (a == b) return; \
if (c) { \
x \
} \
} \
} while (0)
int main(void) {
frame_it(
CODE INJECT HERE
);
frame_it(
OTHER CODE INJECT HERE
);
}
That keeps the CODE INJECT HERE code in the function using it, which might be advantageous if in fact each such piece of code is used in only one place. It also allows both that code and the framing code to access the local variables of the function in which they appear, and to return from that function if desired.
However, macro programming has earned a mostly-deserved reputation for being error prone and difficult to read and debug. Your particular need may be one that is well served by this approach, but do not choose this direction lightly.
Function pointers are great for this. You can typedef the function signatures you'd like to support. Example:
/* A signature for condition checking functions, taking a "void*" argument
and returning true or false */
typedef bool(*cond_check_t)(void*);
/* A signature for functions to execute if a condition is met. This takes a
"void*" argument but you decide what you need */
typedef void(*exec_t)(void*);
You can package these two in a struct to form a nice pair:
typedef struct {
cond_check_t checker;
exec_t executor;
} check_exec_t;
And with that, another struct to keep a bunch of these condition and executor pairs:
typedef struct {
size_t size;
size_t capacity;
check_exec_t *conditionals;
} cond_pack_t;
You then create support functions for adding checkers and executors and a function to processes one of these packaged checkers and executors.
cond_pack_t* cond_pack_create(size_t capacity) {
cond_pack_t* cp = malloc(sizeof(*cp));
if(cp) {
cp->conditionals = malloc(sizeof(*cp->conditionals) * capacity);
if(cp->conditionals) {
cp->size = 0;
cp->capacity = capacity;
} else {
free(cp);
cp = NULL;
}
}
return cp;
}
void cond_pack_destroy(cond_pack_t *cp) {
free(cp->conditionals);
free(cp);
}
bool cond_pack_add(cond_pack_t *cp, cond_check_t checker, exec_t executor) {
if(cp->size == cp->capacity) return false;
cp->conditionals[cp->size].checker = checker;
cp->conditionals[cp->size].executor = executor;
++cp->size;
return true;
}
void cond_pack_process(cond_pack_t *cp) {
for(size_t i = 0; i < cp->size; ++i) {
if(cp->conditionals[i].checker(NULL)) { /* execute checker */
cp->conditionals[i].executor(NULL); /* execute executor */
}
}
}
With that, a usage example could look like this
//---
bool some_check(void *foo) {
return true;
}
void some_executor(void *foo) {
printf("some_executor\n");
}
bool some_other_check(void *foo) {
return false;
}
void some_other_executor(void *foo) {
printf("some_other_executor\n");
}
int main() {
cond_pack_t *cp = cond_pack_create(10);
if(cp) {
cond_pack_add(cp, some_check, some_executor);
cond_pack_add(cp, some_other_check, some_other_executor);
cond_pack_process(cp); /* run all the checkers / executors */
cond_pack_destroy(cp);
}
}
Demo

how to remove certain words from a line of text in c

I got my code working to an extent, but I need some more help. If I needed to remove the word "an", from sentence: "I ate an apple whilst looking at an ape.", it only removes the first "an" and not the second, how do I repeat the loop so it deletes all "an"s? I need the final sentence, after the code has been ran, to be: "I ate apple whilst looking at ape.". That is the goal im trying to achieve
Sorry for not including the code.
Here it is:
#include "RemoveFromText.h"
#include <stdlib.h>
#include <string.h>
int findFirstSubstring(char textToChange[], char removeThis[])
{
int size = strlen(textToChange);
int subStringLength = strlen(removeThis);
for(int i=0; i<size; i++)
{
if(textToChange[i] == removeThis[0])
{
int j = 0;
while(textToChange[i+j] == removeThis[j])
{
j++;
if(j==subStringLength)
{
return i;
}
}
}
}
return -1;
}
void removeFromText( char textToChange[], char removeThis[])
{
int textLength = strlen(textToChange);
if(findFirstSubstring(textToChange, removeThis) >= 0)
{
int subStringIdx = findFirstSubstring(textToChange, removeThis);
int loopVariabele = 0;
for(loopVariabele = subStringIdx; loopVariabele<textLength; loopVariabele++)
{
textToChange[loopVariabele] = textToChange[loopVariabele + strlen(removeThis)];
}
}
}
Leveraging 'strstr', and 'memmove' standard "C" library functions
// Remove all occurences of 'source' from 'message'.
void removeAll(char *message, char *source)
{
int len = strlen(source) ;
for (char *x = message ; x=strstr(x, source) ; ) {
// Copy everything after 'source', including terminating nul.
memmove(x, x+len, strlen(x+len)+1) ;
} ;
}
Notes:
that solution that not properly address the trailing space(s) after a word. This can be addressed by chaning the 'memmove'.
Probably make sense to make the function return the number of substitutions, or some other meaningful result

Unexpected behavior in C

This is the question I'm working on : http://www.geeksforgeeks.org/recursively-remove-adjacent-duplicates-given-string/
Here's my code in Java for one pass :
/*If a character isn't repeating, copy it to str[j].
* Find start and end indices of repeating characters. Recursively call again
* And starting position now should be end+1. Pass j and starting position */
public class removeDuplicates {
public static void main(String[] args)
{
char[] str = {'c','c'};
removeDups(str,0,0,0);
System.out.println(str);
}
public static void removeDups(char[] str,int j, int start,int flag)
{
/*Check if start character is repeating or not. If yes , then loop till you find
* another character. Pass that characters index(new start) into a recursive call*/
if(start == str.length-1)
{
if(flag!=1)
{
str[j] = str[start];
j++;
}
if(j<=str.length-1)
{
str[j] = '0';
}
}
while(start<str.length-1 && str[start]!='0')
{
if(str[start+1]!=str[start])
{
str[j] = str[start];
start++;
j++;
if(start==str.length-1) {removeDups(str,j,start,flag);}
}
else
{
char ref = str[start];
while(str[start]==ref)
{
if(start<str.length-1)
{
start++;
}
else
{
flag =1;
break;
}
}
removeDups(str,j,start,flag);
return;
}
}
}
}
This works as expected. Here I'm just trying to use a 0 instead of \0 character as in C. Now when I translate the code to C
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void removeDups(char *str,int j, int start,int flag)
{
/*Check if start character is repeating or not. If yes , then loop till you find
* another character. Pass that characters index(new start) into a recursive call*/
if(start == strlen(str)-1)
{
if(flag!=1)
{
str[j] = str[start];
j++;
}
if(j<=strlen(str)-1)
{
str[j] = '\0';
}
}
while(start<strlen(str)-1 && str[start]!='0')
{
if(str[start+1]!=str[start])
{
str[j] = str[start];
start++;
j++;
if(start==strlen(str)-1) {removeDups(str,j,start,flag);}
}
else
{
char ref = str[start];
while(str[start]==ref)
{
if(start<strlen(str)-1)
{
start++;
}
else
{
flag =1;
break;
}
}
removeDups(str,j,start,flag);
return;
}
}
}
int main()
{
char str[] = "abcddcba";
int len =
while()
for(int i=0;str[i]!='\0';i++)
{
printf("%c",str[i]);
}
printf("\n");
}
The above code gives different results as compared to the Java code.Its virtually identical , just that I'm using strlen() instead of str.length(as in Java).
The interesting part is : if I change the portion to
if(j<=strlen(str)-1)
{
str[j] = '\0';
return;
}
it works perfectly. I've just added a return statement to the if statement.
Why is this happening ? Identical code producing different results in C and Java
You are using return statement and subsequently all code below that return is being excluded from running for that iteration.
Also, You may want to understand what is \0 is and how it's different than 0.
Here's link:
What does the \0 symbol mean in a C string?
In C, assigning a character in a string to '\0' changes the length, so strlen() will return a different result after that. In your Java code, you're using an array, and an array length never changes. You're setting the character to '0' instead of '\0', which are two different things, but even if you did set it to '\0', it still wouldn't change the length. I haven't examined your entire code, but this is one obvious thing that would cause different results.

Making y[i] a modifiable variable in C

I am building a program that randomly generates a password using the ascii tabe of values and can only contain one of each char. it generates a password that is 8 char long.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#define SIZE 10
char Charactor(char x);
void Check(char* y);
int main()
{
char string[SIZE];//defines varriables
char* point;
point=&string[SIZE];
srand(time(NULL));
for (int i=0;i<SIZE-1;i++)//empties out the string
{
string[i]='\0';
}
for (int i=0;i<SIZE-2;i++)//randomizes a char for each space in the string
{
string[i]=Charactor(*point);
}
Check(point);/checks the string for duplicated values
printf("%s\n",string);//prints string on screen
}
char Charactor(char x)
{
int rnd=0;
rnd=rand()%2;//chooses char or number using ascii
if (rnd==0)
{
rnd=rand()%10+48;
}
else
{
rnd=rand()%26+65;
}
x=(char)rnd;
return x;
}
void Check(char* y)
{
int run=0;
for (int i=0; i<SIZE-2;i++)
{
for (int x=0; x<SIZE-2; x++)
{
if (y[i]==y[x] && run=0)
{
run++;
continue;
}
else
{
y[i]='\0';
y[i]=Charactor(*y);
}
}
}
return;
}
with those changes the code is running now I just have to figure out how to change the correct value so I dont have any duplication.
Fix:
char* point =&string[0]; //Make it to point to first element
Since your Charactor(*point); is really not doing anything based on *point and later you use Check(point); probably to start a scan from start of string.
And
if (y[i]==y[x] && run==0)
^^Use Equality check
You cannot modify a boolean outcome of y[i]==y[x] && run as zero.
Note :
However if (y[i]==y[x] && (run=0) ) wouldn't have thrown this error.
Your error seems to be that you are mistakenly setting run=0 in
if (y[i]==y[x] && run=0)
This is the part that most likely confuses your compiler. Doesn't have to do anything with Y.
Fix to:
if (y[i]==y[x] && run==0)

Memory allocation error for structs with members that are function pointers and void pointers

I have written a straightforward C code that uses an engine to run two different algorithms depending on user input. It uses function pointers to the algorithm methods and objects. There is a nasty memory bug somewhere that I can not track down, so maybe I am allocating memory in the wrong way. What is going wrong?
Below is (the relevant parts of) a minimal working example of the code.
main.c
#include "engine.h"
int main()
{
char *id = "one";
Engine_t eng;
Engine_init(&eng);
Engine_select_algorithm(eng, id);
Engine_run(eng);
}
engine.h
typedef struct _Engine *Engine_t;
engine.c
#include "engine.h"
#include "algorithm_one.h"
#include "algorithm_two.h"
typedef struct _Engine
{
void *p_algorithm;
void (*init)(Engine_t);
void (*run)(Engine_t);
} Engine;
void Engine_init(Engine_t *eng)
{
*eng = malloc(sizeof(Engine));
(*eng)->p_algorithm = NULL;
}
void Engine_select_algorithm(Engine_t eng, char *id)
{
if ( strcmp(id, "one") == 0 )
{
eng->init = Algorithm_one_init;
eng->run = Algorithm_one_run;
}
else if ( strcmp(id, "two") == 0 )
{
eng->init = Algorithm_two_init;
eng->run = Algorithm_two_run;
}
else
{
printf("Unknown engine %s.\n", id); exit(0);
}
eng->init(eng);
}
void Engine_run(Engine_t eng)
{
eng->run(eng);
}
void Engine_set_algorithm(Engine_t eng, void *p)
{
eng->p_algorithm = p;
}
void Engine_get_algorithm(Engine_t eng, void *p)
{
p = eng->p_algorithm;
}
algorithm_one.h
typedef struct _A_one *A_one_t;
algorithm_one.c
#include "engine.h"
#include "algorithm_one.h"
typedef struct _A_one
{
float value;
} A_one;
void Algorithm_one_init(Engine_t eng)
{
A_one_t aone;
aone = malloc(sizeof(A_one));
aone->value = 13.0;
//int var = 10;
Engine_set_algorithm(eng, &aone);
}
void Algorithm_one_run(Engine_t eng)
{
A_one_t aone;
Engine_get_algorithm(eng, &aone);
printf("I am running algorithm one with value %f.\n", aone->value);
// The code for algorithm one goes here.
}
The code for algorithm_two.h and algorithm_two.c are identical to the algorithm one files.
There must be a memory bug involved, because the code runs as given, but if I uncomment the
//int var = 10;
line in algoritm_one.c the code crashes with a segmentation fault.
You pass the wrong thing to Engine_set_algorithm. You are passing the address of a local variable rather than the address of the algorithm. You need to write:
Engine_set_algorithm(eng, aone);
And also Engine_get_algorithm is wrong. You are passed a pointer by value and modify that pointer. So the caller cannot see that modification. You need it to be:
void Engine_get_algorithm(Engine_t eng, void **p)
{
*p = eng->p_algorithm;
}
I think your code would be easier if you defined a type to represent an algorithm. That type would be just a void*, but it would make the code much easier to read. What's more, I would make Engine_get_algorithm return the algorithm.
algorithm Engine_get_algorithm(Engine_t eng)
{
return eng->p_algorithm;
}
void Engine_set_algorithm(Engine_t eng, algorithm alg)
{
eng->p_algorithm = alg;
}

Resources