Inverting a string with ANSI C & Pointers

closed account (1w64216C)
Swap case) Write a function that inverts a string by changing all uppercase letters to lowercase and lowercase letters to uppercase and displays the symbols in reversed order. The function prototype is:
 
  void swapCase(char *s)

Write a test program that prompts the user to enter a string and invokes the function, and displays the result string from the function. Here is a sample run:
1
2
  Enter a string: The capital of Bulgaria is Sofia
  The new string is: AIFOs SI AIRAGLUb FO LATIPAC EHt

I would really appreciate some help for this exercise.
I don't doubt this is your homework.
What's your progress so far?
closed account (1w64216C)
I figured out I need to use the std::transform and std:reverse functions. Working on it atm.
For starters, do you know how to reverse a string?

I figured out I need to use the std::transform and std:reverse functions. Working on it atm.

You don't necessarily have to use those. Just a simple for-loop, strlen(), isupper(), toupper() and tolower() is all you need.
Last edited on
closed account (1w64216C)
I'm doing something wrong with the blasted pointers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <cstring>

using namespace std;

void swapCase(char *s)
{
    for (int i = 0; i <= *s; i++)
    {
        if(isupper(s + i) == 1)
        {
            tolower(s + i);
        }
        else
        {
            toupper(s + i);
        }
    }
}

int main()
{
    int char str[100];
    cout << "Enter a string: "
    cin >> str;
}
You did not make much progress did you?
closed account (1w64216C)
I did not pay enough attention to the course for about 2 weeks and I have a quiz + HW deadline today. Trying to cope with the material and solve my other assignment asap, but there is something rotten in those c++ pointers and it impedes me.
for (int i = 0; i <= *s; i++)
*s will get the character at the start of the C-string s. For example, if s == "Hello", *s == 'H'. It will then be implicitly converted to an int, resulting in the ASCII value of 'H', 72. As you don't increment s, your for loop is essentially the same as doing for( int i = 0; i <= 72; i++ )

On a similar note, if(isupper(s + i) == 1) s == 72, and as long as i <= 18 (ASCII character of 'Z' is 90), this expression will return true.
This expression will most likely return false, as you're passing a pointer (an address in memory), which when converted into an int, will be an extremely large value. It's outside the range of the ASCII values of uppercase characters(65 to 90, inclusive).
Also, you isupper() isn't guaranteed to return 1, if it's true.
A value different from zero (i.e., true) if indeed c is an uppercase alphabetic letter. Zero (i.e., false) otherwise.

Coincidentally, that's how C++ evaluates expressions like this if( 100 ). This expression will always be true. However, if( 0 ) will always be false.
Basically, you can just write if( isupper( /* ... */ ) ).

tolower(s + i);
tolower() returns its argument's lowercase variant if it has one.
Return Value
The lowercase equivalent to c, if such value exists, or c (unchanged) otherwise.
The value is returned as an int value that can be implicitly casted to char.

http://www.cplusplus.com/reference/cctype/tolower/

Now onto how to solve your problem.
Notice that this problem can be split up into 2 sub-problems:
- Reversing the string
- Flipping the case of each character
If you know how to reverse a string, that's the hardest part of your problem solved.
The second sub-problem is really easy. Your code demonstrated that you understood what you needed to do.
1
2
3
4
5
6
7
8
if(isupper(s + i) == 1)
{
    tolower(s + i);
}
else
{
    toupper(s + i);
}
Last edited on
closed account (1w64216C)
I'm making progress, but the reverse function only reverses the first word of the string. Any suggestions?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <iostream>
#include <cstring>

using namespace std;

void swapCase(char *s)
{
    char *front, *rear, temp;
    front = s;
    rear = s+strlen(s) - 1;
    while( front < rear)
    {
        temp = *front;
        *front = *rear;
        *rear = temp;
        front++;
        rear--;
    }

}

int main()
{
    char input[100];

    cout << "Enter a string: ";
    cin >> input;
    swapCase(input);
    cout << input << endl;


	return 0;
}
I'm assuming you tried to enter something like Hello World. cin stops reading as soon as it sees a whitespace character, so only Hello will get passed to swapCase. To fix, use cin.getline().
1
2
3
4
5
const int MAX{ 100 };
char input[MAX]{};

cout << "Enter a string: ";
cin.getline( input, MAX );

http://www.cplusplus.com/reference/istream/istream/getline/
> Trying to cope with the material and solve my other assignment asap,
> but there is something rotten in those c++ pointers and it impedes me.

Divide and conquer: write small functions, each simple function doing one small bit, and it won't be as hard.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <cctype>
#include <algorithm>

char flip_case( char c ) { return std::isupper(c) ? std::tolower(c) : std::toupper(c) ; }

char* end_of_cstr( char* cstr ) // return pointer to the terminating null character
{
    if( cstr == nullptr ) return nullptr ;
    char* end = cstr ;
    while( *end != 0 ) ++end ; // get to the terminating null character
    return end ;
}

void transform_and_print( char* cstr ) // using std::transform, std:::reverse
{
    if( cstr != nullptr )
    {
        char* end = end_of_cstr(cstr) ; // the terminating null character
        std::transform( cstr, end, cstr, flip_case ) ;
        std::reverse( cstr, end ) ;
    }
    std::cout << cstr << '\n' ;
}

void swap_flipped( char& a, char& b )
{
    char temp = flip_case(a) ;
    a = flip_case(b) ;
    b = temp ;
}

void transform_and_print_2( char* cstr ) // C-style code
{
    if( cstr != nullptr && *cstr != 0 ) // if not an empty string or null
    {
        char* right = end_of_cstr(cstr) - 1 ; // just before the terminating null character
        for( char* left = cstr ; left <= right ; ++left, --right ) swap_flipped( *left, *right ) ;
    }
    std::cout << cstr << '\n' ;
}

int main()
{
    char cstr[100] = "The capital of Bulgaria is Sofia." ;
    // std::cin.getline( cstr, sizeof(cstr) ) ;
    std::cout << cstr << '\n' ;

    transform_and_print(cstr) ;
    transform_and_print_2(cstr) ; // should get back the original string
}

http://coliru.stacked-crooked.com/a/30345cf2f329cf6a
@JLBorges
Your solution is far from complex.
Topic archived. No new replies allowed.