Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

I need help working with strings... help would be appreciated... thank

Status
Not open for further replies.

benb777

Programmer
Dec 30, 2002
7
0
0
US
I am creating a program that enters strings into an array using cin.getline. When i use this one of two things happens: Either the cin.getline is skipped and the string is not entered, or enter doesn't work, it gets struck in a blank loop.
Also i was wondering how to compare strings and how to change them.
Thanks
 
Here's how cin.getline should work for char arrays:

const int arraySize = 50;
char array[arraySize];

cout << &quot;Enter a sentence:&quot; << endl;
cin.getline( array, arraySize - 1 );

cout << &quot;\nThe sentence entered is:\n&quot;
<< array << endl;

In this form, cin.getline takes 2 arguements. The first is the array (actually a char *) to enter the sentence into, and the second is the number of characters to enter. It should be at most one less than the size of the array, because you must leave space for a terminating null character.

strcmp( const char *s1, const char *s2 ) compares 2 strings, returns a negative number if s1 < s2, zero if s1 == s2, and a positive number if s1 > s2.
 
Thank you but i still have the same problem... I have been using something like:

cin.getline(name[x],99,'\n');

and i tried your suggestion:

cin.getline(name[x],99);

but still the same problem, either the return to actually enter the text is skipped over and i can never enter the text and move on im my program, or the cin.getline is skipped and the variable is left blank.

Also when using strcmp i should #include <string.h> right? thanks
Ben
 
The code I gave is tested and works correctly, try it out to see if you get the same error you've been getting.

Assuming that the &quot;name&quot; array you're using is a double-scripted character array, I suspect there is a logic error, or bad input. Can you post your code?

Also, I the string and cstring header files have strcmp. If I am correct, capitalization may throw the intended comparison off, so be aware.
 
Im pretty new at programming, and have only taken one class on programing... Even in the class i got these errors with cin.getline. If it was skipped over i would just dublicate the line and it would work. The instructor didn't know how to fix it either. The program im trying to do is pretty simple: I am making a program where i enter weapons for a RPG i am working on and it will save them to as a file that will be read later. I have no idea how to do the saving to a file part but i will get to that later (if u know that would help). I've only worked with <iostream>, <string.h>, and <iomanip>. so far here is the code:

#include <iostream>
#include <string.h>
#include <iomanip.h>

using namespace std;
/*
class weapon
{
public:
char name [100];
char wclass [40];
int weight;
}
*/
int main()
{
//weapon wp [10];
char name [10][100];
char wclass [100][100];
char damage [10][100];
char comment [10][1000];
double weight [10];
int strength [100];
int x=1, i;
int itemcount=0;

cout << &quot;How many weapons would you like to enter? &quot;;
cin >> i;
itemcount=itemcount+i;

for(x=1;x<=i;x++)
{
cout << &quot; Weapon &quot; << x << endl;
cout << &quot;Name: &quot;;
cin.getline(name[x],99,'\n');
cout << &quot;Class: &quot;;
cin.getline(wclass[x],99);
cout << &quot;Damage: &quot;;
cin.getline(damage[x],100);
cout << &quot;Strength: &quot;;
cin >> strength[x];
cout << &quot;Weight: &quot;;
cin >> weight[x];
cout << &quot;Comments: &quot;;
cin.getline(comment[x],100);
}

cout << endl;
back:
for(x=1;x<=itemcount;x++)
{
cout << x << &quot;) &quot; << name[x] << endl;
}

cout << &quot;Which weapon would you like to look at?: &quot;;
cin >> x;
cout << endl;

cout << name[x] << &quot;[&quot; << wclass[x] << &quot;], &quot; << damage[x] << &quot;, &quot; << weight[x] << &quot;lbs. &quot; << strength[x] << &quot; strength is required to use. &quot; << comment[x] << endl << endl;
goto back;
return 0;
}

also i am using a mac compiler called codewarrior. I used the same code on this as when using microsoft visual c++ and there were no problems. Thanks for the help

Ben
 
I can tell you WHAT is happening. Apparently, when cin takes the value of a number, it doesn't read the newline character that proceeds it. Using cin.ignore() after inputting a number (and before inputting a string) gets things functioning properly. Why is this happening? I don't know. I've modified the code a bit to get it running. Here's what I have so far:

#include <iostream>
using std::cin;
using std::cout;
using std::endl;
//#include <string.h>
//#include <iomanip.h>

//using namespace std;

const int arraySize = 10,
stringLength = 100;

int main()
{
char name [arraySize][stringLength];
char wclass [arraySize][stringLength];
char damage [arraySize][stringLength];
char comment [arraySize][1000];
double weight [arraySize];
int strength [arraySize];
int i, itemcount, weapon;

cout << &quot;How many weapons would you like to enter? &quot;;
cin >> itemcount; //input shouldn't be < 0 or > arraySize

if( itemcount > arraySize )
itemcount = arraySize;

cin.ignore(); //money!

for(i=0;i<itemcount;i++)
{
cout << &quot; Weapon &quot; << i << endl;
cout << &quot;Name: &quot;;
cin.getline(name,arraySize - 1);
cout << &quot;Class: &quot;;
cin.getline(wclass,arraySize - 1);
cout << &quot;Damage: &quot;;
cin.getline(damage,arraySize - 1);
cout << &quot;Strength: &quot;;
cin >> strength;
cout << &quot;Weight: &quot;;
cin >> weight;
cin.ignore();
cout << &quot;Comments: &quot;;
cin.getline(comment,999);
}

cout << '\n' << '\n';
//back: //change this
for(i=0;i<itemcount;i++)
{
cout << i << &quot;) &quot; << name << endl;
}

cout << &quot;\nWhich weapon would you like to look at?: &quot;;
cin >> weapon; //check to see if weapon exists
cout << '\n';

cout << name[weapon] << &quot;[&quot; << wclass[weapon] << &quot;], &quot; << damage[weapon] << &quot;, &quot; << weight[weapon] << &quot;lbs. &quot; << strength[weapon] << &quot; strength is required to use. &quot; << comment[weapon] << '\n' << endl;
//goto back; */
return 0;
}

There are some other things that can be done to improve the aesthetics of the code, but that can come later. (E.G. I would use a while loop that exits with a sentinel value rather than using an infinate goto loop)

For inputting into files, you should research the fstream, ifstream, and ofstream header files. If you'd like, I have developed a fairly robust file handler class that would make the process pretty simple (it creates, modifies, and reads random access files full of similar objects based on a template), but its efficiency could probably be improved (it was my first real project with streams), and some of its functionality is untested.

Let me know.
 
I copied your code exactly as you had it, and after a lot of work taking out the white spaces, which were illigal tokens, i ran it and i had at least 15 errors. I am a newbie, and couldn't figure out these errors. They all had to do with your reorganizing of the arrays and string lengths.
Also you were talking about organization. and how you didn't think u should have a loop go on forever (you suggested a while loop). I had already reorganized my program into funtions. But i was having a few problems with that also. Thank you for all your help.
One more thing, i was thinking about all this cuting and paisting of code and it would be easier to just email it. My email address is benb@jimburford.com, if you would like to do this for sending code. Thanks again for your help

Ben
 
Hi BoulderBum, maybe you should compile a console app and send it to Ben along with the project files so he can play around with it and skip through with the debugger.

Anyways, I'm sorry for sticking my nose in but I know you mentioned before that you had just configured a dual boot of Windows and Linux - I wondered if you had done this on an NTFS formatted disk? Also, did you have to format the disk first?
I just got Linux 8.0 but the system I want to install on has NTFS file structure. I don't want to be wiping all my exisiting stuff off the disk first (there's far too much to restore!). I understand there's a disk partitioning software called Partition Magic that can handle NTFS partitions without having to reformat first but this costs $70 - hell... I could buy a couple of new hard disks for this!! Apologies again for butting in but I just wondered how you got along with the dual boot thing?

[hammer]
tellis.gif

[sup]programmer (prog'ram'er), n A hot-headed, anorak wearing, pimple-faced computer geek.[/sup]​
 
Gednick,

I actually have Partition Magic 7, and used it to create new blank ext2 (or whatever) and swap partitions. If you'd like to go the Partition Magic route (which I recommend because the software's handy for so many things), I noticed you can pick up a copy of the latest version on half.com for under 30 bucks. With the software, you can resize existing partitions, create new ones, and convert NTFS to FAT which, as I understand, is a less buggy format to work with using Linux.

When I installed Red Hat 8, it looked for Linux partitions to install itself on. I forget if it formatted the disk, but if you want to snoop around you can probably find the answers to your questions on the linuxnewbie.org forums.

Good luck with it! I love Linux because of the OS competition it introduces, but after using Windows for so long, I feel completely lost about seemingly simple things in a Linux environment.
 
Thanks BoulderBum, I figured I'd probably be better off spending the 30-40 bucks on a second internal hard disk and format it to FAT for the Red Hat 8.0 install. After snooping around on the net I discovered that linux doesn't like NTFS disks and often has trouble accessing data on them. This shouldn't be too much of a problem because I only really intended to install linux for development purposes - not for exchanging data between both OS's. Which brings me to another query for you...
You said you were looking forward to testing the dev tools on it. Mines not a boxed set (CDs only) so I have no clue what is on there and what to expect. Any info would be appreciated on this score [pc2]
As for competition between the OS's - I agree but I've never had the pleasure of using linux (only Mac and Windows) yet. So far, in my opinion, the Mac beats Windows hands down. I have a few old Macs running between System 7 and 8.5 and all these are still a far better OS than anything Microsoft have come up with. Unfortunately though, when it comes to earning money from programming, in most circumstances you need to be programming for Windows as your mainstay. Kind of unfortunate when you consider that the programmer's life is so much easier on a Mac in most respects - for example, knowing that sound and TTS is built-in to every Mac and the lack of DLL files, etc, etc.
[bigcheeks]
tellis.gif

[sup]programmer (prog'ram'er), n A hot-headed, anorak wearing, pimple-faced computer geek.[/sup]​
 
I got my CDs with a book on Linux. Durin the install a wizard looked for a Linux partition and a swap file or something, and then there were a bunch of intuitive forms and check boxes to apply settings, set passwords, and determine what you'd like included.

All I've done with the included development tools (you may want to do a custom install to make sure they're included) is a &quot;Hello World&quot; app, so I don't know too much about it, but I noticed that they expect anything made with the IDE will be an application for free distribution.

 
&quot;free distribution&quot;?????? wow.. I'm already broke!! [sadeyes] Seriously, I'm looking forward to playing around with it and seeing what the OS has to offer. As for development, I'm looking to put together a set of foundation classes that work across the three major platforms. Kind of a STL and multi-platform MFC combination type thing to try and make it easier to produce cross-platform versions of software. This is kind of a part-time thing for me and there's no real rush because I view it as a kind of hobby so I think I'll nip down to CompUSA at the beginning of next week and see how much those secondary hard disks are!

[yoda]
tellis.gif

[sup]programmer (prog'ram'er), n A hot-headed, anorak wearing, pimple-faced computer geek.[/sup]​
 
Your hobby sounds cool. I always try to write the most portable code possible too. In fact, a class file I think Ben might find helpful is one I developed for a bank record project I was working on. It was my first attempt to use streams, but I'm pretty happy with the results.

The following code keeps track of files full of a type of object (determined by the arguement passed to a template). You can add, retrieve, delete, and modify objects in the file. Erase the contents of the file, copy the file, and do a few other things and it's all made using ANSI standard code.

There are certainly some things that can be added (like an insert object function, which would be easily implemented), and I suspect there are better or more efficient ways to do implement the code, but I swear, as it is, the code makes it soooo easy to maintain files of objects. I tried to clean it up a little for display in the narrow forum text area, but it's still not as clear as it is in my .h file:

//file handler template header
//handles creation of, management of, copying of,
//and printing of files of
//a group of similar objects.

//Note: print funciton reliant on overloaded << operator


#ifndef FILEHANDLER_H
#define FILEHANDLER_H

#include<iostream>
using std::ios;
using std::cerr;
using std::endl;

#include <fstream>
using std::fstream;
using std::ifstream;
using std::eek:fstream;

template< class T >
class FileHandler
{
public:
//constructor takes 3 arguements: the filename, an array of objects,
//and the size of the array, it writes the object contained
//in the array to the file
FileHandler( const char *, const T[], const int );

//takes filename arguement, counts the objects in file
FileHandler( const char * );

//erase the contents of a file
clearFile();

//overwrite entire file truncating its former contents
overwriteFile( const T [], const int );

//overwrite single record
replaceObject( T , const unsigned );

//append an object to the end of the list
addObject( const T& );

//delete a single object
deleteObject( const unsigned );

//delete a range of objects
deleteObjects( const unsigned, const unsigned );

//returns # of objects in file
const int getObjCount() { return objectCount; }

//copy member file to different file
copyFile( const char * );

//returns a copy of an object positioned at a given index
const T returnObject( const int );

//output contents of member file
printFile();

//output single object of member file
printRecord( const int );
private:
const char * fileName;
int objectCount;
fstream inOutObject;
writeToPosition( T , const unsigned );
handleError( const int ); //int error type
};



//member function definitions

template< class T >
FileHandler< T >::FileHandler( const char *nameOfFile,
const T array[], const int objCnt ):
inOutObject( nameOfFile,
ios::in | ios::eek:ut | ios::binary | ios::ate ),
fileName( nameOfFile )
{
objectCount = objCnt;
if( !inOutObject )
{
handleError( 0 );
exit( 1 );
}
overwriteFile( array, objCnt );
}

template< class T >
FileHandler< T >::FileHandler( const char *nameOfFile ):
inOutObject( nameOfFile,
ios::in | ios::eek:ut | ios::binary | ios::ate ),
fileName( nameOfFile )
{
objectCount = 0;
T objectVar;

if( !inOutObject )
{
handleError( 0 );
exit( 1 );
}

inOutObject.seekg(0);
inOutObject.read( reinterpret_cast<char *>( &objectVar ), sizeof( T ));


while( !inOutObject.eof() )
{
++objectCount;
inOutObject.read( reinterpret_cast<char *>( &objectVar ), sizeof( T ));
}
inOutObject.clear();
}

template< class T >
FileHandler< T >::clearFile()
{
ofstream eraser( fileName, ios::eek:ut | ios::binary | ios::trunc );
objectCount = 0;
}




template< class T >
FileHandler< T >::eek:verwriteFile( const T arrayOfObjects[], const int numberOfElements )
{
clearFile();
objectCount = numberOfElements;

try
{
for ( int i = 0; i < objectCount; i++ )
{
writeToPosition( arrayOfObjects, i );
}
}
catch( ... )
{
handleError( 2 );
}
inOutObject.flush();
}



template< class T >
FileHandler< T >::replaceObject( T insObj, const unsigned position )
{
if ( position < objectCount )
{
writeToPosition( insObj, position );
}
else
handleError( 3 );
}


template< class T >
FileHandler< T >::deleteObject( const unsigned index )
{
if( index < objectCount )
{
int i;
T *storage = new T[objectCount];

//storage array is loaded with all the elements than aren't deleted,
//then the member file is overwritten according to storage's info
for ( i = 0; i < index; i++ )
storage = returnObject( i );
for ( i = index; i < objectCount; i++ )
storage = returnObject( i + 1 );

overwriteFile( storage, --objectCount );

delete [] storage;
}
else
handleError( 3 );
}

template< class T >
FileHandler< T >::deleteObjects( const unsigned begIndex, const unsigned endIndex )
{
if ( begIndex >= 0 && endIndex < objectCount )
{
int difference = endIndex - begIndex,
i;
//storage array is loaded with all the elements than aren't deleted,
//then the member file is overwritten according to storage's info
T *storage = new T[ objectCount - ( difference + 1 ) ];

//load storage array
for( i = 0; i < begIndex; i++ )
storage = returnObject( i );
for( i = endIndex + 1; i < objectCount; i++ )
//place objects after endIndex into the proper space in the array
storage[i - ( difference + 1 )] = returnObject( i );

objectCount -= difference + 1;

overwriteFile( storage, objectCount );
delete [] storage;
}
else
handleError( 3 );
}


template< class T >
FileHandler< T >::addObject( const T &obToAdd )
{
writeToPosition( obToAdd, objectCount++ );
}

template< class T >
FileHandler< T >::copyFile( const char *copiedFileName )
{
ofstream outPrintFileCopy( copiedFileName, ios::eek:ut | ios::trunc );


if ( !outPrintFileCopy )
{
handleError( 1 );
exit( 1 );
}

T copyObject;

inOutObject.seekg( 0 );
inOutObject.read( reinterpret_cast<char *>( &copyObject ), sizeof( T ));

while( !inOutObject.eof() )
{
outPrintFileCopy.write( reinterpret_cast< char * >( &copyObject ), sizeof( T ));

inOutObject.read( reinterpret_cast<char *>( &copyObject ), sizeof( T ));
}
inOutObject.clear();
cout << &quot;Copied file to: &quot; << copiedFileName << endl;

}

template< class T >
const T FileHandler< T >::returnObject( const int index )
{
T objectVar;

if ( index < objectCount )
{
inOutObject.seekg( index * sizeof( T ));
inOutObject.read( reinterpret_cast<char *>( &objectVar ), sizeof( T ));
}
else
{
handleError( 3 );
}
return objectVar;
}

//print function reliant on overloaded << operator
template< class T >
FileHandler< T >::printFile()
{
int i = 0; //used to indentify record index

while( i < objectCount )
{
printRecord( i++ );
}
}

template< class T >
FileHandler< T >::printRecord( const int index )
{
if ( index < objectCount )
cout << /*&quot;Record &quot; << index << '\n' <<*/ returnObject( index ) << '\n' << endl;
else
handleError( 3 );
}

//private functions

template< class T >
FileHandler< T >::writeToPosition( T insObj, const unsigned position )
{
inOutObject.seekp( ( sizeof T ) * position );
inOutObject.write( reinterpret_cast<char *>( &insObj ), sizeof( T ));

inOutObject.flush();
}

template< class T >
FileHandler< T >::handleError( const int errorType )
{
switch( errorType )
{
case 0:
cerr << &quot;File \&quot;&quot; << fileName << &quot;\&quot; does not exist. Aborting...&quot; << endl;
break;
case 1:
cerr << &quot;File could not be opened&quot; << endl;
break;
case 2:
cerr << &quot;Error creating new file&quot; << endl;
break;
case 3:
cerr << &quot;Passed subscript out of bounds&quot; << endl;
break;
default:
cerr << &quot;Error of unknown type&quot; << endl;
}
}

#endif



..........................................................

If someone can use the source, I can just send the file to make things easier.

I was sorta also hoping people can give some ideas on how to improve the code. I have a few ideas of my own, but I'd like to hear from others. [nosmiley]
 
E-mail me the source BB and I'll test it for you on the Mac too. My address is: nick@QED-online.com

tellis.gif

[sup]programmer (prog'ram'er), n A hot-headed, anorak wearing, pimple-faced computer geek.[/sup]​
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top