1,105,409 Community Members

reading names into char array of pointers

Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

i'm looking to get a first name followed by four scores and finally a last name, stored into multiple arrays (a char *array, a float array, & a char *array). getting the scores i understand however the names are pointer arrays. as far that goes what am i doing wrong here

char *FNs[50];   //Student's First Names.
	char *LNs[50];   //Student's Last Names.
ifstream text("data5.txt", ios::in);
	if(text.is_open()) 
		char Name[20];
		while(i<50 && text>>Name[]) 
		{
			newPtr = new char[20];
			strcpy(newPtr, Name);
			FNs[i] = newPtr; 
			text>>Scores[i][0];
	                                text>>Scores[i][1];
	                                text>>Scores[i][2];
			text>>Scores[i][3];
	                                text>>Name;
			i++;
		}
	text.close();
}

example data i want to input:

Jane Doe
13.1 82.4 99.0 66.2
John M. Smith
48.1 58.2 12.3 99.1
Bill Forest
88.8 99.2 48.1 60.5
and so on

Member Avatar
vmanes
Postaholic
2,141 posts since Aug 2007
Reputation Points: 1,165 [?]
Q&As Helped to Solve: 282 [?]
Skill Endorsements: 10 [?]
 
0
 

Assuming you have a declaration for char * newptr; your handling of the pointer arrays looks correct, as far as that goes. There are other problems or questions:

First clarify, is the data in the form you show in example ( fn ln s1 s2 s3 s4) or as in your description ( fn s1 s2 s3 s4 ln ) ? That makes a difference.

Second, reading in first and last names separately will cause problems when there's a middle initial or multiple first or last names (Billy Bob Smith, Sara Jones Carter). As you have the code now, all you read in is a first name, then try to read the scores, which is going to cause input failure.

Third, you can cut out a bit of redundancy by allocating memory directly to the array of pointers, as in FNs[i] = new char[20]; strcpy(FNs[i], Name); What does the assignment actually say about handling the names? Are there any qualifications of the types of names, or assurances of only two name parts?

Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

i was reading the data file wrong.
should be reading in fn ln d1 d2 d3 d4, as in the example:

John M. Smith
48.1 58.2 12.3 99.1

there are spaces between the initial and last name however spaces on this forum aren't working out.

i'm supposed to treat the initial as part of the first name. was planning on slaving over that later on though so i didn't mention it.

assignment just asks that the names be placed in two separate arra of pointers (first name and last name). not much more specific.

thanks in advance

Member Avatar
vmanes
Postaholic
2,141 posts since Aug 2007
Reputation Points: 1,165 [?]
Q&As Helped to Solve: 282 [?]
Skill Endorsements: 10 [?]
 
0
 

That clears up a lot.

Breaking up the name is now a bit simpler, but still needs some work.

My approach is to read the whole name in at one go to a temporary string using getline( ). Then work backwards from the end to find the space that marks the beginning of the last name. (and the ending of the first name middle initial). Copy the firstname portion - strncpy or strncat will work, since you know how much to copy. Then you can copy the last name in several ways.

1 - simply loop from where last name start to end of last name, storing char by char to the last name array element.

2 - use strcpy/strcat using the address of the first character of the last name as the source string. Example:

char tempname[50] = "John Q. Public";
char fname[20] = "";
char lname[20] = "";
int start;
//find index of the space between Q. and Public, store as start
strncat( fname, tempname, start );
strcat( lname, &tempname[start+1] );

And I'm sure someone else has other more elegant ways, but I think this is clear for the beginner.

Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

understood but a q: i'm assuming i could use that to get the first name (and a initial should it contain one) if i have the number of characters the last name takes up, so how do i work backwards to figure out the length of the last name? let alone separate the first and last name from each other

Member Avatar
vmanes
Postaholic
2,141 posts since Aug 2007
Reputation Points: 1,165 [?]
Q&As Helped to Solve: 282 [?]
Skill Endorsements: 10 [?]
 
1
 

You can find the length of the whole name string (there's a string function for this). Using a loop, go backwards from that last position till you find a blank space. The index of that space is the length of the first name (plus middle name, if present). One past that is the index of the first char of the last name. Consider

char wholename[20] = "John Doe";

looks like:
J o h n   D o e \0                  content
0 1 2 3 4 5 6 7 8 9 10 11.....19    indexes

length of string is 8, which is also the index of the NULL terminator
start loop at 7, go backwards till you find the blank at index 4.
So, first name is of length 4.  The string containing the last name starts at 
&wholename[5] (address of the element at index 5.)  String functions will think the string starts there, and still ends at the NULL terminator.
Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

can i get a logic check to make sure this should all work out right?

char wholename[21];
	int index=0, k=0;
	ifstream text("data5.txt", ios::in);
	if(text.is_open())
		while(i<50 && text.getline(wholename, 20))
		{
			int namelength=strlen(wholename);    
			FNs[i] = new char[20]; 

			for(int j=namelength; j!=0; j--)
				if(wholename[j]=='\0')
					index=j;

			strncat(FNs[i], wholename, index);

			LNs[i] = new char[20];
			for(k=0; k!=namelength-index; k++)
				strcat(LNs[k], wholename[k]);

			text>>Scores[i][0];
			text>>Scores[i][1];
			text>>Scores[i][2];
			text>>Scores[i][3];
			i++;
		}
Member Avatar
vmanes
Postaholic
2,141 posts since Aug 2007
Reputation Points: 1,165 [?]
Q&As Helped to Solve: 282 [?]
Skill Endorsements: 10 [?]
 
0
 

for the strncat to work, you must set the FN to an empty string. Simply allocating the memory does not do that.

FNs[i] = new char[20]; 
strcpy( FNs[i], "" );

In looking for the space before the last name, start you loop at namelength-1. The value that strlen returns is the index of the '\0', so your loop would set index right away. And, you really want to look for the blank space, not the NULL. They are not the same thing.

In copying the characters of the last name, you are simply copying array elements. Don't use a string function. What you have should not even be compiling.

LNs[i] = new char[20];
index++;
for(k=0; k!=namelength-index; k++)
   LNs[i][k] =  wholename[index++];
Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 
int namelength=strlen(wholename);    

			FNs[i]=new char[20]; 
			strcpy(FNs[i], "");

			for(int j=namelength-1; j!=0; j--)
				if(isspace(wholename[j]))
					index=j;
			strncat(FNs[i], wholename, index);

			LNs[i] = new char[20];
			index++;
			for(k=0; k!=namelength-index; k++)
				LNs[i][k]=wholename[index++];

better?
thanks.

Member Avatar
vmanes
Postaholic
2,141 posts since Aug 2007
Reputation Points: 1,165 [?]
Q&As Helped to Solve: 282 [?]
Skill Endorsements: 10 [?]
 
0
 

Yes, better. But let's look at this a bit deeper.

The loop looking for the space must stop when it finds the space. A for loop is not the best choice here. A while loop will stop just when you find the space

int namelength=strlen(wholename);    
FNs[i]=new char[20]; 
strcpy(FNs[i], "");

int j = namelength-1;
while( !isspace(wholename[j] )&&  j >= 0 )
    j--;
//add some test for j < 0, in case there's no space at all!
index=j;
strncat(FNs[i], wholename, index);

LNs[i] = new char[20];
index++;
for(k=0; k!=namelength-index; k++)
	LNs[i][k]=wholename[index++];
//or
do
{
     LNs[i][k++]=wholename[index++];
}while( wholename[index-1] != '\0' );  //loops till NULL copied
Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

aight well i've got one more problem here.

the text file has a certain (random) number of spaces between the first (and initial if such is included) and last names i.e

"George               Washington"

so our method is giving me some trouble.
in particular

FNs[i]=new char[20];

			strcpy(FNs[i], "");
			int j=namelength-1;
			while(!isspace(wholename[j]) && j>=0)
				j--;
                                                //haven't included a space check yet
			index=j;
			strncat(FNs[i], wholename, index);

strcat is duplicating the entire contents of what was in wholename (the string "George Washington") into FNs

what am i missing?

Member Avatar
GPXtC02
Light Poster
37 posts since Feb 2008
Reputation Points: 0 [?]
Q&As Helped to Solve: 0 [?]
Skill Endorsements: 0 [?]
 
0
 

aight fixed that. new question..
what is wrong with this:

while(i<50 && text.getline(wholename, SIZE) && (!strstr(wholename, SENTINEL)))

it goes through the first time around fine but on coming back to the top and reading a new name into it something goes wrong. SENTINEL being defined as "more" but that's not the problem because it is entering the while loop after that statement.
it's just apparently reading in something wrong (or nothing at all, because strlen=0). it just stops (messes up) a few lines after it enters..

Member Avatar
vmanes
Postaholic
2,141 posts since Aug 2007
Reputation Points: 1,165 [?]
Q&As Helped to Solve: 282 [?]
Skill Endorsements: 10 [?]
 
0
 

I'm not sure without seeing more code. The basis of your loop should work, as this little demo shows:

#include <string>
#include <iostream>
using namespace std;

int main()
{
    char s[25] = "";
    int i = 0;
    char sentinel[] = "stop";

    while( i < 50 && cin.getline( s, 25 ) && (!strstr( s, sentinel ) ))
    {
        cout << s << endl;
        i++;
    }

    return 0;
}

The one situation I find it behaves badly is if there's an EOF condition in the same line as the input with the sentinel value, in the case of a file that would be the last line not having a terminal endline. That would not explain it reentering the loop and giving bad results. Please post a program with this problem, and a sample of the data.

Question Answered as of 6 Years Ago by vmanes
You
This question has already been solved: Start a new discussion instead
Post:
Start New Discussion
Tags Related to this Article