Swapping C-Strings

Maui

Newbie
Joined
Jul 6, 2004
Messages
390
Reaction score
0
Hey guys, here's something that's had me frustrated for a while. It should be simple enough: I'm trying to organize a vector of c-strings that hold sentences using an insertion sort. All is well and good until I go to swap two pointers in the vector.

What I tried initially is
Code:
void swap(char *a, char *b)
{
	char *t;
	t = a;
	a = b;
	b = t;
}

When I call that from somewhere else with swap(pA, pB) (where pA and pB are pointers to char arrays) it compiles okay but doesn't seem to actually swap them. All the google searches I did were for swapping numbers about, not even arrays of numbers - and of course "swap arrays" only returned results about swapping values *within* arrays.

Any help is appreciated :thumbs:
 
You have two options.

Copy the string from one variable to the other, using strcpy.

The other option is to pass in pointers to the char arrays (pointers to pointers) and swap around what they point to.
i.e.

Code:
void swap(char **a, char **b)
{
	char *t;
	t = a*;
	a* = b*;
	b* = t;
}
I think
 
Thanks guys, both ways worked! (except minor glitch on SLH's, should be like t = *a; not a* - nitpicking :p)

I think I see my mistake now (theoretical, obviously in code :p) - I was trying to swap the two char arrays pointed to by those in the vector, instead of changing around the ones in the vector which were doing the pointing, right? Thus the double *?
 
Couldn't you just use strcpy for this? seems it would do the trick.

[edit] To clarify:

Code:
void swap(char *a, char *b)
{
	char *t;
	strcpy(t,a);
	strcpy(a,b);
	strcpy(b,t);
}
 
fifty7var, that's dangerous. If you run the code enough times on enough different machines, it will crash. You don't know where t is pointing. Furthermore, if a and b are different sizes, then you're in for it too. Swapping pointers (with references) is really the best way.

Actually, you don't even have to write a separate swap function. The STL does it for you (the compiler effectively generates a function for char pointers that's equivalent to Marco's second example):

Code:
#include <utility> // for swap()

using std::swap;

int main(int argc, char** argv)
{
    char *hello = "Hello, world.";
    char *goodbye = "Goodbye, world.";
    swap(hello, goodbye);
    // The two strings are now swapped.

    return 0;
}
 
Thanks for the responses! Not only did you help me with my project, but I think I got some interesting insights here as well. I just may start checking out the Coding forum a bit more and helping where I can.

Thanks again! :D
 
As a special treat (maybe) for helping me out, I've decided to throw up the fun little thing I was working on - it's a random-sentence generator, made for some stupid C++ class. I'd put up the binary, but I can see the mods getting a little worried by that - so here's the source if you're interested. It's ISO C++.

Code:
#include <cstdlib>
#include <iostream>
#include <vector>
using namespace std;
#include <cmath>

vector< char* > v_nouns;
vector< char* > v_articles;
vector< char* > v_verbs;
vector< char* > v_preps;
vector< char* > v_sents;
const int NUM_SENTENCES = 20;

void createVector(vector< char* > &a, char* qry);
void createSentences(int numSentences);
void outputSentences();
void sortSentences();
int myStrCmp(char *a, char *b);
void swap(char *&a, char *&b);
void searchMode();
int search(char *qry, int line);

int main()
{
	createVector(v_articles, "articles");
	createVector(v_nouns, "nouns");
	createVector(v_verbs, "verbs");
	createVector(v_preps, "prepositions");
	
	createSentences(NUM_SENTENCES);
	cout << "It's after we're back in main()\n";
	outputSentences();
	cout << "Gonna swap first two sentences\n";
	swap(v_sents[0], v_sents[1]);
	cout << "Swapped, outputing again\n";
	outputSentences();
	cout << "Attempting to sort...\n";
	sortSentences();
	cout << "Sentences sorted, outputting again\n";
	outputSentences();
	
	cout << "Beginning search subroutine\n\n";
	searchMode();
	cout << "Program Terminated.\n";
	system("PAUSE");
	return 0;
}

void createVector(vector< char* > &a, char* qry)
{
	int num;
	cout << "Number of " << qry << "? ";
	cin >> num;
	a.resize(num);
	for(int i = 0; i < num; i++)
	{
		a[i] = new char[256];
		cout << "Enter " << qry << ", " << (num - i) << " left. ";
		cin >> a[i];
	}
}

void createSentences(int numSentences)
{
	v_sents.resize(numSentences);
	cout << "Resized okay\n";
	for(int i = 0; i < numSentences; i++)
	{
		v_sents[i] = new char[256];
		cout << "Assigned new char pointer to slot " << i << " okay.\n";
		strcpy(v_sents[i], v_articles[rand() % v_articles.size()]);
		cout << "Did strcpy okay\n";
		strcat(v_sents[i], " ");
		strcat(v_sents[i], v_nouns[rand() % v_nouns.size()]);
		strcat(v_sents[i], " ");
		strcat(v_sents[i], v_verbs[rand() % v_verbs.size()]);
		strcat(v_sents[i], " ");
		strcat(v_sents[i], v_preps[rand() % v_preps.size()]);
		strcat(v_sents[i], " ");
		strcat(v_sents[i], v_articles[rand() % v_articles.size()]);
		strcat(v_sents[i], " ");
		strcat(v_sents[i], v_nouns[rand() % v_nouns.size()]);
		strcat(v_sents[i], ".");
		cout << "Made sentence " << i << endl;
	}
}

void outputSentences()
{
	for(int i = 0; i < NUM_SENTENCES; i++) cout << (i+1) << ": " << v_sents[i] << endl;
}

void sortSentences()
{
	int result;
	int lowest = 0;
	int marker = 0;
	int i = 0;
	while(marker < (NUM_SENTENCES-1))
	{
		//find lowest that isn't behind marker
		cout << "In while loop, iteration " << i << endl;
		while(i < (NUM_SENTENCES-1))
		{
			result = std::strcmp(v_sents[lowest], v_sents[i]);
			cout << result;
			if(result > 0)
			{
				cout << "Changed lowest from " << lowest << " to " << i << ".\n";
				lowest = i;
			}
			i++;
		}
		cout << "swapping " << lowest << " and " << marker << endl;
		swap(v_sents[lowest], v_sents[marker]);
		marker++;
		i = marker;
	}
	
}

void searchMode()
{
	int result;
	char *input = new char[256];
	do
	{
		cout << "\nSEARCH MODE - Enter search term (CTRL-C to quit): ";
		cin >> input;
		if(*input != '\0')
		{
			for(int i = 0; i < v_sents.size(); i++)
			{
				result = search(input, i);
				if(result > -1) cout << "Found '" << input << "' in position " <<
				result << " in line " << (i+1) << endl;
			}
		}
	} while(*input != '\0');
}

int search(char *qry, int line)
{
	//search through v_sents[line] for the character pattern
	//method is painfully brute-force, but without hashes and a Rabin-Karp search,
	//it's the best I can do without library functions.  To give an idea, it runs
	//in quadratic time.
	
	//First find the length of the search query
	int patLength, sentLength;
	for(patLength = 0; *(qry+patLength) != '\0'; patLength++);
	for(sentLength = 0; *(v_sents[line]+sentLength) != '\0'; sentLength++);
	char *pTemp = new char[256];
	
	int numIter = sentLength - patLength + 1;
	int result;
	for(int i = 0; i < numIter; i++)
	{
		for(int j = 0; j < patLength; j++)
		{
			*(pTemp+j) = *(v_sents[line]+i+j);
		}
		result = std::strncmp(qry, pTemp, patLength);
		if(result == 0) return i;
	}
	//never found
	return -1;
}

int myStrCmp(char *a, char *b)
{
	int result = 0;
	for( int i = 0; result == 0 && !(a[i] == '\0' || b[i] == '\0'); i++) result = a[i] - b[i];
	if(result != 0) result /= std::abs(result);
	return result;
}

void swap(char *&a, char *&b)
{
	char *t;
	t = a;
	a = b;
	b = t;
}

EDIT: Now I can tell all the chicks I'm an open-source programmer! And enjoy the looks of confusion on their faces as they slowly back away!

EDIT AGAIN: Blah, I left the diagnostic cout statements in there - still works quite well getting the sentences, you just have some fluff in the meantime.
 
Back
Top