i have try this code made by me but no output and there's no errors?
#include <stdio.h>
void reverse(char *p,char *v,int size){
for(int i=size-1,j=0;i<0;i--){
*(v+j) = *(p+i);
j++;
}
}
int main(){
char word[6] = {"hello"};
char re_word[6];
re_word[5]='\0';
reverse(word,re_word,6);
printf("%s",re_word);
}
Using pointers it can look like this:
void reverse(char *w, char *revw, int slen) {
revw += slen - 1; // forward to pos. of last letter
revw[1] = '\0'; // one further *(revw+1)
while (*w)
*revw-- = *w++;
}
This is clear and symmetric, once it works, while your i-- and j++ are far apart.
slen is meant to be the number of letters w/o termination. Here the call:
char word[] = {"hello"};
char re_word[sizeof word];
reverse(word, re_word, sizeof word - 1);
strlen() should be used, probably, but these lines show how you can and have to control not just the total size but especially the last byte of the char array.
Without the correct length, reverse() would have to do a strlen() first, because it has to know how far away to put the first letter.
This *(v+j) = *(p+i) is more or less v[j] = p[i] and does not really take advantage of pointers, on the contrary.
(revw
caller) in reverse()
| |
v v
-4 -3 -2 -1 revw +1
o l l e h \0
... revw-- revw[1]
So revw is maybe not the best name inside the function; revw_first_backwards is meant...or fill_start. But before I fill backwards I do the one additional write to the right side to terminate the string: array notation using a pointer: revw[1] = '\0'.
First of all, i < 0 will always be false, given i = size - 1 > 0.
What you want is i >= 0.
Also, given size = 6, size - 1 will be equal to 5, and that is the NULL terminator position since array indexing in C start from 0. Perhaps use a C function such as strlen() to calculate the length rather than hard coding it.
void reverse(char *p, char *v, size_t size)
{
for (int i = size - 1, j = 0; i >= 0; i--)
{
*(v + j) = *(p + i);
j++;
}
}
int main()
{
char word[6] = {"hello"};
char re_word[6];
re_word[5] = '\0';
reverse(word, re_word, 5); /* or reverse(word, re_word, strlen(word)) */
printf("%s", re_word);
}
Related
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 reverse a string. scanf is working well but when I use fixed string then it gives garbage value. So where is the fault ?
#include<stdio.h>
#include<string.h>
int main()
{
char s[50]="Hi I Love Programming";
char rev[strlen(s)];
int i,k;
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
printf("The reverse string is: %s\n", rev);
}
Your program has two issues:
1.
char rev[strlen(s)];
You forgot to add an element for the string-terminating null character '\0'.
Use:
char rev[strlen(s) + 1];
Furthermore you also forgot to append this character at the end of the reversed string.
Use:
size_t len = strlen(s);
rev[len] = '\0';
Note, my len is the k in your provided code. I use the identifier len because it is more obvious what the intention of that object is. You can use strlen(s) because the string has the same length, doesn´t matter if it is in proper or reversed direction.
2.
k=strlen(s);
for(i=0; i<strlen(s); i++)
{
rev[k]=s[i];
k--;
}
With rev[k] you accessing memory beyond the array rev, since index counting starts at 0, not 1. Thus, the behavior is undefined.
k needs to be strlen(s) - 1.
Three things to note:
The return value of strlen() is of type size_t, so an object of type size_t is appropriate to store the string length, not int.
It is more efficient to rather calculate the string length once, not at each condition test. Use a second object to store the string length and use this object in the condition of the for loop, like i < len2.
char s[50]="Hi I Love Programming"; can be simplified to char s[]="Hi I Love Programming"; - The compiler automatically detects the amount of elements needed to store the string + the terminating null character. This safes unnecessary memory space, but also ensures that the allocated space is sufficient to hold the string with the null character.
The code can also be simplified (Online example):
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Hi I Love Programming";
size_t len = strlen(s);
char rev[len + 1];
size_t i,j;
for(i = 0, j = (len - 1); i < len; i++, j--)
{
rev[j] = s[i];
}
rev[len] = '\0';
printf("The reverse string is: %s\n", rev);
}
Output:
The reverse string is: pgnimmargorP evoL I iH
your program is hard to understand. Here you have something much simpler (if you want to reverse the string of course)
#include <stdio.h>
#include <string.h>
char *revstr(char *str)
{
char *start = str;
char *end;
if(str && *str)
{
end = str + strlen(str) - 1;
while(start < end)
{
char tmp = *end;
*end-- = *start;
*start++ = tmp;
}
}
return str;
}
int main()
{
char s[50]="Hi I Love Programming";
printf("%s", revstr(s));
}
https://godbolt.org/z/5KX3kP
I'm new to C and I'm attempting to perform a modification to a string that I have (I'm attempting to reverse it), but I'm unsure why the program doesn't run as intended (displays no output).
void reverse(char *rTarget);
int main()
{
char memes[] = "memes";
reverse(memes);
printf("%s", memes);
}
void reverse(char *rTarget)
{
char swap;
int length = (int) strlen(rTarget);
for (int i = 0; i < length / 2; i++)
{
swap = rTarget[i];
rTarget[i] = rTarget[length - i];
rTarget[length - i] = swap;
}
}
For starters this function declaration
void reverse(char *rTarget[]);
is equivalent to
void reverse(char **rTarget);
There is no great sense to declare it such a way.
You should declare the function like
void reverse( char rTarget[] );
and call it like
reverse( memes );
The function definition is also wrong. At least you have to use the loop like
for (int i = 0; i < length / 2; i++)
and these expressions
swap = *rTarget[i];
*rTarget[i] = *rTarget[length - i];
*rTarget[length - i] = swap;
are invalid. They shall be rewritten like
swap = ( *rTarget )[i];
( *rTarget )[i] = ( *rTarget )[length - i -1];
( *rTarget )[length - i - 1] = swap;
Also the variable length shall have the type size_t because in general an object of the type int can not accommodate an object of the type size_t and the function strlen have the return type size_t. So you have to substitute this declaration
int length = (int) strlen(*rTarget);
For this declaratiuon
size_t length = strlen(*rTarget);
Pay attention to that according to the conventions for standard C string functions the function should return pointer to the reversed string.
And according to the C Standard the function main without parameters shall be declared like
int main( void )
Here is a demonstration program that shows how the function can be declared and defined
#include <stdio.h>
#include <string.h>
char * reverse( char *s )
{
for ( size_t i = 0, n = strlen( s ); i < n / 2; i++ )
{
char c = s[i];
s[i] = s[n-i-1];
s[n-i-1] = c;
}
return s;
}
int main(void)
{
char memes[] = "memes";
puts( reverse( memes ) );
return 0;
}
The program output is
semem
#include <stdio.h>
#include <string.h>
void reverse(char *rTarget);
int main()
{
char memes[] = "memes";
reverse(memes);
printf("%s", memes);
}
void reverse(char *rTarget)
{
int length = (int) strlen(rTarget);
for (int i = 0; i < length / 2; i++)
{
char swap = rTarget[i];
rTarget[i] = rTarget[length - i - 1];
rTarget[length - i - 1] = swap;
}
}
The expression *rTarget[i] is parsed as *(rTarget + i), not *(rTarget) + i as you may expect. And you do not need to pass char ** here.
The problem is here
*rTarget[i] = *rTarget[length - i]
*rTarget[length - i] = swap;
The primary problem seems to be operator precedence. [] has higher precedence than *. You are passing "array of strings" (because pointers can be used as arrays), so when i is 0, on the left side you take the first (and only existing) array at [0], and * references its first character. To this you assign nonsense from the right side: first character of array [length] (which doesn't exist), which is undefined behavior, so what you program does after this is meaningless to speculate about. You need to add parentheses, so that you reference the pointer to array, so you get the actual array, and then use [] on that.
But even if you add parentheses, your algorithm is wrong. On first round, i is 0 so you copy (*rTarget)[length] to start of string. That is the string terminating 0, so you end up with modified string length 0 (first byte is 0). You need -1 for the length.
Fixing your original code, it therefore becomes:
for (int i = 0; i < length / 2; i++)
{
swap = (*rTarget)[i];
(*rTarget)[i] = (*rTarget)[length - i - 1];
(*rTarget)[length - i - 1] = swap;
}
Additionally, your function argument is needlessly complex (pointer to pointer to char), straight pointer to modifiable string is enough. Other answers cover that beauty issue.
There are all kinds of dereferencing errors here. Rememember, a string is an array of characters, not an array of character pointers. So this
void reverse(char *rTarget[])
Should be
void reverse(char rTarget[])
And here:
int length = (int) strlen(*rTarget);
You don't have to dereference rTarget, so remove the *. Same in the swap, remove all * that you have there.
Last but not least, there's an off by one error in your swap. Instead of going to length - i, you want to go to length - i - 1, otherwise you're swapping the null terminator to the beginning.
Also your loop should only go to the first half of the array, because otherwise you swap everything twice, resulting in the original string again:
for (int i = 0; i < length/2; i++)
All in all it should look like this:
void reverse(char rTarget[]);
int main()
{
char memes[] = "memes";
reverse(memes);
printf("%s", memes);
}
void reverse(char rTarget[])
{
char swap;
int length = (int)strlen(rTarget);
for (int i = 0; i < length/2; i++)
{
swap = rTarget[i];
rTarget[i] = rTarget[length - i - 1];
rTarget[length - i - 1] = swap;
}
}
This should do it:
void reverse(char rTarget[]);
int main()
{
char memes[] = "memes";
reverse(memes);
printf("%s", memes);
}
void reverse(char rTarget[])
{
char swap;
int lastindex = (int) strlen(rTarget) - 1;
for (int i = 0; i < lastindex / 2; i++)
{
swap = rTarget[i];
rTarget[i] = rTarget[lastindex - i];
rTarget[lastindex - i] = swap;
}
}
There are a couple of problems in your code.
First of all, arrays are always 'passed by reference', so you don't need to pass a pointer to an array. Any changes you make in the array will persist after the function call.
Secondly, array subscripts in C start from 0. So the last character (not counting null) in a string of length n is string[n-1] not string[n].
EDIT: As #roottraveller mentioned, since you are swapping characters, you don't need to run till the end of the string. You only need to go till the half of length.
If you are not intended to send multiple strings to reverse function then function argument only require a char pointer. While swap character you need to traverse only 50% of the string. The code can be as following.
void reverse(char *rTarget)
{
char swap;
int length = (int) strlen(rTarget);
for(int i = 0, j = (length - 1); i < (length / 2); i++, j--)
{
swap = *(rTarget+i);
*(rTarget+i) = *(rTarget+j);
*(rTarget+j) = swap;
}
}
I am doing a check whether 2 strings are permutations. I sort the strings then compare each character to each other. However, I think my sorting process also changes the original strings (I am very bad with pointers and passing by reference).
Is there a way to check without modifying the original strings?
I also tried using strcpy but I don't really know how to use it.
I tried this in my check() function:
char temp[128];
strcpy(temp, word);
Below is my code. I call the areAnagram function from another function like this:
void check(char *word, struct Entry *en) {
if (areAnagram(en->word, word) == 1) {
//printf("EW:%s W:%s\n", en->word, word);
//For example, this should return something like
// EW:silent W:listen
//But I got
// EW:eilnst W:eilnst
}
}
Structure for Entry:
typedef struct Entry {
char *word;
int len;
struct Entry *next;
} Entry;
Here is the anagram check process:
void quickSort(char *arr, int si, int ei);
int areAnagram(char *str1, char *str2)
{
// Get lenghts of both strings
int n1 = strlen(str1);
int n2 = strlen(str2);
// If lenght of both strings is not same, then they cannot be anagram
if (n1 != n2) {
return 0;
}
// Sort both strings
quickSort (str1, 0, n1 - 1);
quickSort (str2, 0, n2 - 1);
int i;
// Compare sorted strings
for (i = 0; i < n1; i++) {
if (str1[i] != str2[i]) {
return 0;
}
}
return 1;
}
void exchange(char *a, char *b)
{
char temp;
temp = *a;
*a = *b;
*b = temp;
}
int partition(char A[], int si, int ei)
{
char x = A[ei];
int i = (si - 1);
int j;
for (j = si; j <= ei - 1; j++) {
if(A[j] <= x) {
i++;
exchange(&A[i], &A[j]);
}
}
exchange (&A[i + 1], &A[ei]);
return (i + 1);
}
void quickSort(char A[], int si, int ei)
{
int pi; /* Partitioning index */
if(si < ei) {
pi = partition(A, si, ei);
quickSort(A, si, pi - 1);
quickSort(A, pi + 1, ei);
}
}
There is a better way of checking whether two strings are anagrams.You can create an array to store the count of each character in first string(increment the ASCII value index in the array). Then traverse second string and decrement the count of each character (ASCII value index in the array). Now check if all elements of array are zero,if yes these are anagrams otherwise not.
int arr[123];
suppose two strings are s1="abba" and s2="baba"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second array arr[97]=0,arr[98]=0;
Now if you traverse the whole array then all elements will be zero.
But if two strings s1="abba" and s2="abac"
while traversing first string arr[97]=2,arr[98]=2;
while traversing second string arr[97]=0,arr[98]=1,arr[99]=-1;
Since all elements of array are not zero so these are not anagrams.
The complexity of above algorithm is O(n).
Hope it helps.
Make a copy using strcpy:
char *copy = malloc(strlen(word) + 1); // can use a temporary buffer, but this allows variable length inputs
strcpy(copy, word);
// use copy as your temporary string
free(copy);
Your title states that you do not want to modify the original string, however your solution uses Quicksort, which modifies the string. Plus, sorting -- even a fast optimized sort -- is an expensive operation and is not needed for the problem you are trying to solve. You could use a lookup table for speed and it would not modify the original string. You simply create a unique number for each letter and sum the values. Equal sums would constitute an anagram.
/* OPTION 1: let the compiler build your table */
static const int A=0x0000001;
static const int B=0x0000002;
static const int C=0x0000004;
/* continue to double for other letters until ... */
static const int Z=0x4000000;
/* OPTION 2: calculate a cheap hash for each letter */
/* Returns 0 for anagram similar to strcmp */
int anagram (const char* word1, const char* word2)
{
/* strings must be equal length */
if (strlen(word1) != strlen(word2))
return -1;
unsigned long sum1 = 0;
unsigned long sum2 = 0;
char c;
for (int i = 0 ; word1[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word1[i]);
sum1 += 1 << (c - 'A');
}
for (int i = 0 ; word2[i] != '\0' ; i++)
{
/* use toupper() function here if case insensitive */
c = toupper(word2[i]);
sum2 += 1 << (c - 'A');
}
return (int)(sum1 - sum2); /* ignore overflow */
}
The anagram function above is untested and has been written for clarity. You'd need to include the ctype.h to convert the case using toupper().
Finally, you could make a copy of one of the strings, traverse the other string calling strchr() on each character to find the matching character in the copy. If strchr() returns NULL then there is no anagram, otherwise if strchr() returns a valid pointer, use it to modify the copy, e.g. set to char value to 0x01, so that you can sum the chars in the modified copy. In this instance, the strings would be anagrams if the sum of all the chars in the modified copy equal the integer length of the comparison string.
Hy everybody!
I am trying to write a program that checks if a given string of text is a palindrome (for this I made a function called is_palindrome that works) and if any of it's substrings is a palindrome, and I can't figure out what is the optimal way to do this:
For example, for the string s = "abcdefg" it should first check "a", then "ab", "abc", "abcd" and so on, for each character
In Python this is the equivalent of
s[:1], s[:2], ... (a, ab, ...)
s[1:2], s[1:3] ... (b, bc, ...)
What function/method is there that I can use in a similar way in C ?
This is the one liner I use to get a slice of a string in C.
void slice(const char *str, char *result, size_t start, size_t end)
{
strncpy(result, str + start, end - start);
}
Pretty straightforward.
Given you've checked boundaries and made sure end > start.
This slice_str() function will do the trick, with end actually being the end character, rather than one-past-the-end as in Python slicing:
#include <stdio.h>
#include <string.h>
void slice_str(const char * str, char * buffer, size_t start, size_t end)
{
size_t j = 0;
for ( size_t i = start; i <= end; ++i ) {
buffer[j++] = str[i];
}
buffer[j] = 0;
}
int main(void) {
const char * str = "Polly";
const size_t len = strlen(str);
char buffer[len + 1];
for ( size_t start = 0; start < len; ++start ) {
for ( int end = len - 1; end >= (int) start; --end ) {
slice_str(str, buffer, start, end);
printf("%s\n", buffer);
}
}
return 0;
}
which, when used from the above main() function, outputs:
paul#horus:~/src/sandbox$ ./allsubstr
Polly
Poll
Pol
Po
P
olly
oll
ol
o
lly
ll
l
ly
l
y
paul#horus:~/src/sandbox$
There isn't; you'll have to write your own.
In order to check a string, you would need to supply to the number of characters to check in order to check for a palindrome:
int palindrome(char* str, int len)
{
if (len < 2 )
{
return 0;
}
// position p and q on the first and last character
char* p = str;
char* q = str + len - 1;
// compare start char with end char
for ( ; p < str + len / 2; ++p, --q )
{
if (*p != *q)
{
return 0;
}
}
return 1;
}
now you would need to call the function above for each substring (as you described it, i.e. always starting from the beginning) e.g.
char candidate[] = "wasitaratisaw";
for (int len = 0; len < strlen(candidate); ++len)
{
if (palindrome(candidate, len))
{
...
}
}
disclaimer: not compiled.
Honestly, you don't need a string slicing function just to check for palindromes within substrings:
/* start: Pointer to first character in the string to check.
* end: Pointer to one byte beyond the last character to check.
*
* Return:
* -1 if start >= end; this is considered an error
* 0 if the substring is not a palindrome
* 1 if the substring is a palindrome
*/
int
ispalin (const char *start, const char *end)
{
if (start >= end)
return -1;
for (; start < end; ++start)
if (*start != *--end)
return 0;
return 1;
}
With that, you can create the following:
int
main ()
{
const char *s = "madam";
/* i: index of first character in substring
* n: number of characters in substring
*/
size_t i, n;
size_t len = strlen (s);
for (i = 0; i < len; ++i)
{
for (n = 1; n <= len - i; ++n)
{
/* Start of substring. */
const char *start = s + i;
/* ispalin(s[i:i+n]) in Python */
switch (ispalin (start, start + n))
{
case -1:
fprintf (stderr, "error: %p >= %p\n", (void *) start, (void *) (start + n));
break;
case 0:
printf ("Not a palindrome: %.*s\n", (int) n, start);
break;
case 1:
printf ("Palindrome: %.*s\n", (int) n, start);
break;
} /* switch (ispalin) */
} /* for (n) */
} /* for (i) */
}
Of course, if you really wanted a string slicing function merely for output (since you technically shouldn't cast a size_t to int), and you still want to be able to format the output easily, the answer by Paul Griffiths should suffice quite well, or you can use mine or even one of strncpy or the nonstandard strlcpy, though they all have their strengths and weaknesses:
/* dest must have
* 1 + min(strlen(src), n)
* bytes available and must not overlap with src.
*/
char *
strslice (char *dest, const char *src, size_t n)
{
char *destp = dest;
/* memcpy here would be ideal, but that would mean walking the string twice:
* once by calling strlen to determine the minimum number of bytes to copy
* and once for actually copying the substring.
*/
for (; n != 0 && *src != 0; --n)
*destp++ = *src++;
*destp = 0;
return dest;
}
strslice actually works like a combination of strncpy and the nonstandard strlcpy, though there are differences between these three functions:
strlcpy will cut the copied string short to add a null terminator at dest[n - 1], so copying exactly n bytes before adding a null terminator requires you to pass n + 1 as the buffer size.
strncpy may not terminate the string at all, leaving dest[n - 1] equal to src[n - 1], so you would need to add a null terminator yourself just in case. If n is greater than the src string length, dest will be padded with null terminators until n bytes have been written.
strslice will copy up to n bytes if necessary, like strncpy, and will require an extra byte for the null terminator, meaning a maximum of n+1 bytes are necessary. It doesn't waste time writing unnecessary null terminators as strncpy does. This can be thought of as a "lightweight strlcpy" with a small difference in what n means and can be used where the resulting string length won't matter.
You could also create a memslice function if you wanted, which would allow for embedded null bytes, but it already exists as memcpy.
There is not any built-in function/method in any standard C library which can handle this. However, you can come up with your own method to do the same.