I'm currently doing an exercise, where I have to find a way to "pass" the level (It's a reverse engineering exercise, I decompiled it with IDA).
The level function consists of 3 while loops, from each I have to break to get to the next one. To pass the level, I have to input something that will pass through the 3 checks.
Code is as follows:
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
memset(Buffer, 0, sizeof(Buffer));
stream = _acrt_iob_func(0);
fgets(Buffer, 1020, stream);
if ( strlen(Buffer) >= 0x1E )
break;
}
if ( first_check_string(Buffer) )
break;
}
if ( second_check_string(Buffer) )
break;
}
return printf(aWellDone, Buffer[0]);
}
The first_check_string function:
int __cdecl first_check_string(_BYTE *str_addr)
{
while ( *str_addr )
{
if ( (char)*str_addr < 97 || (char)*str_addr > 122 )
return 0;
if ( ((char)*str_addr - 97) % 3 )
return 0;
++str_addr;
}
return 1;
}
The second_string_check function:
BOOL __cdecl second_check_string(char *Str)
{
int v2; // [esp+4h] [ebp-8h]
char *i; // [esp+8h] [ebp-4h]
if ( strlen(Str) % 4 )
return 0;
v2 = 0;
for ( i = Str; *(_DWORD *)i; i += 4 )
v2 ^= *(_DWORD *)i;
return v2 == 1970760046;
}
For the first if, i just have to enter a string longer than 1E, or 30 in decimal.
The second, I have to enter only a-z character, but only ones that their ascii - 97 is divisible by 3. So only options are: a, d, g, j, m, p, s, v, y.
But there's a catch - I have to enter at least 1019 characters, since otherwise, the fgets will get the newline 0x0A character, and the first_check_string function will not pass.
So I enter 1019 "a"s for example.
I pass the first 2 ifs. But the 3rd if function second_check_string requires my string to be divisble by 4, which can't be if I enter 1019 chars. And if I enter less, the first_check_string function will encounter the 0x0A newline char and return 0.
If anyone got any idea of how could I approach this, I would be grateful.
GENERALIZED SOLUTION
To enter a NUL 0x00 byte, we need to redirect the program to read from a file instead from the user's keyboard.
To do so, we execute the program as follows:
prog.exe < file
this makes the standard input, which fgets uses, become the file.
In the file we can any bytes we want, including the NUL character.
We can do so either by using a programming language to write to that file, or a hex editor (I used 010 editor).
Cheers to EVERYONE who helped me!
Input a manual NUL character, '\0' at one past a multiple of 4 offset (so the apparent string length is a multiple of 4). fgets will happily retrieve it as part of a string without stopping, but your tests using C-style string definition will stop at the NUL, and never see a following newline, nor any other character violating the rules being checked. This dramatically relaxes the restrictions; make it long enough to pass the basic break in the innermost loop, then put a NUL after a multiple of four characters has been entered, and after that you can enter anything for the remainder of the 1019 characters because the rules won't be checked past the NUL.
Kudos to #Shadowranger for noting the that a strategic \0 simplifies the problem immensely!
The following is a minor adaptation of the code given in the original problem.
int first_check_string( char *cp ) {
while ( *cp ) {
if( !islower( *cp ) ) // 'a'- 'z'
return 0;
if ( (*cp - 'a') % 3 ) // but only every third of those pass muster
return 0;
++cp;
}
puts( "Passed 1st check" );
return 1;
}
bool second_check_string(char *Str) {
int v2; // [esp+4h] [ebp-8h]
char *i; // [esp+8h] [ebp-4h]
if ( strlen(Str) % 4 )
return 0;
v2 = 0;
for ( i = Str; *(uint32_t *)i; i += 4 )
v2 ^= *(uint32_t *)i;
printf( "Aiming for %08X... Got %08X\n", 1970760046, v2 );
return v2 == 1970760046;
// Hides 0x7577696E as a decimal value
// ASCII decoding: 0x75-'u', 0x77-'w', 0x69-'i', 0x6E-'n' ==> "uwin"... :-)
}
int main() {
char Buffer[1020] = {
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
0, 0, 0, 'd', 0, 0, 0, 'd',
'n', 'i', 'w', 'u', 0, 0, 0, 0, // 7577696E = 'u', 'w', 'i', 'n';
};
while( 1 ) {
while ( 1 ) {
while ( 1 ) {
/* Using compile-time array instead of loading binary file */
if ( strlen(Buffer) >= 0x1E )
break;
}
if ( first_check_string(Buffer) )
break;
}
if ( second_check_string(Buffer) )
break;
else {
puts( "Failed 2nd check" );
getchar();
}
}
puts( "Well Done" );
return 0;
}
Passed 1st check
Aiming for 7577696E... Got 7577696E
Well Done
The 1st 32 bytes followed by 0 satisfy the minimum string length. (The compile time array skirts the OP problem of reading up to 1020 bytes, with an embedded NULL, from a file. The effect is the same, regardless.)
The XOR of those (even quantity) 'a' characters results in zero; a clean start for more processing.
The XOR of bytes 32-35 (treated as an unsigned int) with the next 4 bytes means that v2 is still zero...
Finally, hidden behind that NULL (thanks Shadowranger), and all those balancing XOR's, is the literal unsigned integer (32 bits) that is the key to matching. Note that 'endian-ness' comes into play, and the "u win" message must be reversed (on my hardware).
And the next 4 NULL bytes will terminate the 2nd check, so anything in the buffer beyond that is ignored...
Good fun!
Related
I am new to C, and I am learning shift operation.
I understand the shift operation if the data is a binary number, but for my code in this case, I want to implement the case that 't', 'h', 'i', 's', ' ', '\0' are all discarded or shifted, and move 'a' to the first element of this string.
Can I do this behavior by using shift operator? If so, why is so?
Really appreciated.
char words[10] = {'t', 'h', 'i', 's', ' ', '\0', 'a', 'b', 'c'};
The shift operator you are talking about is basically bitwise operator. You can't use this to shift array of characters.
To accomplish what you asked, you can write a function. Suppose you want left shift -
int leftShift(char *words, int len)
{
int i;
for(i = 1; i < len; i++)
{
words[i - 1] = words[i];
}
len--;
return len;
}
What this function does? - it takes an array and length of that array as parameter, and perform left shift one time.
So then from your main function you can just call this method any number of times you want -
int main(void) {
char words[10] = {'t', 'h', 'i', 's', ' ', '\0', 'a', 'b', 'c'};
int len = 10;
len = leftShift(words, len); // left shift one time - this will discard 't'
len = leftShift(words, len); // left shift one time - this will discard 'h'
//finally print upto len, because len variable holds the new length after discarding two characters.
int i;
for(i = 0; i < len; i++)
{
printf("'%c', ", words[i]);
}
return 0;
}
This is very trivial idea, surely this approach can be improved in many ways. But I think you got the basic idea.
I'm a little confused with the string compare strcmp() function in C.
When you have two strings, grass and grapes and you use strcmp(grass, grapes); which results in 39, or any positive number, does this mean that "grapes" is alphabetized before "grass", or the opposite?
I know that if it results to 0, they're equal.
strcmp function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs until the characters differ or until a terminating null-character is reached.
This means that, this function performs a binary comparison of the characters.
The following program should give you an Idea about how strcmp works:
#include <stdio.h>
#include <string.h>
int stringcmp(char *s1, char *s2){
int count = 0;
while (s1[count] == s2[count]) {
if (s1[count] == '\0' || s2[count] == '\0')
break;
count++;
}
if (s1[count] == '\0' && s2[count] == '\0'){
return 0;
}
if(strlen(s1) < strlen(s2)){
return -1;
}else{
return 1;
}
}
int main(void){
char *b = "grass";
char *a = "grapes";
if(stringcmp(a, b) == 0){
printf("Are equal.\n");
printf("Length of A = %zu\n",strlen(a));
printf("Length of B = %zu\n",strlen(b));
printf("Return of stringcmp = %d\n",stringcmp(a, b));
}else{
printf("Are not equal.\n");
printf("Length of A = %zu\n",strlen(a));
printf("Length of B = %zu\n",strlen(b));
printf("Return of stringcmp = %d\n",stringcmp(a, b));
}
return 0;
}
Output:
Are not equal.
Length of A = 5
Length of B = 6
Return of stringcmp = -1
If you swap a with b you get:
Are not equal.
Length of A = 6
Length of B = 5
Return of stringcmp = 1
And if A and B are the same:
Are equal.
Length of A = 5
Length of B = 5
Return of stringcmp = 0
The return value of strcmp is defined in C99 7.21.4
The sign of a nonzero value returned by the comparison functions memcmp, strcmp,
and strncmp is determined by the sign of the difference between the values of the first
pair of characters (both interpreted as unsigned char) that differ in the objects being
compared.
So if the result is positive, it means the second argument comes after the first.
It's not exactly alphabetical order, but is rather dependent on the underlying encoding of the characers. For instance, in ASCII, 'B' < 'a', because 'B' is encoded as 66 and 'a' is 97. If the characters are all letters of the same case, this will be equivalent to alphabetical order in all (non-multibyte) encodings I'm familiar with, but I don't believe this is required.
For cases like "grass" vs "grapes", it'll just keep scanning until it finds characters that differ ('s' vs 'p' in this case), and then make the decision. A special case of this is when one string is a substring of another: e.g. "grape" vs "grapes". For that case, you just need to remember that "grape" is actually { 'g', 'r', 'a', 'p', 'e', '\0' }, and apply the normal rule: '\0' < 's', so "grape" comes before "grapes".
This would be a conforming implementation of strcmp:
int strcmp(const char *a, const char *b) {
size_t i = 0;
while (a[i] || b[i]) {
if (a[i] != b[i]) {
if (a[i] < b[i]) return -1;
else return 1;
}
i++;
}
return 0;
}
I was faced with a question recently in C. We have a phone's numpad with following layout:
1[abc] 2[def] 3[ghi]
4[jkl] 5[mno] 6[pqr]
7[st] 8[uv] 9[wx]
0[yz]
How to come up with an API which gives all possible combinations of characters belonging to each number for a given numeral input.
For e.g. input = 1234
Then the API should print all possible combinations of characters-
adgj bdgj cdgj aegj begj cegj.. and so on.
Is there a simple way to do it? Apart from hardcoded nested for loops.
I was given a hint as recursion but couldn't figure a way out of it.
Recursion is a good solution for such problems, where you must find combinations. The advantage over nested loops is that recursion works for strings of any length.
In your case, you need a function that takes:
the original string
an auxiliary char buffer for the solution* and
the current index, which starts at 0.
Recursive functions require a termination condition: When you have reached the end of the original string, print it and return.
Otherwise, take the next digit, check whether it is valid, determine the letters associated with it and then call the function for each of the letters. That is, for each letter, copy it to the solution at the current index, then call the function with the next index.
Below's an example implementation that uses an intermediate function to do some house-keeping:
#include <stdlib.h>
#include <stdio.h>
/*
* Recursive back-end, that produces all combinations in sol.
*/
void alpha_r(const char *str, char *sol, int index)
{
const char *combo[] = {
"yz", "abc", "def", "ghi", "jkl", "mno", "pqr", "st", "uv", "wx"
};
if (str[index] == '\0') {
printf("%s\n", sol);
} else {
int k = str[index] - '0';
const char *p = combo[k];
while (*p) {
sol[index] = *p++;
alpha_r(str, sol, index + 1);
}
}
}
/*
* Non-recursive front-end that checks the string for validity
* and creates a temporary buffer for the solutions.
*/
void alpha(const char *str)
{
int len = 0;
while (str[len]) {
if (str[len] < 0 || str[len] > '9') {
fprintf(stderr, "Invalid input.\n");
return;
}
len++;
}
char sol[len + 1];
sol[len] = '\0';
alpha_r(str, sol, 0);
}
int main()
{
alpha("123");
return 0;
}
*) You could also use the string itself to store the solutions.
(That is not the standard layout for a phone, by the way.)
The tricky part is handling the data structures. It is handy that the input string consists of numbers, because then we can use the digits in the string to index an array that holds the possible letters for each number.
The idea is to modify an output string at a particular index using a for loop to go over all the possible replacements at that index. Then recursively move to the next index in the output array in the body of the for loop.
If you reach the end of the array, then print and return.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* data[] = {"0", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7prs", "8tuv", "9wxy"};
char* input = "23456783";
char* arr;
void current(int index)
{
if(index == strlen(input)) printf("%s\n", arr);
else
{
for(int i = 0; i < strlen(data[input[index] - '0']); ++i)
{
arr[index] = data[input[index] - '0'][i];
current(index + 1);
}
}
}
void main()
{
arr = malloc(strlen(input) + 1);
arr[strlen(input)] = '\0';
printf("%s\n\n", input);
current(0);
}
A way to find the combinations that you are looking for could be bitwise logic, with a binary number and an integer. The binary number would be as long as the string, with 0's and 1's acting as on and off switches for what is included and excluded in the string. The thing here is that we use base 3 or 4 depending on the number "pressed", and
If base four, then some if statements have to be applied to move the ones along that are actually base three.
Recursion is just a sneaky way of nesting four for loops. Here's what the code looks like
#include <stdio.h>
void sneaky( int depth, int maxDepth, char str[] )
{
char c, start;
start = 'a' + depth * 3;
for ( c = start; c < start + 3; c++ )
{
str[depth] = c;
str[depth+1] = '\0';
if ( depth == maxDepth )
printf( "%s\n", str );
else
sneaky( depth + 1, maxDepth, str );
}
}
int main( void )
{
char str[5] = { 0 };
sneaky( 0, 3, str );
}
You can also solve this problem, and similar combinatorial problems, with a simple counting algorithm. A counting algorithm emulates natural counting, in which you increment the least significant digit from 0 to 9. When the least significant digit wraps from 9 back to 0, the next digit to the left is incremented.
The same can be done to solve the OP's problem. But in this case, the digits have either two or three possible values. And if you examine the pattern in the OP, it's readily apparent that the least significant digit is on the left. In the pattern
adgj bdgj cdgj aegj
you can see that a becomes b, b becomes c, and when c wraps back to a, then d becomes e.
Here's the code
#include <stdio.h>
#include <stdlib.h>
static char InitialValue[] = { 'y', 'a', 'd', 'g', 'j', 'm', 'p', 's', 'u', 'w' };
static char NextValue[] = { 'b', 'c', 'a', 'e', 'f', 'd', 'h', 'i', 'g',
'k', 'l', 'j', 'n', 'o', 'm', 'q', 'r', 'p',
't', 's', 'v', 'u', 'x', 'w', 'z', 'y' };
static void error( char *msg )
{
fprintf( stderr, "%s\n", msg );
exit( EXIT_FAILURE );
}
int main( void )
{
int i, oldDigit;
char str[12];
// get the input string from the user
printf( "Enter the input string: " );
fflush( stdout );
if ( scanf( "%10s", str ) != 1 )
error( "whatever" );
// convert the input string to the corresponding first output string
for ( i = 0; str[i] != '\0'; i++ )
{
if ( str[i] < '0' || str[i] > '9' )
error( "invalid input string" );
str[i] = InitialValue[str[i] - '0'];
}
printf( "%s\n", str );
// use a simple counting algorithm to generate the string combinations
for (;;)
{
for ( i = 0; str[i] != '\0'; i++ )
{
oldDigit = str[i]; // save the current digit
str[i] = NextValue[oldDigit - 'a']; // advance the digit to the next value
if ( str[i] > oldDigit ) // if the digit did not wrap
break; // then we've got a new string
}
if ( str[i] == '\0' ) // if all the digits wrapped
break; // then we're done
printf( "%s\n", str ); // output the new string
}
return( EXIT_SUCCESS );
}
#include <stdio.h>
#include <string.h>
void main()
{
char alfavita[30] =
{
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j',
'k',
'l',
'm',
'n',
'o',
'p',
'q',
'r',
's',
't',
'u',
'v',
'w',
'x',
'y',
'z'
};
char str[20];
printf("Give a word:\n");
gets(str);
for(int i=0;i<strlen(str);i++)
{
for(int j=0;j<strlen(alfavita);j++)
if(alfavita[j] == str[i])
str[i] = alfavita[j+3];
}
puts(str);
}
For example if i give 'a' it should be return 'd' (each letter will transform into the 3d next of the alfavita array ) But it just prints me a null string. I can't find something wrong or I don't see it .
str[i] = alfavita[j+3];
After this line the code continues, so it will put i+3, i+6, ... until it gets out of alfavita.
You can add a break to exit the inner loop like that:
for(int i=0;i<strlen(str);i++)
{
for(int j=0;j<strlen(alfavita);j++)
if(alfavita[j] == str[i])
{
str[i] = alfavita[j+3];
break; // next i.
}
}
, or maybe just directly access the array:
for(int i=0;i<strlen(str);i++)
{
char c = str[i];
if (c >= 'a' && c <= 'z') {
str[i] = alfavita[(c - 'a' + 3) % strlen(alfavita)];
}
}
Note the % strlen(alfavita) to avoid ending after the end of the list.
You could also write it:
if (c >= 'a' && c <= 'z') {
str[i] = ((c - 'a' + 3) % 26) + 'a';
}
You can use a table that gives the replacement character for each character.
Then encode by computing the index into plain, and transferring that index into encoded:
char encode_char(char c)
{
const char *plain = "abcdefghijklmnopqrstuvwxyz";
const char *encoded = "defghijklmnopqrstuvwxyzabc";
const char *pp = strchr(plain, c);
if(pp != NULL)
return encoded[(ptrdiff_t) (pp - plain)];
return '?';
}
How the above works:
Define two strings that are supposed to be 1:1 mapped, i.e. plain[0] is encoded into encoded[0]. This can be more clearly modelled (i.e. by a struct that has the pair) but then the iniialization becomes more complicated.
Search for the input character c inside the plain string. This returns NULL if not found, or a pointer to somewhere inside plain found.
Make sure the pointer isn't NULL before using its value.
Subtract plain (i.e. &plain[0], the address of the a) from pp. This evaluates to 0 for a, 1 for b, and so on.
Use the computed index to look up the corresponding character in encoded.
On failure to encode, return ?.
In a portable, general program, you can not use plain subtraction (i.e. c - 'a'), since C does not guarantee that characters are encoded in values next to each other.
As pointed out, the above assumes that each character encodes in exactly one char. That might not be true for targets with exotic encodings, in which case it really is safer to use an explicit table, like this:
const struct {
char plain;
char encoded;
} encoding[] = {
{ 'a', 'd' },
{ 'b', 'e' },
{ 'c', 'f' },
/* ... and so on ... */
};
The encoding function then becomes:
char encode_char2(char c)
{
for(size_t i = 0; i < sizeof encoding / sizeof *encoding; ++i)
{
if(encoding[i].plain == c)
return encoding[i].encoded;
}
return '?'; /* Not found. */
}
I am trying to input a string of characters, and then output them backwards like
Input: Hello
Output: olleH
I have a working example, however I am getting every single letter except the last.
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
int main(void) {
int my_stg2[MAX_SIZE];
int i = 0;
int j;
char my_stg[MAX_SIZE];
int input ;
input = getchar();
while (input != '\n'){//The new line is the stopping point.
my_stg2[i] = input;
++i;
input = getchar();
}
for (j=0;i>=0;i--){
my_stg[j] = my_stg2[i];
j++;
}
printf("%s\n" , my_stg);
}
I tried the above code, however I am getting weird output with large strings. Can someone fix the loop for me? http://imgur.com/PK97b.png
Ok. In order to solve cases like this you should really do what Kristopher Johnson says and go through it on paper to figure out how your variables will change during the execution of your program. Pen and paper are some of the most important tools a programmer has.
Just because I know it can be hard to do this if you don't know how to do it, let me talk you through it.
Assume the input "Hello\n". Before you start looping you will have the following values:
i = 0 & input = 'H'
You then go on to loop:
while (input != '\n') { my_stg2[i] = input; ++i; input = getchar(); }
for each iteration in your loop, your values will change to be:
i = 1 & input = 'e' & my_stg2[0] = 'H'
i = 2 & input = 'l' & my_stg2[1] = 'e'
i = 3 & input = 'l' & my_stg2[2] = 'l'
i = 4 & input = 'o' & my_stg2[3] = 'l'
i = 5 & input = '\n' & my_stg2[4] = 'o'
So. i is now 5.
You now go on to the second loop, and you do the following:
for (j = 0; j <= i; j++) { --i; my_stg[i] = my_stg2[j]; }
you start to loop, and after having decremented i you have the following value pairs:
j = 0 & i = 5 & my_stg[4] = my_stg2[0] = 'H'
j = 1 & i = 4 & my_stg[3] = my_stg2[1] = 'e'
j = 2 & i = 3 & my_stg[2] = my_stg2[2] = 'l'
...and at the third step the loop stops. The output you get is "leH".
Now, why did the loop stop? Look over your conditions, and you'll find your answer.
Tweak your for loop as below
for (j=0; j < i; j++)
{
my_stg[i - (j + 1)] = my_stg2[j];
}
my_stg[i] = 0;
This is what you have
// The following line is pseudo-code.
// The '\0' is required in C to mark end of a character string.
orig := 'H', 'e', 'l', 'l', 'o', '\0'
with number of characters n = 6 (don't forget the \0).
Following is what you want to achieve
reverse := 'o', 'l', 'l', 'e', 'H', '\0'
So, this is what we have to do:
A. put a \0 in reverse[ n - 1 ]
B. We would read orig forward starting at index i = 0, and write to reverse backward starting at index j = n - 1. For that, we use two index variables:
i, for indexing orig, starting at 0 and incrementing up to n - 1
j, for indexing reverse, starting at n - 1 and decrementing down to 0
C. copy from orig[ i ] to reverse[ j ]
for( i = 0, j = n - 1; (i <= n - 1) && (j >= 0); ++i, --j ) {
reverse[ j ] = orig[ i ];
}
There are 2 mistakes with your program.
First, realize that the value of "i" in your first loop is always set to "the index we will next write into".
i = 0; input = getchar();
while (input != '\n'){
my_stg2[i] = input;
++i;
input = getchar();
}
Exiting that loop after writing "Hello!", you would have
my_stg2[] = {'H', 'e', 'l', 'l', 'o', '!'}, i=6
When you start reading the values out of my_stg2 you should therefore start reading from (i-1) instead of from i.
The second problem is that after copying the contents of my_stg2 to my_stg you need to do:
my_stg2[j] = 0;
This is because strings in C use a trailing null to determine the end of the string. The reason you get garbage characters following your string in the picture you attached is because the printf() code will keep printing each successive byte in memory until it reaches a 0, and you never placed a 0 at the end of the my_stg string explicitly.
Alternately you could initialize the entire contents of my_stg2 to 0 at the start of your program with
memset(my_stg2, 0x00, sizeof(my_stg2));
This is an important lesson with C - when you declare a variable you need to initialize it or it will on some platforms be filled with whatever was previously stored in the memory location.
You have several issues in your code:
int my_stg2[MAX_SIZE]; is an array of random ints when declared. These are of sizeof(int) on your platform -- probably 32 or 64 bits;
char my_stg[MAX_SIZE]; is a array of random characters when declared. These are of sizeof(char) on your platform -- probably 8 bits;
You are interchanging ints and characters with the assignment of my_stg[j] = my_stg2[i]; without a cast.
You are not checking for a buffer overrun in while loop. If someone typed more than MAX_SIZE characters before a \n, you will overrun the buffer you allocated;
You are not null terminating the string. If you are using getchar() that is a single character. You need to put a NUL after that or you will have a runaway string with the printf()
In your while loop, you need to check for EOF
It is counterintuitive, but getchar() is its own little loop like construct. It will not enter the while loop until an EOF or CR. It will then dump all the characters. You should not, then, test for CR against the getchar().
Your second loop is off by one; you are copying the value after the last character.
This code works as you expects I believe:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 100
int main(void) {
char my_stg[MAX_SIZE], my_stg2[MAX_SIZE];
int i,j,input = 0;
while ((input=getchar())!=EOF) {
if(input=='\n' || i>=MAX_SIZE-1) break;
my_stg2[i++] = (char)input;
my_stg2[i+1] = (char)0l;
}
printf("my_stg2= %s\ni=%i\n",my_stg2,i);
for (j=0;i>0;i--,j++){
my_stg[j] = my_stg2[i-1];
my_stg[j+1]=(char)0l;
printf("i=%i %s\n",i,my_stg);
}
printf("%s\n" , my_stg);
return EXIT_SUCCESS;
}
Because it get a bit tedious to think about strings as having a NUL termination, most people use the standard C library for strings.
You may also want to ponder doing this loop more efficiently. Reversing a string in place using 1/2 the memory and 1/2 the steps with a recursive function like this:
void strrev ( char *buff, int start, int end )
{
char tmp ;
static int i=0;
if ( start >= end ) {i=0; return;}
printf("%i strrev=%s\n",++i,buff);
tmp = *(buff + start);
*(buff + start) = *(buff + end);
*(buff + end) = tmp ;
strrev (buff, ++start, --end );
}
If you look at the output, you can see it is 1/2 the steps and without copying to another buffer:
Hello World!!!
my_stg2= Hello World!!!
i=14
i=14 !
i=13 !!
i=12 !!!
i=11 !!!d
i=10 !!!dl
i=9 !!!dlr
i=8 !!!dlro
i=7 !!!dlroW
i=6 !!!dlroW
i=5 !!!dlroW o
i=4 !!!dlroW ol
i=3 !!!dlroW oll
i=2 !!!dlroW olle
i=1 !!!dlroW olleH
!!!dlroW olleH
Recursive:
1 strrev=!!!dlroW olleH
2 strrev=H!!dlroW olle!
3 strrev=He!dlroW oll!!
4 strrev=HeldlroW ol!!!
5 strrev=HelllroW od!!!
6 strrev=HelloroW ld!!!
7 strrev=Hello oWrld!!!
reverse the reverse: Hello World!!!
Have a look at a pointer backward-solution for your array question:
const char *loop = my_stg2 + strlen(my_stg2);
...
do {
my_stg[loop-my_stg2] = *loop;
} while( my_stg2 != loop-- );