Solved

Separating Each Line in a File

Posted on 2011-03-20
8
316 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 500 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

[Webinar] Learn How Hackers Steal Your Credentials

Do You Know How Hackers Steal Your Credentials? Join us and Skyport Systems to learn how hackers steal your credentials and why Active Directory must be secure to stop them. Thursday, July 13, 2017 10:00 A.M. PDT

Question has a verified solution.

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

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
Examines three attack vectors, specifically, the different types of malware used in malicious attacks, web application attacks, and finally, network based attacks.  Concludes by examining the means of securing and protecting critical systems and inf…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

626 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