Why does this C reverse string function not work? - c

I'm confused why I get an empty string when I print out reversed. Printing out the character at each iteration seems to be working ok.
Output:
original string: testing
g
n
i
t
s
e
t
reversed:
#include <stdio.h>
#include <string.h>
void reverse_string(char string[]) {
int str_len = strlen(string);
char reversed[20];
int j = 0;
for (int i = strlen(string); i>= 0; i--) {
char tmp = string[i];
reversed[j] = tmp;
printf("%c\n", reversed[j]);
j++;
}
reversed[j] = '\0';
printf("reversed: %s", reversed);
}
int main (void) {
char string[8] = "testing";
printf("original string: %s", string);
reverse_string(string);
return 0;
}

i starts at strlen(string), which points to the terminating '\0' character. That character is copied into position 0 in the reversed string, so any characters after that are not considered part of the string.

for (int i = strlen(string); i>= 0; i--) {
char tmp = string[i];
string[strlen(string)] is by definition always the string termination character '\0'. You have to start your loop at strlen(string)-1.

Related

Attempt to reverse a string results in a blank string

I'm newbie in C and I'm trying to do some function to reverse a word, here my code:
#include <stdlib.h>
#include <string.h>
// ƒ to revers the word
void lettreCount(char *saisi, int length){
int i, j = 0;
char revers[length];
for (i = length; i >= 0; --i){ //loop
*(revers+j) = saisi[i];
++j;
}
printf("%s\n",revers);
}
int main(){
char text[30]; //Array for text
int len;
printf("Saisissez le text:\n");
gets(text);
len = strlen(text);
lettreCount(text, len);
}
but I get all time just an empty string in terminal, how i should to do? thank you
Strings in C are terminated by a null byte. So when you start your loop with i = length the first character you put in the new array is the null byte. This means you have an empty string.
Start your loop at index length-1 so you start at the last character of the string. Then after the loop, you'll need to manually add the terminating null byte to the destination array.
char revers[length+1];
for (i = length-1; i >= 0; --i){ //loop
*(revers+j) = saisi[i];
++j;
}
revers[length] = 0;
Do you name all your functions as lettreCount independent on what they are doing?:)
incompatible pointer to integer conversion strchr
If a string s has length characters (the value returned by the function strlen) then the expression s[length] yields the terminating zero character '\0'. The terminating zero character is being written as the first character of the new string in this for loop in its first iteration
for (i = length; i >= 0; --i){ //loop
*(revers+j) = saisi[i];
++j;
}
As a result the destination array contains an empty string.
The function that creates a reversed string of a given string can be declared and defined the following way
char * copy_reverse( const char *s )
{
size_t n = strlen( s );
char *reversed = malloc( n + 1 );
if ( reversed != NULL )
{
reversed[n] = '\0';
for ( char *p = reversed + n; *s; ++s )
{
*--p = *s;
}
}
return reversed;
}
The first thing you do is copy the null terminator of the string into the first position of the array, so it is normal that it prints as an empty string.
void lettreCount(char *saisi, int length){
int i, j = 0;
char revers[length];
for (i = length; i >= 0; --i){ //loop
*(revers+j) = saisi[i];
The first character you copy is saisi[length] --> revers[0], so you put a '\0' at the start of your string.
void lettreCount(char *saisi, int length){
char revers[length];
int i = length, j = 0;
while (--i >= 0) { //loop
revers[j++] = saisi[i];
}
/* you need to end the string */
revers[j] = '\0';
printf("%s\n",revers);
}
Your code corrected is shown below, as you have some other counseils given in the comments:
#include <stdio.h> /* you need also this file to use fgets, gets or printf */
#include <stdlib.h>
#include <string.h>
// ƒ to revers the word
void lettreCount(char *saisi, int length){
char revers[length];
int i = length, j = 0;
while (--i >= 0) { //loop
revers[j++] = saisi[i];
}
/* you need to end the string */
revers[j] = '\0';
printf("%s\n",revers);
}
int main(){
char text[100]; //Array for text
int len;
printf("Saisissez le text:\n");
/* Don't use the obsolete gets, use fgets */
fgets(text, sizeof text, stdin);
len = strlen(text);
lettreCount(text, len);
}

Trying to "copy" one string in reverse

I've been trying to "copy" one string to another, in reverse.
It kindof works, but it prints some weird symbols.
I've tried setting char copy[length2] but that makes the program not run at all.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define ARR_SIZE 50
int main()
{
char string[ARR_SIZE];
printf("Enter char array!\n");
fgets(string, ARR_SIZE, stdin);
string[strlen(string) - 1] = '\0';
int length = (strlen(string) - 1);
int length2 = (strlen(string) - 1);
printf("%s\t%d\n", string, length);
for (int i = 0; i <= length; i++)
{
printf("INDEX = %d CHAR = %c\n", i, string[i]);
}
printf("%d", length2);
char copy[ARR_SIZE];
for (int i = 0; i <= length2; i++)
{
copy[i] = string[length];
length--;
}
printf("\n%s", copy);
}
These are the minimal modifications I'd make to your code:
#include <stdio.h>
#include <string.h>
// remove unneeded headers
#define ARR_SIZE 50
int main(void)
{
char string[ARR_SIZE];
printf("Enter char array!\n");
fgets(string, ARR_SIZE, stdin);
string[strlen(string) - 1] = '\0';
// remove the -1 on the string length calculation, the NUL terminator is not
// included in strlen's return value
int length = strlen(string);
// no sense in calling strlen twice
int length2 = length;
// fixed `length` now prints the correct length
printf("%s\t%d\n", string, length);
// change from <= to <. The array indices where the characters live are
// [0, length-1].
for (int i = 0; i < length; i++)
{
printf("INDEX = %d CHAR = %c\n", i, string[i]);
}
// fixed `length2` now prints the correct length
printf("%d", length2);
char copy[ARR_SIZE];
for (int i = 0; i < length2; i++)
{
// last character in `string` lives at the `length`-1 index
copy[i] = string[length-1];
length--;
}
// `length2` is the index after the last char in `copy`, this needs
// to be NUL terminated.
copy[length2] = '\0';
// prints the reversed string
printf("\n%s", copy);
}
Demo
Use functions.
Terminate strings with null character \0 or simply 0.
char *copyreverse(char *dest, const char *src)
{
size_t len = strlen(src);
const char *end = src + len - !!len;
char *wrk = dest;
while(len--)
*wrk++ = *end--;
*wrk = 0;
return dest;
}
int main()
{
char dest[10];
char *src = "hello";
printf("`%s` reversed `%s`\n", src, copyreverse(dest, src));
}

strcpy(char*,char a[]) is giving incorrect output. (Reversing a string word by word)

What I'm trying to achieve -
Input: (String literal assumed.) This is a string
Output: string a is This
My naive solution:
Copy the string literal to an char array.
Current contents of the char array str[sizeofstring] : This is a string
Reverse the array word by word and store it in another array.
char reverse[sizeofstring]: sihT si a gnirts
Traverse array reverse from the last to the 0th position. Store it in char array solution.
char solution[sizeofstring]: string a is This
strcpy(pointertoachar, solution). - Because the function needs to return a pointer to char.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse(char *input) {
int n = strlen(input);
char str[n];
char reverse[n];
char solution[n];
char *solutionp = malloc(sizeof(char) * n);
strcpy(str, input);
int last = 0;
int i = 0;
int q = 0;
while (str[i] != '\0') {
if (str[i] == ' ') {
printf("i : %d\n", i);
printf("LAST:%d\n", last);
for (int t = (i - 1); t >= last; t--) {
reverse[q] = str[t];
q++;
}
last = i + 1;
reverse[q] = ' ';
q++;
}
i++;
}
// for the last word.
for (int cc = i - 1; cc >= last; cc--) {
reverse[q] = str[cc];
q++;
}
// Traversing from the last index to the first.
int ii;
int bb = 0;
for (ii = n - 1; ii >= 0; ii--) {
solution[bb] = reverse[ii];
bb++;
}
// This prints the right output.
// printf("%s\n",solution);
// Copying from a char array to pointer pointing to a char array.
strcpy(solutionp, solution);
return solutionp;
}
int main() {
char *str = "This is a string";
char *answer;
answer = reverse(str);
printf("%s\n", answer);
printf("\n");
return 0;
}
The problem:
Steps 1 to 3 are working as intended. For debugging purpose, I tried printing the output of the array which contains the solution and it worked, but when I copy it to char array pointed by a pointer using strcpy and return the pointer, it prints garbage values along with partially right output.
OUTPUT:
string a is This??Z??
There seems to be some problem in step 4. What am I doing wrong?
The major problem in your code is you allocate your temporary buffers one byte too short. You must make enough room for the final '\0' byte at the end of the strings.
You can simplify the code by using an auxiliary function to copy a block in reverse order:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverse_block(char *dest, const char *src, int len) {
for (int i = 0; i < len; i++) {
dest[i] = src[len - i - 1];
}
dest[len] = '\0';
return dest;
}
char *reverse_words(const char *string) {
int i, last;
int len = strlen(string);
char temp[len + 1];
for (i = last = 0; i < len; i++) {
if (string[i] == ' ') {
// copy the word in reverse
reverse_block(temp + last, string + last, i - last);
temp[i] = ' ';
last = i + 1;
}
}
// copy the last word in reverse
reverse_block(temp + last, string + last, len - last);
// allocate an array, reverse the temp array into it and return it.
return reverse_block(malloc(len + 1), temp, len);
}
int main(void) {
const char *string = "This is a string";
printf("%s\n", string);
char *solution = reverse_words(string);
printf("%s\n", solution);
free(solution);
return 0;
}
Now you can improve the code further by implementing a function that reverses a block in place. With this, you no longer need a temporary buffer, you can work on the string copy directly and it simplifies the code.

C. the prints don't come out right, so far haven't been able to figure out why

This is my code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void splitString(char s[]) {
char firstHalf[100] = { 0 };
char secndHalf[100] = { 0 };
for (int i = 0; i < strlen(s) / 2; i++){
firstHalf[i] = s[i];
}
for (int i = strlen(s) /2; i < strlen(s); i++){
secndHalf[i - strlen(s) / 2] = s[i];
}
printf("The string split in two is '%s, - %s' \n", firstHalf, secndHalf);
}
void upperCase(char s[]){
//String in upper case
for (size_t i = 0; i < strlen(s); i++)
s[i] = toupper(s[i]);
printf("The string in uppercase is '%s'", s);
}
void lowerCase(char s[]){
//String in lower case
for (size_t i = 0; i < strlen(s); i++)
s[i] = tolower(s[i]);
printf("The string in lowercase is '%s'", s);
}
int main() {
char s[200];
char splitS[200];
printf("Type a string: ", sizeof( s));
if (fgets(s, sizeof(s), stdin) != 0){
printf("The string is '%s'", s);
}
strcpy(splitS, s);
upperCase(s);
lowerCase(s);
splitString(splitS);
return 0;
}
The correct way it's supposed to print is like this:
The string is 'Hello world'
The string in uppercase is 'HELLO WORLD'
The string in lowercase is 'hello world'
The string split in two is 'Hello, - world'
But instead it prints like this:
The string is 'Hello world
'The string in uppercase is 'HELLO WORLD
'The string in lowercase is 'hello world
'The string split in two is 'Hello , - world
'
You need to read the documentation for fgets() (my emphasis):
fgets() reads in at most one less than size characters from stream and stores them into the buffer pointed to by s. Reading stops after an EOF or a newline. If a newline is read, it is stored into the buffer. A terminating null byte ('\0') is stored after the last character in the buffer.
Since you are typing in these lines with line break characters at the end, you need to remove them in your code.
You have to put null terminator
void splitString(char s[]) {
char firstHalf[100] = { 0 };
char secndHalf[100] = { 0 };
// u need to add null terminator '\0' at the end of string
// so u can add it in for loop or set i outside of loop
for (size_t i = 0; i < strlen(s) / 2; i++){
firstHalf[i] = s[i];
**firstHalf[i+1] = '\0';**
}
for (size_t i = strlen(s) /2; i < strlen(s); i++){
secndHalf[i - strlen(s) / 2] = s[i];
**secndHalf[i+1] = '\0';**
}
printf("The string split in two is '%s, - %s' \n", firstHalf, secndHalf);
}
The fgets function will read a newline and append it to the input string of there's room for it.
You need to check if the last character in the string is \n and if so set it to zero to trim it.
This is happening because fgets retains a newline at the end of the input string, and also because you do not printf a newline yourself.
So the result, is that newline is being printed in the wrong place, splitting your message, and the ' appears on the next line.
An easy way to remove the newline from the entry is with
s [ strcspn(s, "\r\n") ] = 0;
but don't forget to add the \n to the end of the printf formatting strings.
I thing use scanf with format specifier %[^\n]s so you can skip the new line instated of fgets and add \n in every printf.
Complete working code :
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void splitString(char s[]) {
char firstHalf[100] = { 0 };
char secndHalf[100] = { 0 };
int i;
for ( i = 0; i < strlen(s) / 2; i++){
firstHalf[i] = s[i];
}
for ( i = strlen(s) /2; i < strlen(s); i++){
secndHalf[i - strlen(s) / 2] = s[i];
}
printf("\n The string split in two is '%s, - %s' \n", firstHalf, secndHalf);
}
void upperCase(char s[]){
//String in upper case
int i;
for (i = 0; i < strlen(s); i++)
s[i] = toupper(s[i]);
printf("\n The string in uppercase is '%s'", s);
}
void lowerCase(char s[]){
//String in lower case
int i;
for ( i = 0; i < strlen(s); i++)
s[i] = tolower(s[i]);
printf("\n The string in lowercase is '%s'", s);
}
int main() {
char s[200];
char splitS[200];
printf("Type a string: %ld", sizeof( s));
if (scanf("%200[^\n]s", s)!= 0){ //fgets(s, sizeof(s), stdin)
printf("\n The string is '%s'", s);
}
strcpy(splitS, s);
upperCase(s);
lowerCase(s);
splitString(splitS);
return 0;
}
OR
if you want use fgets only then find new line char in string and make it NULL and add new line char '\n' in every printf .
Code need to change is:
if ( fgets(s, sizeof(s), stdin) != 0){
int i;
for(i = 0 ; i < sizeof( s) ; i++ ){
if(s[i] == '\n'){
s[i] = '\0';
break;
}
}
printf("\n The string is '%s'", s);
}

Assign value to char in array

I'm trying to brush up on my C/C++ and I seem to have forgotten how to properly manipulate char arrays.
Code:
#include <iostream>
#include <string.h>
void reverse(char* str)
{
int numChar = strlen(str);
char *reversed = (char*)malloc(sizeof(char) * (numChar + 1));
int i = numChar;
int j = 0;
while(i >= 0)
{
reversed[j] = str[i];
j++;
i--;
printf("%c", reversed[j]);
}
printf("%s", reversed);
}
int main()
{
char* str;
strcpy(str, "apple\0");
reverse(str);
return 0;
}
I'm very certain I'm not doing what I intend to with reversed[j] = str[i] as reversed comes out empty. What's the correct way to go about this?
From first glance, In main(), memory has to be allocated to character pointer str before referencing it in strcpy
int main()
{
char* str = malloc(6) or use char str[6];
// or char *str = "apple"; is sufficient, strcpy is not required in this case
strcpy(str, "apple\0");
reverse(str);
return 0;
}
Another one :
In reverse() function, you will have to increment j after printing
while(i >= 0)
{
reversed[j] = str[i];
printf("%c", reversed[j]);
j++; //Moved here
i--;
}
reversed[j] = '\0' //Null termination
printf("\n %s", reversed);
or only the below two statements would be sufficient enough to post increment j and decrement i
reversed[j] = str[i--];
printf("%c", reversed[j++]);
Since you start with i being the strlen of the input string (e.g. HAHA -> 4), you start copying at haha[4], which is the null byte at the end of the string. IOW you just null terminated your output right at the start. Try setting i to numChar - 1.
(After fixing the problem Santosh A mentioned)
And then, make sure you null terminate the result!

Resources