ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
I've never had much luck with C++, but I'm giving it another go. This program takes a list of first names and last names and puts them into two arrays. The first name loop goes fine, but the lastname loop crashes right at "lastnames[tmpCounter] = buffer;". It's the same code! Why won't it work?!
I've replaced the lastnames file with the firstnames file, but even with two identical files, it still won't work. I can't figure it out. Am I missing something?
Here's the code:
Code:
#include <iostream.h>
#include <fstream.h>
int main() {
char buffer[80];
ifstream firstNamesFile;
ifstream lastNamesFile;
char **firstnames;
char **lastnames;
int firstnamesLength = 0;
int lastnamesLength = 0;
firstNamesFile.open("firstnames.txt", ios::in);
if (!firstNamesFile) {
cout << "Unable to open firstnames." << endl;
return 1;
}
lastNamesFile.open("lastnames.txt", ios::in);
if (!lastNamesFile) {
cout << "Unable to open lastnames." << endl;
return 1;
}
for (int tmpCounter = 0; !lastNamesFile.eof(); tmpCounter++) {
lastNamesFile.getline(buffer, 80);
lastnames[tmpCounter] = buffer;
lastnamesLength = tmpCounter; // Make this better.
}
lastNamesFile.close();
for (int tmpCounter = 0; !firstNamesFile.eof(); tmpCounter++) {
firstNamesFile.getline(buffer, 80);
firstnames[tmpCounter] = buffer;
firstnamesLength = tmpCounter;
}
firstNamesFile.close();
/*
for (int x=0; x<firstnamesLength; x++) {
cout << firstnames[x] << endl;
}
*/
return 0;
}
It looks like you neglected to allocate space for the strings that you will be referring to through 'firstnames' and 'lastnames'. As it is, they are just pointers (to pointers); if you plan to store strings using those variables, you have to allocate space for the strings. Though, a much simpler approach would be to just declare them as 2D arrays at the outset:
Code:
char firstnames[X][Y];
where X and Y are the maximum number of strings, and maximum length of each string, respectively. If you want to do dynamic allocation (which I wouldn't recommend here, unless X or Y need to be really huge), you could use the C++ 'new' operator after reading each name into the buffer.
Also, assigning firstnames[foo] = buffer does not do what you may expect - it simply makes the pointer residing in firstnames[foo] point to the buffer variable; when buffer is overwritten by something else, the "assignment" of the original string goes away. Using strcpy() to copy the string would be one solution; using the C++ 'string' data type might be better, since it would allow assignment using '='.
if you do want to use the char**, you would do it like this:
char **firstnames;
firstname = new char*[n];
for(int i = 0; i < n; i++)
{
firstnames[i] = new char[80];
}
where n is the number of names. this means that you need to know the number of names before you create the arrays. i usually read the file once, to find out how many entries there are going to be, then allocate the memory. you have to do some tricks with rewinding the file pointer if you choose this way. if you want to allocate the memory on the fly, you are either going to have to write some ugly code, or use the list<> template.
Thanks wapcaplet and zerkliph. Looks like I'm going to have to spend some more time "understanding" rather than "doing." I think you have me on the right track now, though.
On second thought. I think I'll just put C++ back on the shelf before I go postal.
I can find no correlation between what it says in my book, my program, and my output. And as I have no idea how to figure out how to figure out what to do (no, I didn't mistype), I don't see much point in keeping at it.
Since your code uses iostream.h and fstream.h, I'm going to assume that your book is teaching C++ pre-ANSI 92... The latest ANSI/ISO spec for C++ has the standard headers placed in files that drop the .h (and prepend a 'c' for standard C headers), put everything in a std namespace, and declares the headers with the .h as deprecated...
e.g.
#include <iostream.h>
becomes
#include <iostream>
and
#include <stdlib.h>
becomes
#include <cstdlib>
If it doesn't discuss that, then it also probably doesn't discuss any of the STL classes, which would very likely help you out here. In this particular case, instead of saving your string lists as a char**, it might be a lot easier to understand if you saved them as a std::vector<std::string>. That way, all your memory management is going to be handled for you.
You'll still want to learn pointers eventually, but the STL stuff may or may not make your initial C++ learning a bit easier... Anyway, it's just a thought.
Hmmmm... Newer books. Now that might be an idea. The one I have been using is copyrighted in 1992 and has a section on how do make Windows 3.1 dialog boxes. I found one that is copyrighted in 1999, and I might start using that one.
Anyway, I've been away for a while (as you can tell by my late post) and have had time to take a good number of deep breaths. Seeing randyding's bit of code that looked promising, I decided to have another go at it, and this time it worked.
It seems to me that the things that you should really be happy that you've gotten to work take so much out of you that once you're done, you don't have any energy left to rejoice.
Thank you all for your help. Here's the final code:
Code:
#include <fstream.h>
#include <iostream.h>
int main() {
typedef char Tmystring[64];
Tmystring *firstnames;
Tmystring *lastnames;
firstnames = new Tmystring[10000];
lastnames = new Tmystring[90000];
char buffer[80];
ifstream firstNamesFile;
ifstream lastNamesFile;
int firstnamesLength = 0;
int lastnamesLength = 0;
firstNamesFile.open("firstnames.txt", ios::in);
if (!firstNamesFile) { cout << "Unable to open firstnames." << endl;
return 1; }
lastNamesFile.open("lastnames.txt", ios::in);
if (!lastNamesFile) { cout << "Unable to open lastnames." << endl;
return 1; }
for (int tmpCounter = 0; !firstNamesFile.eof(); tmpCounter++) {
firstNamesFile.getline(buffer, 80);
snprintf(firstnames[tmpCounter],sizeof(Tmystring)-1,"%s",buffer);
firstnamesLength = tmpCounter;
}
firstNamesFile.close();
for (int tmpCounter = 0; !lastNamesFile.eof(); tmpCounter++) {
lastNamesFile.getline(buffer, 80);
snprintf(lastnames[tmpCounter],sizeof(Tmystring)-1,"%s",buffer);
lastnamesLength = tmpCounter;
}
lastNamesFile.close();
for (int x=0; x<firstnamesLength; x++) cout << firstnames[x] << endl;
for (int x=0; x<lastnamesLength; x++) cout << lastnames[x] << endl;
delete [] firstnames;
delete [] lastnames;
return 0;
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.