Go Premium for a chance to win a PS4. Enter to Win

x
?
Solved

Separating Each Line in a File

Posted on 2011-03-20
8
Medium Priority
?
321 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
  • 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
Industry Leaders: 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

Vote for the Most Valuable Expert

It’s time to recognize experts that go above and beyond with helpful solutions and engagement on site. Choose from the top experts in the Hall of Fame or on the right rail of your favorite topic page. Look for the blue “Nominate” button on their profile to vote.

Question has a verified solution.

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

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Summary: This tutorial covers some basics of pointer, pointer arithmetic and function pointer. What is a pointer: A pointer is a variable which holds an address. This address might be address of another variable/address of devices/address of fu…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

927 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