Greetings everyone...

I'm new to Standard Template Libraries thus I'm encountering problems now and then...

I managed to get some examples on integer lists to work but the string lists give me nothing but grief...

What I'm trying to do is to read a series of words from an input text file, insert them into a list and then print them on the screen. However, the following code only prints the last word repeatedly, the number of times equal to the words in the file, which leads me to believe I actually succeed in creating the list but can't read properly from it.

The code is as follows... And help would be appreciated.

Thanks in advance...

Barış

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

#include <stdio.h>
#include <stdlib.h>


void main (void)
{
 	FILE *inputFile = fopen("input.txt", "r");

	if(inputFile == NULL)
	{
		std::cout << "Dosya acilamadi...";
	}


	list<char *> wordList;

	char currentword[100] = "";
	


	while(!feof(inputFile))
	{
		fscanf(inputFile, "%s", currentword);

		wordList.push_back(currentword);

		printf("%s\n", currentword);
	}

	
	list<char *>::iterator wordListIterator = wordList.begin();


	for(list<char *>::iterator ai=wordList.begin(); ai!=wordList.end(); ++ai)
	{
		std::cout << *ai << " ";
	}


	fclose(inputFile);  
 }

The input file is as follows :


Deneme Anne Elvis Abba

Lives cat Baba internet

Kazak Baba

Without being an STL-wizard myself, it appears to me that you are filling the list with pointers to the same array of characters every time, and replacing the data in this array with the latest word. This ought to give you the behaviour you describe.

What you need to do is to dynamically allocate space for every word as you want it stored, and then save the pointer to this space in your list.
Don't forget to free the memory when you're done with it.

Wow... I didn't think it would work but it did... Thanks :)

Why are you combining C++ STL with old-style C constructs anyway?

It would become a lot easier if you use list<string> instead (and fstream functions for the file handling).

>It would become a lot easier if you use list<string> instead
Agreed.

>and fstream functions for the file handling
Many feel that C++ streams are too awkward and opt for FILE *'s instead. I can understand that feeling for most common uses.

>void main (void)
First, main doesn't return void. It never has and probably never will. Second, you don't need to use void as the parameter list in C++. The funky issues where an empty list in a declaration and an empty list in a definition have subtle differences in meaning don't exist in C++ because there's no need to support K&R style C functions. The preferred way of defining main is:

int main()

Though the following is acceptable as well; it means the same thing, but is slightly uglier:

int main ( void )

>while(!feof(inputFile))
This will bite you eventually. feof (and it's sibling <stream>.eof()) only return true after an attempt to read from the stream has failed. This often results in the last record of a file being processed twice. The most common solution is to use the return value of your input function as the loop condition:

while ( fscanf(inputFile, "%s", currentword) == 1 )

>fscanf(inputFile, "%s", currentword);
Your use of fscanf is unsafe because the word could easily overflow your array if there are more than 99 characters without intervening whitespace in the file. You can hardcode a width modifier to guarantee that this won't happen though:

fscanf(inputFile, "%99s", currentword);

This is generally considered bad because it places a magic number somewhere other than a declaration. There are ways to remove this dependency with preprocessor magic, but it's dreadfully ugly and complicated.

>wordList.push_back(currentword);
If you use list<string> wordList then you can still use a C-style string for input and output by doing this:

wordList.push_back(string(currentword));

This saves you from having to allocate dynamic memory and remember to free it.

list<char *>::iterator wordListIterator = wordList.begin();

for(list<char *>::iterator ai=wordList.begin(); ai!=wordList.end(); ++ai)
{
  std::cout << *ai << " ";
}

wordListIterator doesn't do very much, so you can remove it. The iterator should really be const_iterator because you don't make changes, and as a good practice it's best to remove calls to <container>.end() in the loop condition. Standard containers generally don't suffer from performance problems like calling strlen as a loop condition, but humor me. :)

list<char *>::const_iterator begin = wordList.begin();
list<char *>::const_iterator end = wordList.end();

for ( list<char *>::const_iterator ai = begin; ai != end; ++ai )
{
  cout<< *ai <<' ';
}

Thank you for the recommendation...

I will keep that in mind... :)

Thank you very much Narue... There's a lot of valuable information there...

I'm far from reaching a perfect programming technique in C++ but your advice will help greatly...

Thanks again :)

hi,
I'm not sure about your problem but,i guess it will be solve if you change

list< char*> to list< string >.


Greetings everyone...

I'm new to Standard Template Libraries thus I'm encountering problems now and then...

I managed to get some examples on integer lists to work but the string lists give me nothing but grief...

What I'm trying to do is to read a series of words from an input text file, insert them into a list and then print them on the screen. However, the following code only prints the last word repeatedly, the number of times equal to the words in the file, which leads me to believe I actually succeed in creating the list but can't read properly from it.

The code is as follows... And help would be appreciated.

Thanks in advance...

Barış

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

#include <stdio.h>
#include <stdlib.h>


void main (void)
{
 	FILE *inputFile = fopen("input.txt", "r");

	if(inputFile == NULL)
	{
		std::cout << "Dosya acilamadi...";
	}


	list<char *> wordList;

	char currentword[100] = "";
	


	while(!feof(inputFile))
	{
		fscanf(inputFile, "%s", currentword);

		wordList.push_back(currentword);

		printf("%s\n", currentword);
	}

	
	list<char *>::iterator wordListIterator = wordList.begin();


	for(list<char *>::iterator ai=wordList.begin(); ai!=wordList.end(); ++ai)
	{
		std::cout << *ai << " ";
	}


	fclose(inputFile);  
 }

The input file is as follows :


Deneme Anne Elvis Abba

Lives cat Baba internet

Kazak Baba

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.