Reversing a string without using pointers - c

I'm supposed to copy char orig[] to char reversed[] and reverse it. My function works but doesn't properly reset the string as evidenced by the fact that a blank string returns the prior test results. How can I fix this?
void reverse(char orig[], char reversed[]) {
int lastChar = strlen(orig) - 1;
int lastCopy = lastChar;
int i;
for(i = 0; i < lastChar; i++){
reversed[lastCopy] = orig[i];
reversed[i] = orig[lastCopy];
lastCopy--;
reversed[lastChar+1] = '\0';
}
return ;
}
This is what I get as output:
Test "software" (Pass, returns: erawtfos)
Test the empty string
Assertion failure
Have: <erawtfos>
Expect: <>
Test a long string (Pass)
Test a simple palindrome (Pass)
4 assertions: 3 passed 1 failed

OP problem: When the original string orig has length 0 or 1, the null character is never set in reversed.
Instead create a simple loop pulling 1 char at a time.
// As `orig` elements are not changed, good C style to make it `const`
void reverse(const char orig[], char reversed[]) {
// use `size_t` as `int` may be too narrow
size_t length = strlen(orig);
size_t i;
for(i = 0; i < length; i++) {
reversed[i] = orig[length - i - 1];
}
reversed[i] = '\0';
}
If orig and reversed might overlap, a temporary copy is needed.
void reverse(const char orig[], char reversed[]) {
size_t length = strlen(orig);
char tmp[length+1]; // Add 1 because an array of size 0 is UB
memcpy(tmp, orig, length);
size_t i;
for(i = 0; i < length; i++) {
reversed[i] = tmp[length - i - 1];
}
reversed[i] = '\0';
}

Simplify:
void reverse(char orig[], char reversed[]) {
int len = strlen(orig);
int last = len - 1;
reversed[len] = '\0';
for (int i = 0; i < len; i += 1) {
reversed[last] = orig[i];
last -= 1;
}
return;
}

you can use built in functions like string::rbegin(),string::rend()
in order to copy string reversely.
string copy(orig.rbegin(),orig.rend());
don't forget to include < string.h >

Related

C - repeat a string for a specific number of times in anothervariable

I want to repeat a string - for example hello - for a specific number of imes - for example 3 times -, but it doesnt work :) The example should look like this: hellohellohello, but I get no output or i get HHHHHHHHHHH...
here is my code:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
int z = length;
char *ausgabe = calloc((length*(count+1)), sizeof(char));
for(int i = 0; i<=((int) count);i++){
for(int j =0; j< length; j++){
ausgabe[i+j+z] = src[j];
}
z=z*2;
}
//printf("%s\n", ausgabe);
return(ausgabe);
}
If i remove the 'z' in the brackets of 'ausgabe', i get the output HHHHHHHH%, with the z I just get no output. Could bdy pls help me change this behavoiur - and more important, understant why it does that?
As you are always referring *src, which is fixed to the first letter of src,
the result looks like repeating it. Would you please try instead:
char *repeat_str(size_t count, char *src) {
int length = strlen(src);
char *ausgabe = calloc(length * count + 1, sizeof(char));
for (int i = 0; i < count; i++) {
for (int j = 0; j < length; j++) {
ausgabe[i * length + j] = src[j];
}
}
//printf("%s\n", ausgabe);
return ausgabe;
}
The strcat function is your friend. We can calloc a buffer long enough for n source strings, plus one for the null terminator, and then just concatenate the source string onto that buffer n times.
char *repeat_string(int n, const char *s) {
int len = strlen(s) * n + 1;
char *result = calloc(len, 1);
if (!result) return NULL;
for (int i = 0; i < n; i++) {
strcat(result, s);
}
return result;
}

How can I write the concatenated string to the given string pointer in C?

I am having trouble with the very last line in my function, where I am stilly learning the basics of C. I have the signature of this function given and am tasked to write a function to concatenate two strings. The commented line outputs the correct result.
#include <stdio.h>
#include <stdlib.h>
// 1) len = dst-len + max_dst_len
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int total_len = len + max_dst_len;
char *new_str = malloc(sizeof(char) * total_len);
for (int i = 0; i < len; i++) {
new_str[i] = dst[i];
}
for (int i = len; i < total_len; i++) {
new_str[i] = src[i - len];
}
new_str[total_len] = '\0';
//printf("%s <--\n", new_str);
dst = *new_str;
return total_len;
}
int main() {
char test1[] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, 10));
printf("%s\n", test1);
}
You should not be adding max_dst_len to the length of dst. max_dst_len is the amount of memory that's already allocated in dst, you need to ensure that the concatenated string doesn't exceed this length.
So you need to subtract len from max_dst_len, and also subtract 1 to allow room for the null byte. This will tell you the maximum number of bytes you can copy from src to the end of dst.
In your main() code, you need to declare test1 to be at least 10 bytes if you pass 10 as the max_dst_len argument. When you omit the size in the array declaration, it sizes the array just big enough to hold the string you use to initialize it. It's best to use sizeof test1 as this argument, to ensure that it's correct for the string you're concatenating to.
#include <stdio.h>
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int len_to_copy = max_dst_len - len - 1;
int i;
for (i = 0; i < len_to_copy && src[i] != '\0'; i++) {
dst[len+i] = src[i];
}
dst[i] = '\0';
//printf("%s <--\n", new_str);
return i + len;
}
int main() {
char test1[6] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, sizeof test1));
printf("%s\n", test1);
}

Runtime Error Message: Line 17: index -3 out of bounds for type 'int [256]'

I need help to understand an issue with my C code. I am trying to find longest substring within a given string without character repetition. When run on the leetcode platform, the code below gives me an error for the String "amqpcsrumjjufpu":
Runtime Error Message: Line 17: index -3 out of bounds for type 'int [256]'
However, the same code works fine when I run it from my computer or any online editor. Please help me to understand this behaviour difference.
#include <stdio.h>
#include <string.h>
int lengthOfLongestSubstring(char* s) {
char *h = s;
int A[256] = {0};
int length = 0;
int temp = 0;
int max = 0;
int len = strlen(s);
for(int i = 0; i < len;i ++){
int A[256] = {0};
length = 0;
h = s + i;
for(int j = i; j < len-1; j++){
if (A[h[j]] == 1) {
break;
} else {
A[h[j]] = 1;
length +=1;
}
if (max < length) {
max = length;
}
}
}
return max;
}
int main() {
char *s = "amqpcsrumjjufpu";
int ret = lengthOfLongestSubstring(s);
printf("SAURABH: %d",ret);
}
It seems you are trying to write a function that finds the length of the longest substring of unique characters.
For starters the function should be declared like
size_t lengthOfLongestSubstring( const char *s );
^^^^^^ ^^^^^
These declarations in the outer scope of the function
int A[256] = {0};
//...
int temp = 0;
are redundant. The variables are not used in the function.
The type char can behave either as the type signed char or the type unsigned char. So in expressions like this A[h[j]] you have to cast explicitly the character used as index to the type unsigned char as for example
A[( unsigned char )h[j]]
The inner loop
for(int j=i;j<len-1;j++){
will not execute for strings that contain only one character. So it does not make sense as it is written.
This if statement
if (max < length) {
max = length ;
}
needs to be placed outside the inner loop.
The algorithm used by you can be implemented the following way
#include <stdio.h>
#include <limits.h>
size_t lengthOfLongestSubstring(const char *s)
{
size_t longest = 0;
for (; *s; ++s )
{
size_t n = 0;
unsigned char letters[UCHAR_MAX] = { 0 };
for ( const char *p = s; *p && !letters[(unsigned char)*p - 1]++; ++p) ++n;
if (longest < n) longest = n;
}
return longest;
}
int main( void )
{
char *s = "123145";
printf("The longest substring has %zu characters.\n",
lengthOfLongestSubstring(s));
return 0;
}
The program output is
The longest substring has 5 characters.
Your code crashed because you read data out of range, suppose your input string is amqpcsrumjjufpu its length is 15, in outer loop for i = 13 you do assigment
h = s + i; // h was updated to indicate to 13th element of s
and in inner loop for first iteration, you read this element (j == i == 13)
A[h[j]]
so, you try to read this element A[*(h+j)], but h indicates to 13th element of s, and now you try to add 13 to this value, you want to read 26th position of s, you are out of range of s string.
Thanks Everyone for responses. While Vlad's code worked for all the test cases, here is my code that also passed all the test cases after changes suggested by Vlad and rafix.
int lengthOfLongestSubstring(char* s) {
char *h = s;
int max = 0;
int len = strlen(s);
if (len == 1) {
return 1;
}
for(int i = 0; i < len;i ++){
int A[256] = {0};
int length = 0;
for(int j = i; j < len; j++){
if (A[(unsigned char)h[j]] == 1) {
break;
} else {
A[(unsigned char) h[j]] = 1;
length +=1;
}
}
if (max < length) {
max = length;
}
}
return max;
}

Writing to char array, empty output

I'm wondering what's occurring here, I allocate space for the dest variable outside of the reverse function. And then write to it in the function call. But my output is blank. I want to do this without malloc, purely for educational purposes. Thanks
#include <stdio.h>
#include <string.h>
/*function declaration*/
void reverse(char *src, char *dest);
int main(void) {
char src[] = "hello, world";
char dest[strlen(src)];
reverse(src, dest);
printf("%s\n", dest);
return 0;
}
/*function reverse a string*/
void reverse(char *src, char *dest) {
int i;
int j = 0;
for(i = strlen(src); i >= 0; i--) {
*(dest+j) = *(src+i);
++j;
}
}
1) Since your iteration starts with
for(i = strlen(src); i >= 0; i--) {
it assigns 0 to the dest, thus terminating the string. So printf() prints nothing as it sees the 0 terminator. You can re-write it as:
for(i = strlen(src) - 1; i >= 0; i--) {
*(dest+j) = *(src+i);
++j;
}
dest[j] = 0; /* terminates the string */
2) You have another problem. Your dest doesn't have enough space. It should be:
char dest[strlen(src) + 1]; /* Notice the +1 */
3) You should use size_t for array indexes instead of int.
You are forgetting about the null character in your strings. dest is not large enough to hold the reverse of the string since there needs to be a null-terminator:
char dest[ strlen(src) + 1 ];
Then in the loop you are copying the null-terminator to the front of the string so it is essentially the string "" but using more memory. You need to start at the index strlen() - 1:
for(i = strlen(src)-1; i >= 0; i-- ){
The problem is with the for(i=strlen(src)..... in reverse(). src[strlen(src)] is 0 (zero; string-termination). So when you get to printf(), it sees the firs char and outputs an empty string.
Use strlen(str)-1, and then *(dest+j) = 0 after the for-loop.
In total, reverse() should be:
void reverse(char *src, char *dest) {
int i;
int j = 0;
for(i = strlen(src)-1; i >= 0; i--) {
*(dest+j) = *(src+i);
++j;
}
*(dest+j) = 0;
}

Print out the longest substring in c

Suppose that we have a string "11222222345646". So how to print out subsequence 222222 in C.
I have a function here, but I think something incorrect. Can someone correct it for me?
int *longestsubstring(int a[], int n, int *length)
{
int location = 0;
length = 0;
int i, j;
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
{
if (a[i] != a[j])
{
if (i - j >= *length)
{
*length = i - j;
location = j;
}
j = i;
}
}
return &a[location];
}
Sorry,I don't really understand your question.
I just have a little code,and it can print the longest sub string,hope it can help.
/*breif : print the longest sub string*/
void printLongestSubString(const char * str,int length)
{
if(length <= 0)
return;
int i ;
int num1 = 0,num2 = 0;
int location = 0;
for(i = 0; i< length - 1; ++i)
{
if(str[i] == str[i+1])
++num2;//count the sub string ,may be not the longest,but we should try.
else
{
if(num2 >num1)//I use num1 store the sum longest of current sub string.
{ num1 = num2;location = i - num2;}
else
;//do nothing for short sub string.
num2 = 0;
}
}
for(i = location;str[i]== str[num1];++i)
printf("%c",str[i]);
printf("\n");
}
int main()
{
char * str = "1122222234566";
printLongestSubString(str,13);
return 0;
}
From your code it appears you want to return the longest sub-sequence (sub-string). Since I'm relearning C I thought I would give it a shot.
I've used strndup to extract the substring. I'm not sure how portable it is but I found an implementation if needed, just click on the link. It will allocate memory to store the new cstring so you have to remember to free the memory once finished with the substring. Following your argument list, the length of the sub-string is returned as the third argument of the extraction routine.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len);
int main()
{
char str[] = "11222234555555564666666";
size_t substr_len = 0;
char *substr = extract_longest_subsequence(str, sizeof(str), &substr_len);
if (!substr)
{
printf("Error: NULL sub-string returned\n");
return 1;
}
printf("original string: %s, length: %zu\n", str, sizeof(str)-1);
printf("Longest sub-string: %s, length: %zu\n", substr, substr_len);
/* Have to remember to free the memory allocated by strndup */
free(substr);
return 0;
}
char *extract_longest_subsequence(const char *str, size_t str_len, size_t *longest_len)
{
if (str == NULL || str_len < 1 || longest_len == NULL)
return NULL;
size_t longest_start = 0;
*longest_len = 0;
size_t curr_len = 1;
size_t i = 0;
for (i = 1; i < str_len; ++i)
{
if (str[i-1] == str[i])
{
++curr_len;
}
else
{
if (curr_len > *longest_len)
{
longest_start = i - curr_len;
*longest_len = curr_len;
}
curr_len = 1;
}
}
/* strndup allocates memory for storing the substring */
return strndup(str + longest_start, *longest_len);
}
It looks like in your loop that j is supposed to be storing where the current "substring" starts, and i is the index of the character that you are currently looking at. In that case, you want to change
for (i = 0, j = 0; i <= n-1, j < i; i++, j++)
to
for (i = 0, j = 0; i <= n-1; i++)
That way, you are using i to store which character you're looking at, and the j = i line will "reset" which string of characters you are checking the length of.
Also, a few other things:
1) length = 0 should be *length = 0. You probably don't actually want to set the pointer to point to address 0x0.
2) That last line would return where your "largest substring" starts, but it doesn't truncate where the characters start to change (i.e. the resulting string isn't necessarily *length long). It can be intentional depending on use case, but figured I'd mention it in case it saves some grief.

Resources