Problems with creating a function to reverse a string [closed] - c

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 7 years ago.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Improve this question
I need to create a fuction that returns a string. So far I have come up with this code:
#include <stdio.h>
#include <string.h>
#define SIZE 256
void str_reverse(char[SIZE], char[SIZE]);
int main(void)
{
char input[SIZE];
char output[SIZE];
printf("Please enter a string\n");
fgets(input, SIZE, stdin);
str_reverse(input, output);
printf("%s \n", output);
return 0;
}
void str_reverse(char in[SIZE], char out[SIZE])
{
int i = strlen(in);
int k = 0;
for(int j = i; j>= 0; j--)
{
out[k] = in[j];
k++;
}
}
However, whenever I try to run the code, I do not get an output. Does anyone have any idea what could be wrong

The problem is this line
int i = strlen(in);
Change it to
int i = strlen(in)-1;
strlen() returns the size of the string, hence when you start copying from in[], in[j] would be \0. which is getting stored in out[0].
Another change you need to do is put a \0 in the out[], just after the for loop
for(int j = i; j>= 0; j--)
{
out[k] = in[j];
k++;
}
out[k] = '\0';

Your "reversing" includes the null character too. So the reversed string's first character is '\0'. So the string is empty.
Change:
for(int j = i ; j>= 0; j--)
to
for(int j = i - 1; j>= 0; j--)
You should also check if the string length is zero before the for loop. Otherwise, i-1 will become SIZE_MAX and you'll have problems with that!
A simple condition such as the following in str_reverse() would handle that case:
size_t i = strlen(in);
int k = 0;
if (i<=1) return; //empty string or contains only 1 char char.

i starts out at strlen(in), so the first character you copy over tooutis the null byte at the end of the string. Every other character then appears after the null terminator, soout` is an empty string.
Start with i at strlen(in) - 1, then add the null terminator and the end of the loop:
int i = strlen(in) - 1; // start at the last non-null character
int k = 0;
for(int j = i; j>= 0; j--)
{
out[k] = in[j];
k++;
}
out[k] = '\0'; // add the null terminator

When k is 0 and j is i, you do the following:
out[0] = '\0';
Hence, out looks like an empty string when the function returns.
Use:
for(int j = i-1; j>= 0; j--)
{
out[k] = in[j];
k++;
}
out[k] = '\0';

In the function variable i is set the following way
int i = strlen(in);
So within the loop
for(int j = i; j>= 0; j--)
{
out[k] = in[j];
k++;
}
then j is equal to i then in[j] is equal to the terminating zero '\0' of string in. Thus array out starts from zero that is it will contain an empty string.
It is better to declare the function itself the following way
char * str_reverse( char *out, const char *in );
and to return from the function the pointer out. In this case you could write for example
puts( str_reverse( output, input ) );
Take into acount that function fgets usually also stores the new line character in the string. You should remove it. you can do it the following way
input[strcspn( input, "\n" )] = '\0';
Also instead of the type int in this statement
int i = strlen(in);
it is better to use type size_t.
size_t i = strlen(in);
It is the type of the return value of the function strlen. But in this case you should also to write the loop correctly.:)

Related

C allocation memory error. Don't find something like this

Could you help please ?
When I execute this code I receive that:
AAAAABBBBBCCCCCBBBBBCOMP¬ıd┐╔ LENGTH 31
There are some weirds characters after letters, while I've allocate just 21 bytes.
#include <stdio.h>
#include <stdlib.h>
char * lineDown(){
unsigned short state[4] = {0,1,2,1};
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(21);
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
*(deco+p) = decorationUp[k][i];
p++;
}
}
return deco;
}
int main(void){
char * lineDOWN = lineDown();
int k = 0;
char c;
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != '\0');
printf("LENGTH %d\n\n",k);
}
The function does not build a string because the result array does not contain the terminating zero though a space for it was reserved when the array was allocated.
char * deco = malloc(21);
So you need to append the array with the terminating zero before exiting the function
//...
*(deco + p ) = '\0';
return deco;
}
Otherwise this do-while loop
do{
c = *(lineDOWN+k);
printf("%c",*(lineDOWN+k));
k++;
}while(c != '\0')
will have undefined behavior.
But even if you will append the array with the terminating zero the loop will count the length of the stored string incorrectly because it will increase the variable k even when the current character is the terminating zero.
Instead you should use a while loop. In this case the declaration of the variable c will be redundant. The loop can look like
while ( *( lineDOWN + k ) )
{
printf("%c",*(lineDOWN+k));
k++;
}
In this case this call
printf("\nLENGTH %d\n\n",k);
^^
will output the correct length of the string equal to 20.
And you should free the allocated memory before exiting the program
free( lineDOWN );
As some other wrote here in their answers that the array decorationUp must be declared like
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
then it is not necessary if you are not going to use elements of the array as strings and you are not using them as strings in your program.
Take into account that your program is full of magic numbers. Such a program is usually error-prone. Instead you should use named constants.
In
char decorationUp[3][5] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
your string needs 6 characters to also place the null char, even in that case you do not use them as 'standard' string but only array of char. To get into the habit always reverse the place for the ending null character
you can do
char decorationUp[3][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
Note it is useless to give the first size, the compiler counts for you
Because in main you stop when you read the null character you also need to place it in deco at the end, so you need to allocate 21 for it. As before you missed the place for the null character, but here that produces an undefined behavior because you read after the allocated block.
To do *(deco+p) is not readable, do deco[p]
So for instance :
char * lineDown(){
unsigned short state[] = {0,1,2,1};
char decorationUp[][6] = {
{"AAAAA"},{"BBBBB"},{"CCCCC"}
};
char * deco = malloc(4*5 + 1); /* a formula to explain why 21 is better than 21 directly */
int k;
int p = 0;
for(int j = 0; j < 4; j++){
k = state[j];
for(int i = 0; i < 5; i++){
deco[p] = decorationUp[k][i];
p++;
}
}
deco[p] = 0;
return deco;
}

Storing first characters of elements in a string [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
How can I store the first character of an element in a string? E.g. if I run
for (j=0; j < 5; j++) {
printf("%s\n, string[j]);
}
I get
hello
how
are
you
Thanks to the answer provided by #Holy semicolon, I know that I can run printf("%c\n, string[j][0]); to print the first letters:
h
h
a
y
However, how can I store the first letters in a new array?
So far, I have:
char secondStr[10];
for (j=0; j<5; j++) {
secondStr[j] = string[j][0];
}
This results in an error assignment makes pointer from integer without a cast
I know this question is slightly different to the one I asked before (regarding printing the first elements) - I was unsure whether or not to ask an entirely new question on SO. I apologise in advance if I was supposed to ask a new question.
when you have an array of pointers to char *string1[] = {"hello", "how", "are", "you"}; and you want to print the first string of it hello so you must use %s for string like this printf("%s",string1[0]) but if you want to print the first char of the first string you need to use %c like this printf("%c",string1[0][0]).
#include <stdio.h>
int main()
{
char *string1[] = {"hello", "how", "are", "you"};
printf("%s",string1[0][0]); // I think you did this fault It'll give you Segmentation fault
return 0;
}
so as you see in the code above you need to replce %s with %c.
Edit
What if I wanted to store the first letters in a new list?
you will need then to allocate memory to the new string.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *string1[] = {"hello", "how", "are", "you"};
char **keep = calloc(sizeof(char*),5); //memory allocating
for (int index = 0; index <= 3; index++)
{
keep[index] = calloc(sizeof(char),2); //memory allocating
keep[index][0] = string1[index][0];
keep[index][1] = '\0';
}
//for test
for (int i = 0; i <= 3; i++)
printf("%c\n",keep[i][0]);
return 0;
}
If string is std::string, then:
string s[6] = { "hello","how", "are", "you", "?" };
for (int j = 0; j < 5; j++)
{
if(s[j].size())
printf("%c\n", s[j].c_str()[0]);
}
Should word.
Many options are there. I will just mention some.
Use begin()
for( int i = 0 ; i < num ; i++ )
{
string:: iterator it = String[i].begin();
cout << *it;
}
Use front()
for( int i = 0 ; i < num ; i++ )
{
cout << String[i].front();
}
Use at()
for( int i = 0 ; i < num ; i++ )
{
cout << String[i].at();
}
You can just go through the member functions of string and use it to your purpose

Rearranging string letters

I was doing a program to copy all string words other than its first 2 words and putting a x at the end of it.
However i cant put x at its end. Please help!!!!
Below is my code.
#include<stdio.h>
#include<string.h>
int main()
{
char a[25], b[25];
int i, j, count = 0, l, k;
scanf("%[^\n]s", a);
i = strlen(a);
if (i > 20)
printf("Given Sentence is too long.");
else
{/* checking for first 2 words and counting 2 spaces*/
for (j = 0; j < i; j++)
{
if (a[j] == ' ')
count = count + 1;
if (count == 2)
{
k = j;
break;
}
}
/* copying remaining string into new one*/
for (j = 0; j < i - k; j++)
{
b[j] = a[j + k];
}
b[j + 1] = 'x';
printf("%s", b);
}
}
you are removing first two index. But you wrote k=j and if you check the current value j there it's 1. so you are updating wrongly k because you removed 2 indexes. So k value should be 2. So checked the below code
/* copying remaining string into new one*/
for (j = 0; j < i - 2; j++)
{
b[j] = a[j + 2];
}
b[j + 1] = 'x';
printf("%s", b);
Your index is off by one. After your second loop, the condition j < i-k was false, so j now is i-k. Therefore, the character after the end of what you copied is b[j], not b[j+1]. The correct line would therefore be b[j] = 'x';.
Just changing this would leave you with something that is not a string. A string is defined as a sequence of char, ending with a '\0' char. So you have to add b[j+1] = 0; as well.
After these changes, your code does what you intended, but still has undefined behavior.
One problem is that your scanf() will happily overflow your buffer -- use a field width here: scanf("%24[^\n]", a);. And by the way, the s at the and doesn't make any sense, you use either the s conversion or the [] conversion.
A somewhat sensible implementation would use functions suited for the job, like e.g. this:
#include<stdio.h>
#include<string.h>
int main(void)
{
// memory is *cheap* nowadays, these buffers are still somewhat tiny:
char a[256];
char b[256];
// read a line
if (!fgets(a, 256, stdin)) return 1;
// and strip the newline character if present
a[strcspn(a, "\n")] = 0;
// find first space
char *space = strchr(a, ' ');
// find second space
if (space) space = strchr(space+1, ' ');
if (space)
{
// have two spaces, copy the rest
strcpy(b, space+1);
// and append 'x':
strcat(b, "x");
}
else
{
// empty string:
b[0] = 0;
}
printf("%s",b);
return 0;
}
For functions you don't know, google for man <function>.
In C strings are array of chars as you know and the way C knows it is end of the string is '\0' character. In your example you are missing at the last few lines
/* copying remaining string into new one*/
for(j=0;j<i-k;j++)
{
b[j]=a[j+k];
}
b[j+1]='x';
printf("%s",b);
after the loop ends j is already increased 1 before it quits the loop.
So if your string before x is "test", it is like
't', 'e', 's', 't','\0' in char array, and since your j is increased more than it should have, it gets to the point just right of '\0', but characters after '\0' doesnt matter, because it is the end, so your x will not be added. Simple change to
b[j]='x';

Segmentation Fault:11 in C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am writing a program in C that replaces a number in a char* called "template" with a string, but I continually get a Segmentation Fault: 11 error.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
char *rep_str(const char *s, const char *old, const char *new1){
char *ret;
int i, count = 0;
int newlen = strlen(new1);
int oldlen = strlen(old);
for (i = 0; s[i] != '\0'; i++){
if (strstr(&s[i], old) == &s[i]){
count++;
i += oldlen - 1;
}
}
ret = (char*)malloc(i + count * (newlen - oldlen));
if (ret == NULL)
exit(EXIT_FAILURE);
i = 0;
while (*s){
if (strstr(s, old) == s){ //compare the substring with the newstring
strcpy(&ret[i], new1);
i += newlen; //adding newlength to the new string
s += oldlen;//adding the same old length the old string
} else {
ret[i++] = *s++;
}
}
ret[i] = '\0';
return ret;
}
char* madlib_by_numbers(char* temp, int word_count, char* words[]){
char* numbers[] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
int tempSize = strlen(temp);
for (int i = 0; i < tempSize; i++){
if (isdigit(temp[i])){
for (int j = 0; j < (sizeof(numbers) / sizeof(char*)); j++){
temp = rep_str(temp, numbers[j], words[j]); //it makes it to this line, but never gets to assert()
}
}
}
return temp;
}
int main() {
char* temp1 = "The 1 0 likes to 2 in the moonlight.";
char* words[] = {"git", "brilliant", "swim"};
char* result = "The brilliant git likes to swim in the moonlight.";
int stringLength = strlen(result);
char* test = madlib_by_numbers(temp1, 3, words);
assert(strncmp(test, result, stringLength) == 0);
free(test);
return 0;
}
and when I run the debugger, it simply says: Segmentation Fault: 11
What i just want to understand is where the segmentation fault error is coming from, I have the suspicion one of my loops is running too many times.
There are a few issue with your code. However, the direct answer to your question is in this loop:
for (int j = 0; j < (sizeof(numbers) / sizeof(char*)); j++){
temp = rep_str(temp, numbers[j], words[j]);
}
You are calling rep_str for every digit while you mean call rep_str only if the digit in temp matches the corresponding digit in numbers. So add this conditional if(strcmp(temp,numbers[j]) == 0) right before the line temp=.... Then it'll solve your current problem.
The segfault is caused because there are only three elements in the words array. Your old loop indexes from 0 to 9 and fails when j=3, out of bound.
Also, delete the free() at the end of your program. test was never allocated and will cause a core dump.
ret = (char*)malloc(i + count * (newlen - oldlen));
There are a few problems with this line of code.
For a start, don't cast malloc (or any void * that you're assigning to a variable of different pointer type, or vice versa).
If you intended to allocate space to store a string, where's the string-terminating '\0' going to go? You need to realise that for an empty old string, this will be malloc(0) and zero bytes is not enough to store an empty string.
There's also a problem if you expect that old may be a substring of new (for example, you're replacing "0" with "hell0"). You'll need to tweak your algorithm to handle this problem. I'll leave that as a challenge for you to attempt :)
for (int i = 0; i < tempSize; i++){
if (isdigit(temp[i])){
for (int j = 0; j < (sizeof(numbers) / sizeof(char*)); j++){
temp = rep_str(temp, numbers[j], words[j]); //it makes it to this line, but never gets to assert()
}
}
}
users previous answer highlighted this code correctly, but not for the right reason... and so the solution he/she presented is wrong.
isdigit(temp[i]) may also cause segfaults for some inputs. I recommend using isdigit((unsigned char) temp[i]) instead, in this case.
It's not valid to access words[j] where word_count is 3 and j is greater or equal to 3; you're accessing that array out of bounds.
You also need to be careful to free any memory you *alloc (while simultaneously not freeing memory that you don't *alloc). Forgetting to do the former won't cause crashes, but your program won't run happily; it'll use heaps of memory.
Consider something like this, instead:
temp = strdup(temp);
if (temp == NULL) {
exit(EXIT_FAILURE);
}
for (int i = 0; i < tempSize; i++){
if (isdigit((unsigned char) temp[i])){
for (int i = min(word_count, sizeof(numbers) / sizeof(char*)), j = 0; j < i; j++){
char *new = rep_str(temp, numbers[j], words[j]);
free(temp);
temp = new;
}
}
}

How to find whether the string is a Lapindrome? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 years ago.
Improve this question
The following code is giving correct output as given on the codechef problem page: http://www.codechef.com/problems/LAPIN
but getting wrong answer on submission
please tell me the possible problem with my code
here is the question
Lapindrome is defined as a string which when split in the middle, gives two halves having the same characters and same frequency of each character. If there are odd number of characters in the string, we ignore the middle character and check for lapindrome. For example gaga is a lapindrome, since the two halves ga and ga have the same characters with same frequency. Also, abccab, rotor and xyzxy are a few examples of lapindromes. Note that abbaab is NOT a lapindrome. The two halves contain the same characters but their frequencies do not match.
Your task is simple. Given a string, you need to tell if it is a lapindrome.
Input:
First line of input contains a single integer T, the number of test cases.
Each test is a single line containing a string S composed of only lowercase English alphabet.
Output:
For each test case, output on a separate line: "YES" if the string is a lapindrome and "NO" if it is not.
and here is the code
#include<stdio.h>
#include<string.h>
int main()
{
int f,t,mid,len;
char arr[1000];
int left[125],right[125];
scanf("%d",&t);
for(int i=0;i<t;i++)
{
f=0;
scanf("%s",arr);
memset(left,0,sizeof(left));
memset(right,0,sizeof(right));
len=strlen(arr);
for(int i=0;i<len/2;i++)
left[arr[i]]++;
for(int i=(len+1)/2;i<len;i++)
right[arr[i]]++;
for(int i=0;i<strlen(arr);i++)
{
if(left[arr[i]]!=right[arr[i]])
f++;
break;
}
if(f==0)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
I recommend you read up on modularity; it'll make your life easier.
#include <stdio.h>
#define BOOL unsigned char
#define TRUE 1
#define FALSE 0
unsigned string_length(char *string)
{
unsigned counter = 0;
while (string[counter++] != '\0') { }
return counter - 1;
}
BOOL are_equal(unsigned *a, unsigned *b, int size)
{
int i;
for (i = 0; i < size; ++i)
{
if (a[i] != b[i])
{
return FALSE;
}
}
return TRUE;
}
BOOL is_lapindrome(char *string)
{
unsigned left[26] = { 0 }, right[26] = { 0 },
str_len = string_length(string);
if (str_len < 2)
{
return FALSE;
}
int i;
for (i = 0; i <= str_len / 2 - 1; ++i)
{
left[string[i] - 'a']++;
}
for (i = (str_len + 1) / 2; i < str_len; ++i)
{
right[string[i] - 'a']++;
}
return are_equal(left, right, 26);
}
int main()
{
char *list[6] =
{
"gaga",
"abcde",
"rotor",
"xyzxy",
"abbaab",
"ababc"
};
int i;
for (i = 0; i < 6; ++i)
{
printf("%s\n", is_lapindrome(list[i]) == TRUE ? "YES" : "NO");
}
return 0;
}
Your buffer is one byte too short - a string of 1000 characters requires 1001 chars, the last one taken by the nul terminator.
"lowercase English alphabet" sounds a bit ambiguous - I'd say that by some interpretation, it could contain spaces. If so, the input will be read incorrectly.
I can't see other problems right now, but I'd strongly suspect the first one.

Resources