Reverse string with external function - c

I recently started a course in Programming in C. I got an assignment where I'm going to make an external function with this declaration:
void reverse(char *array, int numberOfChars)
My code looks like this at the moment. The problem is that the code will just reverse the first half of the word, and keep the second half as normal.
#include <stdio.h>
#include <string.h>
void reverse(char *array, int numberOfChars) {
int i = 0;
int j = 0;
for (i = numberOfChars - 1; i >= 0; i--) {
array[j] = array[i];
j = j + 1;
}
}
#define NAMESIZE 100
int main() {
char word[NAMESIZE];
int length;
printf("Enter a word: ");
scanf("%s", word);
getchar();
length = strlen(word);
reverse(word, length);
printf("%s\n", word);
}

Even when you use an intermediate variable, your code will reverse the string twice, leaving it as it was. A small change to the code compares i with j as well as using a temporary variable to do the swap.
int i, j = 0;
char temp;
for(i = numberOfChars-1; i > j; i--){
temp = array[j];
array[j] = array[i];
array[i] = temp;
j = j + 1;
}

Your function has a classic problem: you are reversing the string in place. You overwrite the characters at the start of the string with the characters from the end. The initial characters are lost by the time you reach the mid point. You should instead swap the characters from both ends and stop at the mid point.

You are going to need a secondary char array to reverse the string.Try like this:
#include <stdio.h>
#include <string.h>
#define NAMESIZE 100
void reverse(char *arr,int numberOfChars);
int main()
{
char word[NAMESIZE];
printf("Enter a word: ");
scanf("%s",word);
getchar();
size_t length=strlen(word);
reverse(word,length);
printf("%s\n",word);
}
void reverse(char *arr,int numberOfChars)
{
char buffer[NAMESIZE];
int j = 0,i = numberOfChars;
while( i-- )
buffer[j++] = arr[i];
buffer[j] = '\0';
strcpy(arr,buffer);
}

A simple way to prevent overwriting your array is to copy your array into a temporary one and write the reversed readed temporary array into the other.
If you want to have an unknown array size at compilation to reverse, I recommend you to use a heap array (see man malloc) instead of stack one to prevent segmentation fault if numberOfChars is too hight.

Related

printing a string in a specific format

So I created have a program that basically prints any given string like that:
Example:
Input:
Hello
Output:
Hello
ello
llo
lo
o
The problem is that for some reason if I use icdiff and compare my output with that output in a text file it says that I am missing elements and that I have more spaces than it should.
Icdiff output:
Hello
ello
llo
As you can see this is clearly different than what I have, but if I test it on the terminal I get the expected output.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_array(char *p, int tamanho) {
int i;
for (i = 0; i < tamanho; i++) {
printf("%c", p[i]);
}
printf("\n");
}
void nova_str(char *p, char *s, int inicio, int tamanho) {
int i;
for (i = inicio; i < tamanho; i++) {
s[i] = p[i];
}
}
int main() {
char p[1001];
int len;
int j;
scanf("%s", p);
len = strlen(p);
print_array(p, len);
for (j = 1; j < len; j++) {
char *np = (char *)calloc(len + 1, sizeof(char));
nova_str(p, np, j, len);
print_array(np, len);
free(np);
}
return 0;
}
Really any help would be appreciated.
The problem is in the nova_str function: you use the same index into the source and the destination, so the destination array still starts with initcio null bytes which are printed by the print_array and appear as spaces on your system. The array is initialized to all bits zero by calloc().
Here is a much simpler version:
#include <stdio.h>
int main() {
char p[1001];
if (scanf("%1000s", p) == 1) {
for (int i = 0; p[i] != '\0'; i++) {
/* print the word starting at offset i */
printf("%s\n", p + i);
}
}
return 0;
}
calloc() is setting the memory to zero, so you are printing null characters in print_array() when it should be spaces. Replace those null characters with spaces there and this is solved, although I think there is an easier way to achieve what you are trying to do.
If you don't want the letters to be prepended by spaces, add an if (p[i] == '\0') continue; before printf() in print_array() instead.

I am trying to change the string permanently but this code isn't doing it

#include<stdio.h>
#include<conio.h> //**Just To Add getch() function**
int length(char *p){
int i; //**I know That these variable are not the same as they are in other function**
for(i=0;*(p+i)!='\0';i++);
return i;
}
void strrev(char *p){
int i,len;
len=length(p);
char cpy[len]; //**Already Tried to change it to some fixed value**
for(i=0;i<len;i++){
cpy[i]=*(p+len-i);
}
for(i=0;i<len;i++){
*(p+i)=cpy[i];
}
}
int main(){
char str[20]="computer";
strrev(str);
printf("%s",str);
getch(); //**to Stop The Screen**
return 0;
}
I have tried changing the array size to a fixed value i also tried with changing the variable but there is no mistake in my syntax.
By recommendation of #Yunnosch, here is my comment as an answer.
In your function strrev you iterate over the whole string i.e. the iterations for i from zero to len / 2 you correctly grab the characters, but the remaining iterations just undo this again.
Thus, just iterate from zero to len >> 1. The bit-shift ensures integer division.
void strrev(char* const str)
{
const size_t len = strlen(str);
for(size_t i = 0; i < (len >> 1u); ++i)
{
const size_t j = len - 1u - i;
char c = str[i];
str[i] = str[j];
str[j] = c;
}
}
using this cpy[i]=*(p+len-i); means you are placing \0 terminator in the beginning of string cpy. in which case your both of strings will start with \0 and so printf will do nothing.
so change cpy[i]=*(p+len-i); to cpy[i] = *(p + len - i-1);.

Longest palindrome in a string and it's length

I have a program that is supposed to go through a string identify possible palindromes, check if it is a palindrome and then return the length from palindromelength() or -1 if it is not, and print out the longest palindrome of the string.
The program is compiling but the output is wrong.
This is my code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int palindromelength(char *str, int i, int j){
char *start = str;
char *end = str + j;
while(start < end){
if(*start != *end)
return -1;
start++;
end--;
}
return j-i+1;
}
void ispalindrome(char *str){
int length = 1, max = 1, start =0, i, j;
for(i=0; i<= strlen(str) -2; i++){
for(j= 1; j <= strlen(str)-1; j++){
if(abs(i-j) > 1){
length = palindromelength(str, i, j);
if( length> max){
max = length;
start = i;
}
}
}
}
if(max > 1){
printf("Largest palindrome is ");
for( ; start <= j; start++){
printf("%c", str[start]);
start++;
}
}
else
printf("No palindromes in string.");
}
int main(void) {
char a[50];
char *a2;
printf("Enter a string\n");
scanf("%[^\n]", a);
int length = strlen(a) + 1;
a2 = (char*)malloc(length*sizeof(char));
strcpy(a2, a);
free (a2);
char *a3 = &a;
ispalindrome(a3);
return 0;
}
I have tried the palindromelength() separately with a simple string, "aracecar". palindrimelength(a3, 0, 4) returns -1 so that is right, palindromelength(a3, 0, 3) returns 3 so that is right, but palindromelength(a3, 1, 7) returns -1, which is wrong. I double checked my function with other ones on stack overflow and it seems right, what could be the problem?
As for the second function ispalindrome() is there a better way I could write that one? It just seems kind of messy right know.
I am a newbie, therefore I may not have yet learned some more advanced/sophisticated variations I could take to solve this.
I presume int i is the starting index of the string and int j is the ending index. If that is so, have a closer look at the first line of your palindromelength() function. Could the function ever start from somewhere other than index 0?
As for ways to do the ispalindrome() function, there are many algorithms out there to check whether or not an input is a palindrome, I would suggest having a look around and finding out different methods. If your way works, great! probably the cleanest way is to use recursion although that can take some thinking.

Disadvantage when exercising with recursion

I'm doing the following exercise:
Example:
"abcde"
Output:
a
b
c
d
e
Here the template code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char* diag(char* str, char* r)
{
/* Write code */
r[0] = '\0';
return r;
}
int main (void)
{
char str [] = "abcde";
int n = strlen(str);
char* r = malloc(n * n + 1);
r = diag(str, r);
puts(r);
free(r);
return 0;
}
Someone could guide me a little the function must be recursive, not know how to start
The trick with recursion is to consider what condition you need to make the necessary changes. You've already gotten everything set up, now think about how you would increment the array so that you can assign the letters to the diagonal positions (there's a pattern). There also needs to be a terminating case.
You can use this:
printDiagonally(char* s, int low, int high){
if(low < high){
int i;
for(i=0 ; i<low; i++)
printf(" ");
printf("%c\n", *s);
printDiagonally(++s, low+1, high);
}
}

Palindrome Program

I've created a program that takes an inputted string and outputs the string backwards. I've created a function that counts the number of characters in a string. With that information, I've created another function that puts the first character of the original array at the end of the new array. Thus, when the loop in the function has finished, the new array contains the letters of the original array but backwards. I'm running into some difficulty however. I'm still wary of character arrays and I'm not sure if I'm using them correctly. Could someone help me out?
#include <stdio.h>
#define MAXLINE 1000
char backward(char str[], int count)
int count(char str[])
int main() {
char orig[MAXLINE];
int c;
scanf("%s", orig);
c = count(orig);
printf("%s", backward(orig, c));
return 0;
}
char backward(char str[], int count) {
char back[MAXLINE];
int i;
for(i = 0; i <= count; ++i) {
back[count] = str[i];
--count;
return back;
}
int count(char str[]) {
int i;
for (i = 0; str[i] != '\0'; ++i)
;
return i;
}
Edit: Input: Let's say "minivan". Expected output would be "navinim". There's no actual output yet. I'm getting this error:
palindrome.c:8: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘int’
The error you're getting is because your prototypes are wrong:
#include <stdio.h>
#define MAXLINE 1000
char backward(char str[], int count) /* missing ; */
int count(char str[]) /* missing ; */
int main() {
You should also consider replacing count() with strlen(3) from the <string.h> header file. The standard library is full of utilities that have been debugged and known to work well -- it is worth using them. (Yes, there's educational value in re-implementing them. But in that case, be prepared to test with a variety of corner cases.)
Your code probably won't compile because you missed a closing brace in backward().
char backward(char str[], int count) {
char back[MAXLINE];
int i;
for(i = 0; i <= count; ++i) {
back[count] = str[i];
--count;
/** You should add a } character here! **/
return back;
}
MAJOR EDIT 1:
I tried to compile your code and there were lots of things wrong with it. Here is working code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINE 1000
char * backward(char * str);
int main() {
char orig[MAXLINE];
int c;
scanf("%s", orig);
printf("%s\n", backward(orig));
return 0;
}
char * backward(char * str) {
int count = strlen(str);
char * back = malloc(MAXLINE);
int i;
for(i = 0; i < count; i++)
{
back[count-i-1] = str[i];
}
back[count] = 0; // Add the null termination character.
return back;
}
When I run this code and enter "abcde", it outputs "edcba". Let me know if you have any specific questions about how this works. I got rid of your count() function because it is a duplicate of strlen(), and I moved the call to strlen() inside the backward() to make the interface to the backward() function simpler.
Another thing that made your code fail is that you were decrementing count inside the for loop, which would cause your for loop to terminate earlier than you wanted it to.
This line has an off by one mistake:
back[count] = str[i];
count is not the last character of the string, it's the '\0' character.
Also you are returning a stack variable - this is not going to work.
You should reverse the string in place:
for(i = 0; i <= count; ++i) {
--count;
char tmp = str[i];
str[i] = str[count];
str[count] = tmp;
}
You can then return str.
You program have lot of errors. Firstly you have missed out semicolons(;) while declaring the prototypes for backward and count. Then you haven't closed the for loop in backward function with ending braces(}).
But the biggest three problems are
1. You have defined backward function as a char data type but you are returning a pointer to the array of char data type
2. You are accessing back[count] instead of back[count-1]. Suppose the string is minivan. The count will hold 7. the last character is at 6th position not 7th because in array subscripts starts with 0 not 1. And back[count] will point to null character i.e '\0'
3. You are incrementing i and decrementing count and checking i<=count. This will process your string only till mid of it.
Although the right program has been posted by David Greyson, but since he have removed the count function and introduced the strlen and malloc function, I am posting your program again by just correcting your algorithm
#include <stdio.h>
#define MAXLINE 1000
char *backward(char str[], int count);
int count(char str[]);
int main() {
char orig[MAXLINE];
int c;
scanf("%s", orig);
c = count(orig);
printf("%s", backward(orig, c));
return 0;
}
char *backward(char str[], int count) {
char back[MAXLINE];
int i;
for(i = 0; i < count; ++i) {
back[count-i-1] = str[i];
}
back[i] = '\0';
return back;
}
int count(char str[]) {
int i;
for (i = 0; str[i] != '\0'; ++i)
;
return i;
}
You can create a character pointer then add length of string to this pointer, it should likely char *reverse = (char *)name, then add reverse = reverse + strlen(name) -1.
Then you can use while loop through through the start of string. The whole code looks,
void main(void)
{
char *name = "Kernel";
char *reverse = (char *)name;
reverse = reverse + strlen(name) - 1;
while(*reverse)
printf("%c", *reverse);
}
#include<Stdio.h>
#include<string.h>
int main()
{
size_t i,j;
char arr[10]={'\0'};//orignal array
char arr2[10]={'\0'};//it's reverse to be
gets(arr);//prompt
strncpy(arr2,arr,10);//copy
strrev(arr2);
if(strncmp(arr,arr2)==0)
printf("plaindrom");
return 0;
}

Resources