Function to get and return a C string

  • (3 Pages)
  • +
  • 1
  • 2
  • 3

43 Replies - 1821 Views - Last Post: 02 April 2013 - 02:56 PM Rate Topic: -----

#1 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Function to get and return a C string

Posted 12 March 2013 - 10:04 AM

I'm finally done with my homework and officially on Spring Break. While I have the time, I want to figure something out to use the rest of the semester.

I am taking a C++ class, but my professor's requirements are an unusual blend of C and C++. I have written reusable functions to get and return an int, double, and char, but I want to write one that can return a C string (array of characters), since we are not allowed to use strings. Here is an example of one of my reusable functions:

/*********************************
* Gets and returns a Double  *
*********************************/	
double getDouble(char prompt[])
{
	double number = 0.00;
	char buffer[20];
	printf("\n%s",prompt);
	fgets(buffer,20,stdin);
	number = atof(buffer);

	return number;

}//END getDouble


I know you guys are going to cringe at the use of fgets (he used to make us use gets!), and using printf in with the C. But it's what I am required to use. I send the function a char[] called prompt to ask for the specific input.

I cannot get this to work with a char[], because you can't return arrays. I know I could just change the contents of the original array in the function, but that's not really reusable. ANy help would be appreciated!

This post has been edited by synlight: 12 March 2013 - 10:47 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Function to get and return a C string

#2 Ryano121  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 1363
  • View blog
  • Posts: 3,002
  • Joined: 30-January 11

Re: Function to get and return a C string

Posted 12 March 2013 - 10:07 AM

Quote

because you can't return arrays


Why not?
Was This Post Helpful? 0
  • +
  • -

#3 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Function to get and return a C string

Posted 12 March 2013 - 10:13 AM

Show what you have tried.

Jim
Was This Post Helpful? 0
  • +
  • -

#4 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Re: Function to get and return a C string

Posted 12 March 2013 - 10:14 AM

View PostRyano121, on 12 March 2013 - 12:07 PM, said:

Quote

because you can't return arrays


Why not?


Hmm.. I thought that was a rule in C++? You can return an pointer to an array, but not an actual array.

I may be wrong. It's certainly happened plenty of times before.

I've been trying to figure this out off and on all semester with no success.

When I write it in a way that makes sense to me, I get an error that it can't be converted.
Was This Post Helpful? 0
  • +
  • -

#5 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Function to get and return a C string

Posted 12 March 2013 - 10:22 AM

Quote

When I write it in a way that makes sense to me, I get an error that it can't be converted.

Post what you've tried. Then maybe we can help you to the correct path.

While it is true you can't return a local array from a function there are alternatives that may do what you want.

Jim
Was This Post Helpful? 0
  • +
  • -

#6 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Re: Function to get and return a C string

Posted 12 March 2013 - 10:23 AM

Well, first I tried this:

/**********************************
* Gets and returns hauler name    *
**********************************/
string getName()
{
	char buffer[50];
	string name;

	printf("What is the name of this hauler?");

	gets(buffer);
	name = buffer;

	return name;

}//END getName;


But it's not acceptable because it uses a string.

Then I tried something like this
/*********************************
* Gets and returns a String  *
*********************************/
char* getString(char prompt[], int size)
{
	char buffer[40];
	printf("\n%s",prompt);
	fgets(buffer,40,stdin);
	printf(buffer);

	return buffer;
}//END GETSTRING


But that didn't work either, I also tried several variations that I don't have anymore because they didn't work. Like, returning buffer as a pointer (*buffer) etc.

Right now I am trying to use the above function, and make my call a strcpy, like this:

strcpy(customer[sub].name,getString("\nPlease enter the name:", 19));


And it's kind of pretending like it WANTS to work LOL.

I'm using my last homework assignment to test the function, that's why I have the struct.


I also used a C++ function awhile back.. I can't remember,,, it converts a string to a c string.. but I got my program sent back -20 for trying that.

EDITED sorry Jim, I was opening a bunch of old files trying to find the ones I had tried. I've probably tried 25 slight variations all on the same theme.

Also, in the above char* getString function, it is passed an int because I was toying with limiting the size of the character array that way. No luck yet.

This post has been edited by synlight: 12 March 2013 - 10:25 AM

Was This Post Helpful? 0
  • +
  • -

#7 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Function to get and return a C string

Posted 12 March 2013 - 10:36 AM

To return the C-string from your function you have at least the following methods.
char* getString(const char prompt[], char buffer[],  int size)
{
	printf("\n%s",prompt);
	fgets(buffer,size,stdin);
	return buffer;
}//END GETSTRING


You would pass the C-string as a parameter to your function which the function can then return.

Or you can use the following method:
char* getString(const char prompt[], const int size)
{
   char *buffer = new char[size];
	printf("\n%s",prompt);
	fgets(buffer,size,stdin);
	return buffer;
}//END GETSTRING


But you must then remember to delete the memory you allocated when you are done with it.

And another method:
char* getString(const char prompt[])
{
   static char buffer[BUFFER_SIZE];
	printf("\n%s",prompt);
	fgets(buffer,BUFFER_SIZE,stdin);
	return buffer;
}//END GETSTRING

The problem with this method is that the buffer will be overwritten every time you call this function.

Jim
Was This Post Helpful? 1
  • +
  • -

#8 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Re: Function to get and return a C string

Posted 12 March 2013 - 10:51 AM

Jim!! My hero as always!

I think it's hilarious that you can whip out 3 solutions in 10 minutes to a problem I have been toying with for 2 months with no success.

Okay. Couple of questions.

The second method:
	char* getString(const char prompt[], const int size)
	{
	   char *buffer = new char[size];
	    printf("\n%s",prompt);
	    fgets(buffer,size,stdin);
	    return buffer;
	}//END GETSTRING


I have read a little bit about releasing memory, but it's nothing I've ever had to deal with. Would I use the delete function? Where would I use it, after I call getString?

And the third method.. is overwriting the buffer undesirable? To me it seems like it wouldn't matter, at least for my uses. But would there come a time when I wouldn't want that to happen?
Was This Post Helpful? 0
  • +
  • -

#9 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Function to get and return a C string

Posted 12 March 2013 - 11:10 AM

Quote

I have read a little bit about releasing memory, but it's nothing I've ever had to deal with. Would I use the delete function? Where would I use it, after I call getString?

First I don't recommend this method because you will usually end up with a memory leak. You are trying to call this method in your cout statement, so you will need to delete the memory before you call this method again or you will have a memory leak. And yes when you use new or new[] there must be a corresponding call to delete or delete[].

Quote

And the third method.. is overwriting the buffer undesirable? To me it seems like it wouldn't matter, at least for my uses. But would there come a time when I wouldn't want that to happen?

Like everything in life there are always times when things are undesirable. However in this case the way you are using this function it would probably not be a problem. As long as you copy the result to some other location before you reuse the buffer you should be alright. That said you should also not call this function multiple times in the same cout statement because it may lead to undefined behavior.

I really recommend you pass the variable as a parameter. By passing the variable as a parameter you are actually using the same pointer you are returning.

Jim
Was This Post Helpful? 0
  • +
  • -

#10 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1102
  • View blog
  • Posts: 4,597
  • Joined: 09-June 09

Re: Function to get and return a C string

Posted 12 March 2013 - 05:50 PM

Quote

Then I tried something like this
char* getString(char prompt[], int size)
{
   char buffer[40];
   printf("\n%s",prompt);
   fgets(buffer,40,stdin);
   return buffer;
}


But that didn't work either, I also tried several variations that I don't have anymore because they didn't work. Like, returning buffer as a pointer (*buffer) etc.


The problem with this attempt is that the memory "buffer" is local to the getString function call. When you call this function, you add a stack frame on to a call stack. In this stack frame is all of the memory for the local, parameter, and return values. Once the function returns, all the memory from the previous stack frame is released and now ready reuse for further function calls.

You are best off passing a pointer to memory which you would like to write to. This isn't bad practice, the C standard library does the same thing (scanf, fgets, ect..)
Was This Post Helpful? 0
  • +
  • -

#11 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Re: Function to get and return a C string

Posted 01 April 2013 - 08:19 AM

[quote name='jjl' date='12 March 2013 - 07:50 PM' timestamp='1363135837' post='1818763']

Quote

You are best off passing a pointer to memory which you would like to write to. This isn't bad practice, the C standard library does the same thing (scanf, fgets, ect..)


I am working on doing this for my current program. I am passing it a prompt string, and the buffer, then returning the buffer.

I keep getting an error that I am not initializing the buffer (which I'm not). I tried a few methods to initialize it. i.e.:

char *buffer[40] = {'A'};


and

memset(buffer[0], 0, 40);


and

std::fill_n(*buffer, 40, '0');


memset and fill are functions I looked up and tried while trying to get this to work.

Here is an example where I call my getString function (I use it several times in the program)

testName[0]= getString("\nEnter the customer name:", *buffer);


Here is the getString function:

/*********************************
* Gets and returns a String  *
*********************************/
char* getString(char prompt[], char buffer[])
{
	printf("\n%s",prompt);
	fgets(buffer,40,stdin);
	buffer[strlen(buffer)-1] = '\0';

	for(int x = 0; x < strlen(buffer); x++)
	{
		buffer[x] = toupper(buffer[x]);
	}
	return buffer;
}//END GETSTRING


Edited to add my prototype:
char* getString(char*, char*);


It worked when I was passing it a prompt and a string length, but my new requirement is:

A function that is passed two pointers, one to access a prompt and one to receive a string from the keyboard.

On the bright side, I graduate in 3 weeks!

This post has been edited by synlight: 01 April 2013 - 08:21 AM

Was This Post Helpful? 0
  • +
  • -

#12 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Function to get and return a C string

Posted 01 April 2013 - 08:24 AM

So what have you tried? What exactly don't you understand?

Jim
Was This Post Helpful? 0
  • +
  • -

#13 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Re: Function to get and return a C string

Posted 01 April 2013 - 08:29 AM

Well, for instance, I just tried initializing it like this:

and when I run the program and try to enter a string, it threw an access violation error. So, when I initialize it using the methods I posted above, I get Access violation errors. When I don't initialize it, I get an error that buffer is being used without being initialized.

buffer[0] = "a";


ETA: I don't understand why it's not working. It says I need to initialize it, but when I do, I get access violations.

ETA:
Here is where the error is thrown.. in fgets.c:

     if ((*pointer++ = (_TSCHAR)ch) == _T('\n'))
                    break;


I don't understand what this means. It loops through the char array, and tests it for a \n? I'm trying here. I really am. So.. I need to remove the delimiter and it will work? I'm so confused.

This post has been edited by synlight: 01 April 2013 - 08:42 AM

Was This Post Helpful? 0
  • +
  • -

#14 jimblumberg  Icon User is offline

  • member icon


Reputation: 4232
  • View blog
  • Posts: 13,291
  • Joined: 25-December 09

Re: Function to get and return a C string

Posted 01 April 2013 - 08:52 AM

In the following snippet:
buffer[0] = "a";

You can't assign a character string ("a") to a char (buffer[0]). Remember that double quotes ("") denote a string not a character.

Quote

Well, for instance, I just tried initializing it like this:

Since you are getting an access violation please post the complete program so I can compile and run it so I can see the problem.

Quote

Here is where the error is thrown.. in fgets.c:

Is fgets.c written by you? Again more content needed.


Jim
Was This Post Helpful? 0
  • +
  • -

#15 synlight  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 89
  • View blog
  • Posts: 582
  • Joined: 14-September 11

Re: Function to get and return a C string

Posted 01 April 2013 - 08:56 AM

Thanks Jim! The code is long.. it's a homework program still in progress. It's about 80% done. Please don't judge me LOL.

fgets.c is the file (written by Microsoft I guess), that pops up when an error is thrown in fgets. I was trying to research the error to find a solution.

Here is my program:

/***************************************************
* NAME: Synlight                                *  
* PROG: A4                          *
* PURP: Binary file I/O - data entry/verification* 
****************************************************/

# include <cstdio>
# include <cstring>
# include <string>
# include <windows.h>
# include <stdio.h>
# include <float.h>

using namespace::std;

struct dueDate
	{
		int month;
		int day;
		int year;
	};

struct record
	{
		int custID;
		char name[28];
		char state[3];
		char discCode;
		double balanceDue;
		dueDate date;
	};

//PROTOTYPES
int getInt(char*);
double getDouble(char*);
char* getString(char*, char*, int);
char getChar(char*);
void setWindow(int, int);

int getCustID(char*);
char* getName(char*);
char* getState(char*);
char* getCode(char*);
char* getBalance(char*);
char* getDate(char*);

bool testInt(char*);
bool testDouble(char*, double);
bool validState(char*);
bool testCode(char*);
bool validDate(int, int, int);





/**************************
* MAIN - Process  *
***************************/

int main()
{

	setWindow(100,75);
	char *buffer[40];
	buffer[0] = "a";
	int quit = 0;
	int pos = 0;
	int testID = 0;
	int length = 40;
	char *testName[40];
	char *testState[3];
	char testCode;
	double testBalance = 0.00;
	dueDate testDate; 
	record table[50];
	
	

	quit = getInt("Add record? 1 = YES 2 = QUIT");

	while (quit != 2)
	{
		//test selection
		if(quit!=1)
				quit = getInt("Invalid selection. Try again. 1 = ADD RECORD 2 = QUIT");

		testID = getCustID("\nEnter the customerID");
		testName[0]= getString("\nEnter the customer name:", *buffer, length);
		testCode = toupper(getChar("\nEnter the discount code:"));
		testBalance = getDouble("\nEnter the balance due:");
		testState[0] = strcpy(testState[0],(getString("\nEnter the state:", *buffer, length)));
		//getString("Please enter the due date as XX/XX/XXXX", *buffer);

		validState(*buffer);

			
		quit = getInt("Add record? 1 = YES 2 = QUIT"); 
	}//END PROCESS WHILE

	system("pause");
}//END MAIN


/***********************************************
* Gets and returns custID, validates ID <= 998 *
************************************************/
int getCustID(char prompt[])
{
	int ID = 0;
	char buffer[40];
	ID = getInt(prompt);
	printf("%i", ID);

	if(ID > 998)
	{
		getInt("ID must be less than 999. Please enter a valid customer ID");
	}
	return ID;
}


/***********************************************************
* Gets and returns an Integer, validate number is numeric  *
************************************************************/
int getInt(char prompt[])
{
	int number = 0;
	char buffer[40];
	bool isInt = true;
	printf("\n%s",prompt);
	fgets(buffer,40,stdin);
	
	isInt= testInt(buffer);

	if (isInt == true)
		number = atoi(buffer);

	//else
	while(isInt == false)
	{
		printf("Entry must be numeric. Please try again.");
		fgets(buffer,40,stdin);
		isInt= testInt(buffer);
		number = atoi(buffer);
	}


	return number;	
}//END getInt

/*********************************
* Test string as Integer  *
*********************************/
bool testInt(char* buffer)
{
	bool isInt = true;

    for(int x = 0; x < strlen(buffer); x++)
	{
      if(isdigit(buffer[x]))
	  {
		break;
	  }
	  else
		isInt = false;
    }//ENDFOR
  return isInt;
}//END TESTINT


/*********************************
* Test string as Double  *
*********************************/
bool testFloat(char* buffer)
{
	bool isFloat = true;

    for(int x = 0; x < strlen(buffer); x++)
	{
      if(_isnan(buffer[x]))
	  {
		break;
	  }
	  else
		isFloat= false;
    }//ENDFOR

  return isFloat;
}//END TESTINT

/*********************************
* Test state abbreviation  *
*********************************/	
bool validState(char *buffer)
{
	struct state
	{
		char name[10];
		char abbrev[2];
	};
	
	state states[50];
	bool validState = false;
	FILE *myFile;
	myFile = fopen("states.dat","rb");

	if(myFile!=NULL)
		for(int x = 0; x<50;x++)
		{
			fread(states[x].name,10,1,myFile);
			fread(states[x].abbrev,2,1,myFile);
		}
		
	fclose(myFile);

	for(int x=0;x<50;x++)
	{
		if(!strcmp(buffer,states[x].abbrev))
			validState = true;
		/*else
			getString("Not a valid state abbreviation. Please try again.", buffer);*/
	}	

	return validState;
}//END TESTSTATE

/*********************************
* Test discount code  *
*********************************/
bool testCode(char testCode)
{
	bool validCode = false;

	printf("%c",testCode);

	switch (testCode)
	{
		case 'A':
			validCode = true;
			break;
		case 'B':
			validCode = true;
			break;
		case 'C':
			validCode = true;
			break;
		case ' ':
			validCode = true;
			break;
		default:
			validCode = false;
			break;
	}//END SWITCH

	
	return validCode;

}//END TESTCODE

/***********************************************
* Test Due date *
************************************************/


/***********************************************
* Test Due date * I wrote this at first, as being passed the date struct. 
After I had it working, I decided to change it to 3 integers so it
can be reusable in all my programs
************************************************/
bool validDate(int month, int day, int year)
{
	bool validDate = false;
	int numDays = 0;
	bool monthFlag = false;
	bool dayFlag = false;
	bool yearFlag = false;

	if(month > 0 && month < 13)
	{
		monthFlag = true;

		if(month == 4 || month == 9 || month == 6 || month == 11)
			numDays = 30;
		else if (month == 2)
		{
			if (year % 4 == 0)
			numDays = 29;
			else 
			numDays = 28;
		}//END LEAPYEAR
		else 
		numDays = 31;
	}//END MONTH TEST	
	else
		printf("You have entered an invalid month");

	if(day <= numDays || day >= numDays)
		printf("You have entered an invalid day.");
	else
		dayFlag = true;

	if(year > 2013)
		printf("You have entered an invalid year.");
	else
		yearFlag = true;

	if(monthFlag == true && dayFlag == true && yearFlag == true)
		validDate == true;


	return validDate;
}//END VALIDDATE


/*********************************
* Gets and returns a Double  *
*********************************/	
double getDouble(char prompt[])
{
	double number = 0.00;
	char buffer[40];
	printf("\n%s",prompt);
	fgets(buffer,40,stdin);
	number = atof(buffer);

	return number;

}//END getDouble

/*********************************
* Gets and returns a String  *
*********************************/
char* getString(char prompt[], char buffer[], int length)
{
	printf("\n%s",prompt);
	fgets(buffer,length,stdin);
	buffer[strlen(buffer)-1] = '\0';

	//for(int x = 0; x < strlen(buffer); x++)
	//{
	//	buffer[x] = toupper(buffer[x]);
	//}
	return buffer;
}//END GETSTRING


/*********************************
* Gets and returns a Char  *
*********************************/
char getChar(char prompt[])
{
	char buffer[10];
	char code;
	bool validCode = false;

	printf("\n%s",prompt);
	fgets(buffer,10,stdin);
	code = toupper(buffer[0]);
	validCode = testCode(code);

	while(!validCode)
	{
		printf("\n%s","Invalid discount code. Please try again.");
		fgets(buffer,10,stdin);
		code = buffer[0];
		validCode = testCode(code);
	}
	return code;
}//END GETCHAR

/***********************************
* Make the console window sizeable *
************************************/
void setWindow(int Width, int Height)
    {
    _COORD coord;
    coord.X = Width;
    coord.Y = Height;

    _SMALL_RECT Rect;
    Rect.Top = 0;
    Rect.Left = 0;
    Rect.Bottom = Height - 1;
    Rect.Right = Width - 1;

    HANDLE Handle = GetStdHandle(STD_OUTPUT_HANDLE);      // Get Handle
    SetConsoleScreenBufferSize(Handle, coord);            // Set Buffer Size
    SetConsoleWindowInfo(Handle, TRUE, &Rect);            // Set Window Size
    }

Was This Post Helpful? 0
  • +
  • -

  • (3 Pages)
  • +
  • 1
  • 2
  • 3