0

I'm brand new to C. I've been going through exercises in a book I found, and have been having a lot of trouble understand strings. For this program, I'm simply trying to reverse a string that is read from user input.

The code I currently have:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 300

void reverseStr(char *str, int len){
    int i;
    char temp[len];
    for (i = len; i >= 0; i--){
        strncat(temp, &str[i], 1);
    }
    strcpy(str, temp);
}
int main(){
    char *buffer;
    size_t buffsize = 32;
    size_t characters;
    while (characters != 1){
        buffer = (char *)malloc(buffsize * sizeof(char));
        if ( buffer = NULL){
            perror("Unable to allocate buffer");
            exit(1); 
        }

        printf("Type something: ");
        characters = getline(&buffer, &buffsize, stdin);
        printf("%zu characters were read.\n", characters);
        printf("You typed: %s", buffer);
        reverseStr(buffer, buffsize);
        printf("backwards: %s\n", buffer);
    }

}

What I currently have does reverse the string, but it also prepends a bunch of, what I assume to be null characters in the beginning.

Sample input/output:

Type something: sdf
4 characters were read.
You typed: sdf
backwards: 0s����
fds

As you can see, sdf does return fds as it should, but with extra unwanted characters prepended to it.

To further add to my confusion, I have gotten this to work properly before in another program I made.

/* This should be compiled with -ansi flag */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX 3000

void reverseStr(char str[MAX], int len);
int getline(char s[], int lim);

int main(){
    /* Read below on why we use a char array instead of a string, 
     * it's very important we understand this */
    char line[MAX];
    int len = strlen(line)-1;

    while((len=getline(line, MAX))>0){
        len = strlen(line)-1;
        reverseStr(line, len);
        printf("%s\n", line);
    }
}

void reverseStr(char str[MAX], int len){
    int i;
    char temp[len];
    for (i = len; i >= 0; i--){
        strncat(temp, &str[i], 1);
    }
    strcpy(str, temp);
}

int getline(char s[],int lim){
  int i,c;

  for(i=0;i<lim-1 && (c=getchar())!=EOF && c!='\n';++i)
    s[i] = c;
  if( c == '\n')
  {
    s[i]=c;
    ++i;
  }
  s[i]='\0';
  
  return i;
}

Output of second program:

sdf

fds
sdfsdfsdf

fdsfdsfds

The getline() in the second program is taken straight from the book. I'm guessing this must be an old, deprecated way of doing things though? It appears to be a built-in function in later versions of C.

Hoswoo
  • 63
  • 1
  • 7
  • Variables need to be initialized before you use them. – Scott Hunter Jan 03 '22 at 19:14
  • 2
    Does this answer your question? [Reversing a string in C](https://stackoverflow.com/questions/784417/reversing-a-string-in-c) – Ted Lyngmo Jan 03 '22 at 19:15
  • 1
    "_This should be compiled with -ansi flag_" - For gcc, that means C90. Are you sure you want that? C17(18) is available too via `-std=c17` (or `-std=c18`). C90 is 27 years older than C17. – Ted Lyngmo Jan 03 '22 at 19:17
  • @TedLyngmo That solution worked for me, thank you. Perhaps my approach to the problem just isn't a good one. That solution is a bit tough for me to understand though however. Also I will note not to use ansi, thank you for mentioning that. – Hoswoo Jan 03 '22 at 19:34
  • 1
    I see some close votes as a duplicate, but I appreciate that you provided a complete example and explained your expectations and actual results and even an alternate approach. Well done asking. Be aware, this may be closed as a duplicate only because the title looks like you're just asking how to reverse a string which is a well known thing. A better title may be "Why are there unwanted characters being added to the string I'm trying to reverse?" – Wyck Jan 03 '22 at 19:41
  • I was afraid it would, thank you though. I've already gotten great answers so no problem if it does! – Hoswoo Jan 03 '22 at 19:44

1 Answers1

2

This can more easily be done by just copying in the characters in reverse, then adding a NULL terminating byte at the end.

#include <stdio.h>
#include <string.h>

void reverse_string(char *str, char *rev_str) {
    int j = 0, i;
    for (i = strlen(str) - 1; i >= 0; i--) {
        rev_str[j++] = str[i];
    }
    rev_str[j] = '\0';
}

int main() {
    char *str = "123456789";
    char rev_str[strlen(str)];
    printf("%s\n", str);
    reverse_string(str, rev_str);
    printf("%s\n", rev_str);

    return 0;
}

Output:

123456789
987654321
codyne
  • 552
  • 1
  • 9
  • Ah, I can't believe I didn't think about this. I just read about the null terminator characters haha. This solution was much easier for me to follow, thank you! – Hoswoo Jan 03 '22 at 19:41
  • 1
    ... and if you want reversing in-place: [demo](https://godbolt.org/z/o8ze5jM6G) – Ted Lyngmo Jan 03 '22 at 19:45
  • @TedLyngmo Hmm, so I notice that that solution gives me a segmentation fault when I use a char pointer instead of a char array. Why is that? – Hoswoo Jan 03 '22 at 20:01
  • 1
    @Hoswoo Because it's not really a `char*` but a `const char*`. You can't change string literals, like `reverse_string("change me");`. You can define a `char*` to such a string literal (which is bonkers) but actually changing them makes the program have _undefined behavior_. Always define them with `const` to prevent segfaults and to get compilation errors instead: `const char *foo = "Hello world;"` instead of `char *foo = "Hello world";`. – Ted Lyngmo Jan 03 '22 at 20:02
  • 1
    @TedLyngmo I see, I will keep note of that. – Hoswoo Jan 03 '22 at 20:04