Hi,

I'm a newbie to this group. I heard a question in C to swap the two strings using command line arguments but without using the temp. string,pointer or array


Can anyone help me how to do this.

Search for your problem before posting. It is likely that someone might have faced the same problem earlier.

Do you have an example of what you're trying to do?

Since you said "swap without a temp", perhaps you're referring to this dumb trick?
http://c-faq.com/expr/xorswapexpr.html

Hi,

Thank u for ur reply.
My aim is to swap two strings without using a temporary pointer or char array, but i have to use command line arguments for getting the two strings as input.

I don't think there is a general way to do it. A char data type is not large enough to use the method that Salem posted. And my compiler VC++ 2005 Express doesn't allow this either even when I typcast the pointers to unsigned long.

int main(int argc, char* argv[])
{
    if(argc == 3)
    {
        (unsigned long)argv[1] ^= (unsigned long)argv[2] ^= (unsigned long)argv[1] ^= (unsigned long)argv[2];
        cout << argv[1] << "\n";
        cout << argv[2] << "\n";
        
    }

}

At the risk of being repetitive for having mentioned this before, you may not have write access to your command line arguments. Moreover, you can't change their size. I think it is perfectly within reason to copy them into local character arrays:

int main( int argc, char *argv[] ) {
  char *s1, *s2;
  int len, len2;

  if (argc < 3) {
    printf( "fooey!\n" );
    return 1;
    }

  /* len <-- size of the longest string */
  len  = strlen( argv[ 1 ] );
  len2 = strlen( argv[ 2 ] );
  len  = (len < len2) ? len2 : len;

  /* get the strings */
  s1 = (char *)malloc( len );
  s2 = (char *)malloc( len );

  strcpy( s1, argv[ 1 ] );
  strcpy( s2, argv[ 2 ] );

  printf( "Given the strings:\n" );
  printf( "1. %s\n", s1 );
  printf( "2. %s\n", s2 );

  /* (do your swap here) */

  printf( "Now the strings are:\n" );
  printf( "1. %s\n", s1 );
  printf( "2. %s\n", s2 );

  free( s2 );
  free( s1 );
  return 0;
  }

That example for the trick is horribly broken, but it works just fine when done right. Keep the sequence points intact, and only try to swap ordinal values of the same size (char s match both criteria):

char a = '1', b = '2';
printf( "%c%c\n", a, b );
a ^= b, b ^= a, a ^= b;
printf( "%c%c\n", a, b );

Hope this helps.

printf( "%s %s\n", argv[2], argv[1] ); swaps without any trickery at all.

strcpy( s1, argv[ 1 ] );
  strcpy( s2, argv[ 2 ] );

Please don't do that again!

>you may not have write access to your command line arguments
Both C89 and C99 say otherwise, and they both use exactly the same wording:

The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination.

>Moreover, you can't change their size.
This is correct though.

>My aim is to swap two strings without using a temporary pointer
>or char array, but i have to use command line arguments for
>getting the two strings as input.
If the question is to copy the actual arguments (eg. argv[1] and argv[2]), the only viable solution would have to assume that both of those strings are exactly the same length:

#include <stdio.h>

int main ( int argc, char *argv[] )
{
  if ( argc > 2 ) {
    int i = 0;

    printf ( "Before: '%s' '%s'\n", argv[1], argv[2] );

    while ( argv[1][i] != '\0' ) {
      char save = argv[1][i];
      argv[1][i] = argv[2][i];
      argv[2][i++] = save;
    }

    printf ( "After:  '%s' '%s'\n", argv[1], argv[2] );
  }

  return 0;
}

>Please don't do that again!
Not enough information. Why shouldn't he do it again?

commented: good comments +21

Narue: Oh yes, when I said its not possible I was not thinking outside the box but assumed "but without using the temp. string,pointer or array" included a temp variable as in your line 11.

>assumed "but without using the temp. string,pointer or array"
>included a temp variable as in your line 11.
Well, char is still an integral type, so you could use the XOR swap. Doing so is about half a step from stupidity worthy of a Darwin award, but it would certainly remove the temporary variable. :icon_rolleyes:

Cool Narue! I didn't know that. (I suppose that's the kind of brain damage I get for having tried it years ago on some silly, ancient, broken DOS C compiler.)

Doublex, how about this one: printf( "%s", strcpy( "Stupider", "Stupid" ) ); (results may vary).

Cool Narue! I didn't know that. (I suppose that's the kind of brain damage I get for having tried it years ago on some silly, ancient, broken DOS C compiler.)

Doublex, how about this one: printf( "%s", strcpy( "Stupider", "Stupid" ) ); (results may vary).

Results may crash!

:-/ :idea: ;) Yes, that was the point.

Try compiling with gcc -fwritable-strings stupid.c :)

where i commented, he was trying to copy something from argv to destination. This can really easy cause buffer overflow.

Only if you don't check the size of the buffers. Notice how I carefully allocated space large enough for either string before copying? That, and the strings in argv[] are guaranteed to be null-terminated. No problems.

All pointer arithmetic is inherently dangerous. But it is how the machine works. You can take the time to do it right (which includes using functions that do all the checking for you, which don't exist in the standard library in this case). That doesn't justify auto-hatred of specific functions (well, except gets() and the fabled void main(void) ).

My latest example is safe also, because the target string is longer than the source --hence the niftiness of it for you.

(Again, results may vary for your compiler. If using GCC make sure to use the -fwritable-strings flag.)

Enjoy!

>where i commented, he was trying to copy something from
>argv to destination. This can really easy cause buffer overflow.
Your comment was unwarranted then. Just because you see strcpy doesn't mean there's a risk of buffer overflow. You'll notice that he carefully calculated the size of the longest string and allocated that amount to both of the buffers, which makes your correction moot.

I was actually hoping you would point out the real error, which is a failure to add 1 to the allocated length to account for the null terminator. This is correct, and exhibits no buffer overflow (though I do have some stylistic beefs with Duoas' code):

/* len <-- size of the longest string */
len  = strlen( argv[ 1 ] );
len2 = strlen( argv[ 2 ] );
len  = (len < len2) ? len2 : len;

/* get the strings */
s1 = (char *)malloc( len + 1 );
s2 = (char *)malloc( len + 1 );

strcpy( s1, argv[ 1 ] );
strcpy( s2, argv[ 2 ] );

yeap, i haven't looked carefully in your code. sorry narue about that.

Duoas, you are right, there's no function that can do everyting right, at least not in the standard library, but in this case, strcpy only helps you shoot in the leg. I strongly suggest the use of strncpy in this case.

I also think every function should be verified if returned successfully, mostly when you're playing with memory.

>I strongly suggest the use of strncpy in this case.
strncpy has it's own surprises, like always filling the remaining spots in the buffer with null characters, and failing to append a null character if the source string fills the buffer. strcpy always appends one null character, which is what people usually expect. A safer alternative is strncat, as long as you make sure the destination buffer is set to an empty string first.

But both of those "better" options are confusing and tricky, where if you simply make sure that the buffer is large enough to hold the source string, strcpy is perfectly safe and unquestionably intuitive.

The ideal is to write your own "safe" strcpy that allows you to limit the buffer size but also has the expected semantics and secure behavior on error:

int jsw_strcpy_s ( char *dst, size_t n, const char *src )
{
  char *it = dst;
  size_t remaining = n;

  while ( ( *it++ = *src++ ) != '\0' && --remaining > 0 )
    ;

  if ( remaining == 0 ) {
    /* The source exceeds available buffer space */
    *dst = '\0';
  }

  return remaining != 0;
}

I recommend you use whatever function you decide to use properly -- which includes setup of variables. If you don't know what you're doing, beware. If you know what's going on, no problem.

Heh, nice catch Narue. :$
I suppose this is what I get for typing in code late at night without reviewing it...

You could fix it with a little note just in case anyone tries to come along and use it...

Doublex, I suggest you stay away from pointers altogether. I can shoot you in the leg with any routine you like...

(I've shot myself enough to know)

is not that i don't understand pointers or i'm afraid to use them... it's just that we are humans, and humans make mistakes, and if you work on a large project with thousands or more lines of code, the probability to make an error increases
so... getting used with functions like strcpy or gets, makes the possibility to commit such errors a reality.

just because you can play with pointers and you can make a peace of code secure enough doesn't help you.

i've also shot myself a lot of times, and i have good knowledge about what's under the hood, but when it comes to secure programming i just want to be safe.

>so... getting used with functions like strcpy or gets,
>makes the possibility to commit such errors a reality.
It's not as simple as avoiding a "dangerous" function or feature, as I explained by describing the pitfalls of the "safe" alternatives to strcpy. In my experience, labeling functions as safe and unsafe will do little more than encourage programmers to be sloppier with the safe functions.

Those that don't fall into that trap are also the ones who don't need the safe functions in the first place[1] because they write solid code either way.

Those that do fall into that trap are the ones who will probably be sloppy either way, and no amount of protection by the functions will make their code safe enough to instill confidence.

[1] Excluding functions that cannot be made safe, like gets.

Doublex, the whole point I and everyone else on this thread has tried to make to you is that strcpy() is not an unsafe function. It may be used unsafely, but if you are to toss it out the window altogether then how exactly do you intend to copy strings?

You can't compare it to gets() because gets() really is unsafe. Why? Because there is absolutely no way to enforce bounds checking on it. No bounds checking == unsafe.

The strcpy() function is bounds checked. It has a well-defined termination condition and the length of the destination is easily verified and bounded before you call the function.

Your argument about the size to error ratio is true, but it does not apply. Why? Because it is true no matter how "safe" you language of choice is. Programmers don't make errors because the library routines are out to get them. They make errors because they don't use the library routines correctly. No matter how huge your project, it is always possible to validate and use a function like strcpy() safely. If you find it difficult to do, then I suggest that the design of your code is in error.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.