I have a problem with the return of that function, it should return the vector with the typed sequence, but it's returning an ordered sequence, could you tell me where I'm going wrong?
Create a recursive function that takes a string as input and also its length. This function should return how many times the character the substring “hi” appears in the string.
Prohibited
The first line in the input contains the number n of test cases. Next, n lines occur, each containing a string of maximum length equal to 5000 characters
Exit
The output consists of n lines, each containing an integer that indicates the number of times the string “hi” occurs in the input string. All strings are written in lowercase letters.
Example
Prohibited
4
hipotenuse hipothermia hilux hifi
hi
hihihi
xavante hey
Exit
4
1
3
0
My code:
#include <stdio.h>
#include <string.h>
#define MAX 5000
int ocorrencias(const char *palavra, size_t len) {
char *st = "hi";
return len ?
(*st == *palavra) + ocorrencias(palavra + 1, len - 1) :
0;
}
int main() {
int n,i;
scanf("%d",&n);
char palavra[MAX];
int re[n];
for(i=0; i<=n; i++){
fgets(palavra, MAX, stdin);
re[i] = ocorrencias(palavra, strlen(palavra));
}
for(i=0; i<=n; i++){
printf("%d\n", re[i]);
}
}
For starters the for loops like this
for(i=0; i<=n; i++){
^^^^^
are wrong.
You need to write
for(i=0; i < n; i++){
^^^^^^
The function ocorrencias should be declared either like
size_t ocorrencias( const char *palavra );
or like
size_t ocorrencias( const char *palavra, const char *st );
instead of
int ocorrencias(const char *palavra, size_t len) ;
because it deals with strings and the function is able to determine lengths of passed strings.
It can be defined for example the following way
size_t ocorrencias( const char *palavra )
{
const char *st = "hi";
const char *p = strstr( palavra, st );
return p == NULL ? 0 : 1 + ocorrencias( p + strlen( st ) );
}
So in main you should write
size_t re[n];
//...
for ( i = 0; i < n; i++ )
{
printf( "%zu\n", re[i] );
}
Otherwise if you want to count substrings either "hi" or "hy" (according to your comment to the question) then the function can look the following way
size_t ocorrencias( const char *palavra )
{
const char *p = strchr( palavra, 'h' );
return p == NULL ? 0 : ( p[1] == 'i' || p[1] == 'y' ) + ocorrencias( p + 1 );
}
Related
This question already has answers here:
Modify the content of char* str
(2 answers)
Closed 10 months ago.
Im getting a segfault when changing dna[i] to U, Ive debbuged but I still cant understand why.
Also I was comparing the value at a position against T with strcmp, but from what I understand thats for string literals and I can simply compare it with dna[i] == 'T'. Is that right? thanks.
#include <string.h>
char *dna_to_rna(char *dna) {
int size = (int)( sizeof(dna) / sizeof(dna[0]));
char *retour[size];
strcpy(retour, dna);
for (int i = 0; i < size; i++) {
if (dna[i] == 'T') {
dna[i] = 'U';
}
}
return (char *) retour;
}
int main() {
char *dna[] = {
"TTTT",
"GCAT",
"GACCGCCGCC"
};
char *actual, *expected;
size_t n;
for (n = 0; n < 3; ++n) {
actual = dna_to_rna(*(dna + n));
}
return 0;
}
You are passing to the function dna_to_rna a pointer to a string literal
actual = dna_to_rna(*(dna + n));
and then within the function you are trying to change the string literal
if (dna[i] == 'T') {
dna[i] = 'U';
}
Any attempt to change a string literal results in undefined behavior.
Also the expression with the sizeof operator in this declaration
int size = (int)( sizeof(dna) / sizeof(dna[0]));
does not make a sense. It evaluates the size of a pointer of the type char *.
Instead you should use the standard string function strlen.
And this declaration is incorrect
char *retour[size];
At least you need a character array instead of an array of pointers.
char retour[size];
And the function returns a pointer to an array with automatic storage duration that will not be alive after exiting the function
char *dna_to_rna(char *dna) {
//...
char retour[size];
//...
return (char *) retour;
}
that is the function returns an invalid pointer.
You should dynamically allocate a character array within the function with the length strlen( dna ) + 1 and change and return this array.
It seems what you mean is something like the following
#include <string.h>
#include <stdlib.h>
char * dna_to_rna( const char *dna )
{
size_t n = strlen( dna );
char *retour = malloc( n + 1 );
if ( retour != NULL )
{
strcpy( retour, dna );
for ( size_t i = 0; i < n; i++ )
{
if ( retour[i] == 'T' ) retour[i] = 'U';
}
}
return retour;
}
The task is:
Write a full program that takes an int n > 0 and recursively prints all combinations of characters 'a' and 'b' on the screen.
Example for n=3: aaa, baa, bba, aba, bab, aab, abb, bbb.
I assume I have to use something similar to Backtracking.
This is what I have, but Im not able to think of the rest.
void rep(int n, char str, int pos) { //n would be the length and str would be the pointer
char c[n + 1];
char d[3];
d[0] = 'a';
d[1] = 'b';
for (int j = 0; j < 2; j++) {
if (strlen(c) == n) { // if c is n long recursion ends
printf("%s", c);
} else {
c[pos] = d[j]; // put 'a' or 'b' in c[pos]
rep(n, c, pos + 1); // update pos to next position
}
}
}
The variable length array c is not initialized
char c[n+1]
Thus the call of strlen in this if statement
if(strlen(c) == n){
invokes undefined behavior.
Moreover the parameter str is not used within the function.
I can suggest the following solution as it is shown in the demonstration program below
#include <stdio.h>
#include <string.h>
void rep( char *s )
{
puts( s );
char *p = strchr( s, 'a' );
if (p != NULL)
{
memset( s, 'a', p - s );
*p = 'b';
rep( s );
}
}
int main()
{
char s[] = "aaa";
rep( s );
}
The program output is
aaa
baa
aba
bba
aab
bab
abb
bbb
That is the function rep is initially called with an array that contains a string of the required size n (in the demonstration program n is equal to 3) consisting of all characters equal to the character 'a' and recursively outputs all combinations until the string contains all characters equal to the character 'b'.
There a some issues in your code:
the str argument should have type char *
you so not need new arrays in the recursive function, but use the one the str argument points to.
you do not set a null terminator at the end of your char arrays.
instead of strlen(), use pos to determine if the recursion should stop.
Here is a modified version
#include <stdio.h>
// n is the length and str points to an array of length n+1
void rep(int n, char *str, int pos) {
if (pos >= n) {
str[n] = '\0'; // set the null terminator
printf("%s\n", str);
} else {
str[pos] = 'a';
rep(n, str, pos + 1);
str[pos] = 'b';
rep(n, str, pos + 1);
}
}
#define LEN 3
int main() {
char array[LEN + 1];
rep(LEN, array, 0);
return 0;
}
I am trying to learn programming and am doing some random questions and tasks. The task is to write out the last three characters of a string and this is what I've come up with. Please do not solve this for me, I am asking about my output/result not for anyone to do the problem solving for me:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int func(char *input_1, char *input_2) {
char last_three_digits_1[3]; // define two arrays that hold the last three characters
char last_three_digits_2[3];
int x = 0;
for(int y = strlen(input_1) - 4; y < strlen(input_1) - 1; y++) {
last_three_digits_1[x] = input_1[i];
x++;
}
x = 0; // repeat for the second string
for(int z = strlen(input_2) - 4; z < strlen(input_2) - 1; z++) {
last_three_digits_2[x] = input_2[i];
x++;
}
printf("last3_1: %s, \nlast3_2: %s\n", last_three1, last_three2); // this seem to access random memory because it outputs "abc" followed by random "-???" or "-????" or "-?2?2". Same for the second array.
return 0;
}
int main(int argc, char * argv[] ) {
if(argc == 3) { // needs to be two strings. E.g: "abcd efghi"
if(strlen(argv[1]) >= 3 || strlen(argv[2]) >= 3) { // if any of the strings are less than 3 in length, e.g. "ab wadnkwa" then do not proceed.
func(argv[1], argv[2]); // send the user input to the function
}
return 0; // maybe redundant
}
return 0; // return 0 for failure
}
The condition in the if statement
if(strlen(argv[1]) >= 3 || strlen(argv[2]) >= 3)
means that the length of one of the strings can be less than 3. In this case the function func can invoke undefined behavior.
It seems you mean
if(strlen(argv[1]) >= 3 && strlen(argv[2]) >= 3)
Otherwise you need in the function func to make a check whether a string has length greater than or equal to 3 before outputting its last three characters.
If a string has exactly three characters then for example in this loop
for(int i = strlen(text1) - 4; i < strlen(text1) - 1; i++)
the variable i can have an implementation defined value as for example -1 and as a result this expression text1[i] invokes undefined behavior.
The return type int of the function does not have a meaning.
Pay attention to that if you are using the format %s to output a character array using printf then the array shall contain a string that is a sequence of characters terminated with the zero character '\0'.
So neither the if statement in main nor the function itself makes a sense.
To output last three (or any other number) characters of a string there is no need to create an auxiliary array. It can be done much simpler.
For example
void func( const char *text1, const char *text2, size_t n )
{
size_t n1 = strlen( text1 );
if ( !( n1 < n ) ) text1 += n1 - n;
size_t n2 = strlen( text2 );
if ( !( n2 < n ) ) text2 += n2 - n;
printf( "last%zu_1: %s, \nlast%zu_2: %s\n", n, text1, n, text2 );
}
And the function can be called like
func( argv[1], argv[2], 3 );
Using such a declaration of the function you can output any number of last characters of two strings. Also take into account that the function parameters have the qualifier const because the passed strings are not changed within the function.
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
void func( const char *text1, const char *text2, size_t n )
{
size_t n1 = strlen( text1 );
if (!( n1 < n )) text1 += n1 - n;
size_t n2 = strlen( text2 );
if (!( n2 < n )) text2 += n2 - n;
printf( "last%zu_1: %s, \nlast%zu_2: %s\n", n, text1, n, text2 );
}
int main( void )
{
func( "Hello", "World", 3 );
}
The program output is
last3_1: llo,
last3_2: rld
char last_three1[3]; // define two arrays that hold the last three characters
char last_three2[3];
You need space to hold \0 char, because %s expects char* to be \0 terminated.
char last_three1[4];
char last_three2[4];
….
last_three1[x] = '\0';
x = 0; // repeat for the second string
for(int i = strlen(text2) - 4; i < strlen(text2) - 1; i++) {
last_three2[x] = text2[i];
x++;
}
last_three2[x] = '\0';
Strings in C are terminated with a single zero byte.
You're not zero-terminating the strings, so printf doesn't know where to stop printing (and you're lucky your program doesn't outright crash).
I'd refactor things like this, so you have a single function that simply copies the three last bytes and zero-terminates the string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// out must be an array that can hold 4 bytes
// in must be >= 3 characters; otherwise this function returns non-zero
int get_last_three(char *out, const char *in) {
int len = strlen(in);
if (len < 3)
return -1;
for (int i = len - 3; i < len; i++) {
*out = in[i];
out++;
}
*out = 0; // Zero-terminate
return 0;
}
int main(int argc, char *argv[]) {
char out[4];
for (int i = 1; i < argc; i++) {
if (get_last_three(out, argv[i]) == 0) {
printf("last3_%d: %s\n", i, out);
}
}
}
I've been doing this code wars challenge in which you have to take a string, and capitalize each letter, forming a Mexican wave-looking array of strings. For example, an input string like
hello
will result in ["Hello", "hEllo", "heLlo", "helLo", "hellO"]
I managed to complete it in JavaScript, and decided to attempt it in C. The actual code itself is working, as it prints the correct output, but the problem I am having is actually storing the string inside a double pointer.
This is my code:
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void wave(char *s, char **array);
int main(void)
{
char *s = malloc(6);
strcpy(s, "hello");
char **array = malloc(pow(strlen(s)+1, 2));
wave(s, array);
for (int i = 0; i < strlen(s); i++)
{
printf("s = %s\n", array[i]);
}
free(array);
free(s);
return 0;
}
void wave(char *s, char **array)
{
char s2[strlen(s)+1];
for (int i = 0; i < strlen(s); i++)
{
s[i] = tolower(s[i]);
}
int array_index = 0;
for (int i = 0; i < strlen(s); i++)
{
strcpy(s2, s);
if (s[i] != ' ')
{
s2[i] = toupper(s2[i]); // Printing out `s2` here results in the correct output
array[array_index++] = s2; // Adding it here works, but when trying to access it outside of this function, it gives the incorrect output
}
}
}
When printing the string inside the function, I get the following output (which is correct):
Hello
hEllo
heLlo
helLo
hellO
But when I try to print it out inside the main() function, I get the following:
s = hellO
s = hellO
s = hellO
s = hellO
s = hellO
It seems like it is adding/accessing only the last string in the array. I cannot understand why accessing the element inside the wave() function works, but accessing it outside of that function doesn't.
I've had this problem twice before, both in C and C++, and have been unable to solve it, and it is really annoying me.
I left this as a comment, but since it might not be clear, I'll post my answer in code...
As stated in my comment, there's no point allocating a pointer array - on a 64 bit machine, that would be 6 pointers, each requiring 8 bytes to point at a 7 byte long data block - a total of 104 bytes (ignoring the added allocator padding per allocation).
Instead, a single allocation could suffice, allocating 42 bytes to contain all the "wave" strings and their NUL byte in a single block of memory (saving memory while improving locality).
int main(void) {
/* Assuming string "hello" */
const char *org = "hello";
/* Calculate length only once and store value */
const size_t len = strlen(org);
const size_t len_with_nul = len + 1;
/* Allocate `len` strings in a single allocation */
char *buf = malloc(len * len_with_nul);
/* Copy each string to it's place in the buffer */
for (size_t i = 0; i < len; ++i) {
/* position in the buffer */
char *pos = buf + (i * len_with_nul);
/* copy the NUL as well */
memcpy(pos, org, len_with_nul);
/* Wave... */
pos[i] = toupper(pos[i]);
}
/* Print result */
for (size_t i = 0; i < len; i++) {
char *pos = buf + (i * len_with_nul);
printf("s = %s\n", pos);
}
/* Free buffer */
free(buf);
return 0;
}
EDIT - Why is using a single memory block better?:
In this case we allocate a single memory "block" (blob / slice). This offers a number of advantages:
We perform a single allocation and deallocation instead of a larger number of allocations and deallocations.
This improves speed by performing less actions.
We also improve memory locality, which minimizes CPU cache misses and improves performance.
We use less memory.
Each memory allocation comes with a price - we need a pointer to hold the memory address for the memory we allocated. A pointer "costs" 8 bytes on a 64bit machine and 4 bytes on a 32bit machine.
By using a single allocation, we "pay" less.
This is true even if we ignore the metadata attached to the memory block allocated (which requires memory from the memory allocator).
I should note that C doesn't really care about the contents of a memory block, it's all zeros and ones. The meaning given to these zeros and ones is left to the developer.
Even the printf function doesn't care about the contents of the memory it's reading - it simply reads the memory according to the formatting it was instructed to follow by the developer (the %s informs the function that the memory relates to a NUL terminated string).
There are some concerns about memory alignment which are CPU and system specific - but these don't apply to single byte strings. They apply to multi-byte types (such as short, int, and long). So we don't need to worry about them in this example.
In this sense, it basically means that the developer is free to manage the memory and the contents as they see fit (putting aside memory alignment).
This is not to say that it's always better to allocate a single block of memory (if you need to use realloc, you might prefer smaller chunks)... but usually a single block of memory is better.
For starters it is unclear why you are allocating dynamically memory for the string literal "hello".
char *s = malloc(6);
strcpy(s, "hello");
It does not make any sense.
Just write
const char *s = "hello";
This declaration
char **array = malloc(pow(strlen(s), 2));
also does not make sense. What you need is the following.
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
The function wave can be defined the following way
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
and then in main after the function call
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
Here is the full program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void wave( const char *s, char **array )
{
size_t n = strlen( s );
for ( size_t i = 0; i < n; i++ )
{
strcpy( array[i], s );
array[i][i] = toupper( ( unsigned char )s[i] );
}
}
int main(void)
{
const char *s = "hello";
size_t n = strlen( s );
char **array = malloc( n * sizeof( char * ) );
for ( size_t i = 0; i < n; i++ )
{
array[i] = malloc( n + 1 );
}
wave( s, array );
for ( size_t i = 0; i < n; i++ )
{
puts( array[i] );
}
for ( size_t i = 0; i < n; i++ ) free( array[i] );
free( array );
return 0;
}
Its output is
Hello
hEllo
heLlo
helLo
hellO
This question already has answers here:
How do I use strtok with every single nonalpha character as a delimeter? (C)
(4 answers)
Closed 7 years ago.
char *p_word;
p_word = strtok (p_input, " ,.-:\n1234567890");
while (p_word != NULL)
{
printf ("%s\n", p_word);
p_word = strtok (NULL, " ,.-:\n1234567890");
}
I'm reading in a text file and want to perform various functions on each word at a time, ignoring any characters that arent part of the alphabet.
I am wanting to know if there is a way instead of typing every single undesired character into the delimiter (e.g. " ,.-:\n1234567890"), that I can specify a range of ASCII decimal values I dont want, i.e. 0-64, or otherwise NOT alphabet characters.
Thanks
EDIT: I'm not allowed to use material that hasn't been taught so I dont think I can use functions from "ctype.h"
If you must use strtok, you can build a delimiter string like this (assumes ASCII character set) which excludes the alphabet.
char *p_word;
char delims[128];
int dindex;
int i;
dindex = 0;
for (i = 1; i < 'A'; i++)
delims[dindex++] = i;
for (i = 'Z' + 1; i < 'a'; i++)
delims[dindex++] = i;
for (i = 'z' + 1; i < 128; i++)
delims[dindex++] = i;
delims[dindex] = '\0';
p_word = strtok (p_input, delims);
You can write your own strtok function that will accept a predicate as the second parameter.
Of course you should use some other name for the function as you like.
Here is a demonstrative program. I have written a simplified predicate that checks any alpha ASCII character. You may use your own predicate.
#include <stdio.h>
char * strtok( char *s, int cmp( char ) )
{
static char *p;
if ( s ) p = s;
if ( p )
{
while ( *p && cmp( *p ) ) ++p;
}
if ( !p || !*p ) return NULL;
char *t = p++;
while ( *p && !cmp( *p ) ) ++p;
if ( *p ) *p++ = '\0';
return t;
}
int cmp( char c )
{
c |= 0x20;
return c < 'a' || c > 'z';
}
int main( void )
{
char s[] = " ABC123abc<>XYZ!##xyz";
char *p = strtok( s, cmp );
while ( p )
{
puts( p );
p = strtok( NULL, cmp );
}
}
The program output is
ABC
abc
XYZ
xyz
Using the predicate you can specify in it any rules for skipped characters.