简体   繁体   中英

How do I reverse a c string without the use of strlen?

I'm trying to implement a void function that takes a c string as its only parameter and reverses it and prints it. Below is my attempt at a solution however I'm not sure how to go about this problem.

void printBackwards(char forward[]) {
    int i = 0;
    char backwards[];
    while (forward[i] != '\0') {
        backwards[i] = forward[-i - 1];
        i++;
    }
    cout << backwards;

}

By using abstractions, like, your code will be much better at communication WHAT it is doing instead of HOW it is doing it.

#include <iostream>
#include <string>
#include <ranges>

int main()
{
    std::string hello{ "!dlrow olleH" };
    for (const char c : hello | std::views::reverse)
    {
        std::cout << c;
    }
    
    return 0;
}

Under such a condition, I guess you are expected to use recursion.

void printBackwards(char forward[]) {
    if (!forward[0])
        return;
    printBackwards(forward + 1);
    cout << forward[0];
}

Not being able to use strlen , we'll calculate it ourselves using a simple for loop. Then dynamically allocate a suitable buffer (add one character for the null terminating char, and I "cheated" by using calloc to zero the memory so I don't have to remember to set the null terminator. Then anoher simple loop to copy the original into the result in reverse.

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

char *rev(char *s) {
  size_t i;
  char *s2 = s; // A pointer to the beginning as our first loop modifies s

  for (i = 0; *s; s++, i++);

  char *result = calloc(0, i + 1);

  if (!result) return NULL; // In case calloc didn't allocate the requested memory.

  for (size_t j = 0; j < i; j++)
    result[j] = s2[i - j - 1];

  return result;
}

Use a template

#include <iostream>

template<int N, int I=2>
void printBackwards(char (&forward)[N]) {
    std::cout << forward[N-I];
    if constexpr (I<N) printBackwards<N, I+1>(forward);
}

int main() {
    char test[] = "elephant";
    printBackwards(test);
}

Assuming you want to reverse the string rather than just printing it in reverse order, you first need to find the last character location (actually the position of the null terminator). Pseudo-code below (since this is an educational assignment):

define null_addr(pointer):
    while character at pointer is not null terminator:
        increment pointer
    return pointer

Then you can use that inside a loop where you swap the two characters and move the pointers toward the center of the string. As soon as the pointers become equal or pass each other the string is reversed:

define reverse(left_pointer):
    set right_pointer to null_addr(left_pointer)
    while right_pointer > left_pointer plus one:
        decrement right_pointer
        swap character at left_pointer with character at right_pointer
        increment left_pointer

Alternatively (and this appears to be the case since your attempt doesn't actually reverse the original string), if you need to print the string in reverse order without modifying it, you still find the last character. Then you run backwards through the string printing each character until you reach the first. That can be done with something like:

define print_reverse(pointer):
    set right_pointer to null_addr(pointer)
    while right_pointer > pointer:
        decrement right_pointer
        print character at right_pointer

That's probably better than creating a new string to hold the reverse of the original, and then printing that reverse.


One thing you should keep in mind. This very much appears to be a C-centric question, not a C++ one (it's using C strings rather than C++ strings, and uses C header files). If that's the case, you should probably avoid things like cout .

You can make a fixed-size buffer and create new ones if needed. Fill it reverse by moving the string offset back with every inserted character. Chars exceeding the buffer are returned to be processed later, so you can make a list of such buffers:

template<int SIZE>
struct ReversedCStr
{
  static_assert(SIZE > 10); // just some minimal size treshold
  // constexpr
  ReversedCStr(char const* c_str, char const** tail = nullptr) noexcept
  {
    for(buffer[offset] = '\0'; *c_str != '\0';)
      {
        buffer[--offset] = *c_str++;
        if(offset == 0) break;
      }
    if(tail) *tail = c_str;
  }
  //constexpr
  char const* c_str() const noexcept { return buffer.data()+offset;};
private:
  size_t offset = SIZE -1;
  std::array<char,SIZE> buffer;
};

The tag is 'C++' so I assume you use C++ not C. The following code is C++11 so it should fit in every modern project. I posted the working example on godbolt.org .

It doesn't allocate memory, and is completely exception-free. The maximum memory wasted is {buffer_size + sizeof(char*)*number_of_chunks}, and can be easily turned into a list of reversed chunks like this:

  char const* tail;
  std::vector<ReversedCStr<11>> vec;
  for(vec.emplace_back(str,&tail); *tail != '\0';)
    vec.emplace_back(tail,&tail);

While there seems to be several working answers, I thought I'd throw my hat in the stack (pun intended) since none of them take advantage of a FILO data structure (except @273K's answer, which uses a stack implicitly instead of explicitly).

What I would do is simply push everything onto a stack and then print the stack:

#include <stack>
#include <iostream>

void printBackwards(char forward[]) {
    // Create a stack to hold our reversed string
    std::stack<char> stk;

    // Iterate through the string until we hit the null terminator
    int i = 0;
    while (forward[i] != '\0'){
        stk.push(forward[i]);
        ++i;
    }

    // Iterate through the stack and print each character as we pop() it
    while (stk.size() > 0){
        std::cout << stk.top();
        stk.pop();
    }
    // Don't forget the newline (assuming output lines should be separated)
    std::cout << '\n';
}

int main(int argc, char* argv[]){
    char s[] = "This is a string";
    printBackwards(s);
    return 0;
}

Hi guys as promised I have come back to add my own answer. This is my own way using array subscripts and using what I currently know.

#include <iostream>
using namespace std;

void printBackwards(char[]);

int main()
{
    char word[] = "apples";
    printBackwards(word);


    return 0;
}

void printBackwards(char word[]) {
    char* temp = word;
    int count = 0;
    while (*temp++ != '\0') {
        count++;
    }
    for (int i = count - 1; i >= 0; i--) {
        cout << word[i];
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM