Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

Separating Each Line in a File

Posted on 2011-03-20
8
Medium Priority
?
319 Views
Last Modified: 2012-05-11
Hello.
I have a file as follows:
name: John
alias: JohnQ2
website: http://johnme.net

I'm trying to seperate each line so it will be:
name: John (in one buffer)
then
alias: JohnQ2 (in another buffer)

here is the code I'm using:
	  char finalsid[1000] = {0};
  char  finalbuff[1000] = {0};
  int p;
	  for(p = 0; p < strlen(mainbuf); p++)
  {

	if(mainbuf[p] == '\n')
	{
		
		strncpy((char*)finalbuff, (const char*)finalsid, strlen(finalsid));
		cout << finalbuff;
		//strncpy((char*)finalsid, "\0", sizeof(finalsid));
		memset(&finalsid,'\0',1000);
		Sleep(2500);
		MessageBox(0, finalbuff, "Output", MB_OK);
		//break;

	}
	else
	{
		strncat((char *)finalsid, (const char*)mainbuf + p, 1);
		//cout << finalsid;
		//Sleep(2500);
	}

Open in new window


Notice I'm using memset to try and clear the "finalsid" buffer so I can rewrite it anew. It does successfully separate each line but I want to store each line in the "finalbuff" buffer. Instead of storing only each line in there, it will mix up the lines like so:
name: John
tp://johnme.net

alias: JohnQ2
//johnme.net

I notice that this only happens AFTER the line
website: http://johnme.net
is loaded. So I'm assuming that memset isn't properly clearing the memory that the largest line has used, and the other lines are just overwriting portions of it.

So basically I need to know how to fully clear "finalsid" so I can write to it anew on every loop.

Thanks!
0
Comment
Question by:JoeD77
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
8 Comments
 
LVL 40

Expert Comment

by:evilrix
ID: 35176568
Wow, you're making hard work for yourself. If you just want to read all the lines of a text file into memory just use a few standard C++ objects.

http://www.cplusplus.com/reference/stl/vector/
http://www.cplusplus.com/reference/string/string/
http://www.cplusplus.com/reference/iostream/ofstream/
http://www.cplusplus.com/reference/string/getline/
#include <string>
#include <vector>
#include <fstream>

std::string line;
std::vector<std::string> lines
std::ofstream in("somefile.txt");

while(std::getline(in, line))
{
   lines.push_back(line);
}

Open in new window

0
 

Author Comment

by:JoeD77
ID: 35176744
Thanks for that but for learning purposes I want to do it using a similar method to the one I posted.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 35176781
Heh. Well you can do but what you're learning there is bad practice as far as C++ is concerned.. This is C++ and not C. If you want to learn C++ then what I've posted above is the way this would normally be done. What' you're attempting to do is C programming. Whilst the languages share a common base it is often that case that in C++ you would do thing very different.

Nevertheless, below I've gone through your code and provided some feedback as comments for you to review. See if that helps. If not provide me with the full working code and some example test data and describe clearly what's not working and I'll see what I can do to point you in the right direction.
char finalsid[1000] = {0};
char  finalbuff[1000] = {0};
int p;

// RX: you could use strtok to tokenise rather than rolling your own parser
for(p = 0; p < strlen(mainbuf); p++)  // RX: keep calling strlen here is very inefficiant.
{

   if(mainbuf[p] == '\n')
   {

      strncpy((char*)finalbuff, (const char*)finalsid, strlen(finalsid)); // RX: strncpy doesn't add a null terminator.
      cout << finalbuff;
      //strncpy((char*)finalsid, "\0", sizeof(finalsid));
      
      // RX: this memset is wasteful, since you're using string functions all you need do is set the first char to null (*finalsid = 0);

      memset(&finalsid,'\0',1000); 
      Sleep(2500);
      MessageBox(0, finalbuff, "Output", MB_OK);
      //break;

   }
   else
   {
      strncat((char *)finalsid, (const char*)mainbuf + p, 1);
      //cout << finalsid;
      //Sleep(2500);
   }

Open in new window

0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:JoeD77
ID: 35176900
Thanks, evilrix.

I took your advice as best I could:
  int p;
  int sz = strlen(mainbuf);
	  for(p = 0; p < sz; p++)
  {

	if(mainbuf[p] == '\n')
	{
		
		strncpy((char*)finalbuff, (const char*)finalsid, strlen(finalsid));
		cout << finalsid;
		finalsid[0] = '\0';
		strcat(finalsid, "\0");
		Sleep(2500);

	}
	else
	{
		strncat((char *)finalsid, (const char*)mainbuf + p, 1);

	}


  }

Open in new window


with these changes I'm having the same problem. Let me try to explain better.

Okay, the first loop is PERFECT. the lines are read line by line nicely.

_OUTPUT AFTER FIRST LOOP_

name: John
alias: JohnQ2
website: http://johnme.net

_END_

_OUTPUT AFTER SECOND LOOP_

name: Johntp://johnme.net
alias: JohnQ2//johnme.net
website: http://johnme.net

_END_

from what I know about memory, it seems as though once "website: http://johnme.net" is loaded into "finalsid" it's unable to effectively remove them from memory and they are subsequently showing where they shouldn't be.

I hope I made it clear enough and thanks a ton for your assistance.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 35176928
I think the issue here is the strncpy. It does not append a null unless the original string is shorter than the length you provide it. You've added code to append a null but you've put it in the wrong place. See my comments in the revised code.

I urge you to look at strtok as it does most of this for you.
http://www.cplusplus.com/reference/clibrary/cstring/strtok/
int p;
  int sz = strlen(mainbuf); // RX: strlen returns a size_t not an int
          for(p = 0; p < sz; p++)
  {

        if(mainbuf[p] == '\n')
        {
                
                strncpy((char*)finalbuff, (const char*)finalsid, strlen(finalsid));
                cout << finalsid; // RX: You need to append the null BEFORE outputing.

                finalsid[0] = '\0'; 
                strcat(finalsid, "\0"); // RX: this line needs to move before the cout
                Sleep(2500);

        }
        else
        {
                strncat((char *)finalsid, (const char*)mainbuf + p, 1);

        }


  }

Open in new window

0
 
LVL 40

Accepted Solution

by:
evilrix earned 2000 total points
ID: 35177010
I've made the changes I suggested above, to your code, and given my simple test case (I had to make up some test data since you've not provided any) it seems to work.

Please note; however, that this code is horribly inefficient and brittle. If you are using it to learn then fine but please don't consider putting this code into "production".
#include <cstring>
#include <iostream>

using namespace std;

int main()
{
   const char mainbuf[] = "hello\nworld\nand\nit's\nfriends";
   char finalsid[1000] = {0};
   char finalbuff[1000] = {0};

   size_t len = strlen(mainbuf);

   for(size_t idx = 0; idx < len; idx++)
   {

      if(mainbuf[idx] == '\n')
      {

         strncpy((char*)finalbuff, (const char*)finalsid, strlen(finalsid));
         strcat(finalsid, "\0");
         cout << finalsid << endl;

         finalsid[0] = '\0'; 
         // Sleep(2500);

      }
      else
      {
         strncat((char *)finalsid, (const char*)mainbuf + idx, 1);

      }
   }
}

Open in new window

0
 

Author Comment

by:JoeD77
ID: 35177021
Excellent. Strtok worked wonders.

Thanks for all your help.
0
 
LVL 40

Expert Comment

by:evilrix
ID: 35177044
>> Strtok worked wonders.

Hahaha... I'd just finished a strtok example for you. I'll still post it in case you find it useful. Amazing how much shorter the code is eh? If you could performance profile it I'd be prepared to bet real money it'd be much faster too :

Best of luck.

-Rx.
#include <cstring>
#include <iostream>

using namespace std;

int main()
{
   char mainbuf[] = "hello\nworld\nand\nit's\nfriends";
   char finalbuff[1000] = {0};

   char *p = strtok(mainbuf, "\n");
   while(p)
   {
         strcpy(finalbuff, p);
         cout << finalbuff << endl;
         p = strtok(0, "\n");
   }
}

Open in new window

0

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

671 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question