LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 12-04-2011, 10:24 AM   #1
grob115
Member
 
Registered: Oct 2005
Posts: 542

Rep: Reputation: 32
Parse text file for name value pair


Hi, am looking for some sample code to parse a file. Here's an example config file I have.
Code:
NAME=FIRST_PERSON
AGE=11
SEX=M

NAME=SECOND_PERSON
AGE=23
SEX=M

NAME=THIRD_PERSON
AGE=33
SEX=F
The file can contain one or N number of these name-value pairs. The code needs to be able to do the following:
1) Read them all in.
2) Ensure each one has the variables NAME, AGE, and SEX all filled in.

Anyone can suggest a way to do this in C++?
 
Old 12-04-2011, 10:29 AM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by grob115 View Post
...
Anyone can suggest a way to do this in C++?
Try to enter

C++ text parsing

into any web search engine. Start from plain old "C" 'index' function (probably a part of C++ standard library too) : http://linux.die.net/man/3/index .
 
Old 12-04-2011, 02:03 PM   #3
SigTerm
Member
 
Registered: Dec 2009
Distribution: Slackware 12.2
Posts: 379

Rep: Reputation: 234Reputation: 234Reputation: 234
Quote:
Originally Posted by grob115 View Post
Anyone can suggest a way to do this in C++?
There's more than one way to do it. So why don't you post what you already tried to do and explain where you encountered the problem?
 
Old 12-04-2011, 06:35 PM   #4
jb_gpk
Member
 
Registered: Dec 2010
Distribution: Debian
Posts: 30

Rep: Reputation: 13
Quote:
Originally Posted by grob115 View Post
Anyone can suggest a way to do this in C++?
Why not awk?
 
Old 12-04-2011, 08:47 PM   #5
jhwilliams
Senior Member
 
Registered: Apr 2007
Location: Portland, OR
Distribution: Debian, Android, LFS
Posts: 1,168

Rep: Reputation: 211Reputation: 211Reputation: 211
Quote:
Originally Posted by jb_gpk View Post
Why not awk?
How do you do this in Awk? I ask not because I doubt it can be done; rather, I know it can, but am trying to learn awk. (Beyond '{ print $1 }'.)
 
Old 12-05-2011, 02:02 AM   #6
jhwilliams
Senior Member
 
Registered: Apr 2007
Location: Portland, OR
Distribution: Debian, Android, LFS
Posts: 1,168

Rep: Reputation: 211Reputation: 211Reputation: 211
Tada, an awk script -- will complain if not all values are set.

Code:
#!/usr/bin/awk -f
BEGIN {
    RS=""
    FS="="
    OFS="\t"
}
($1 ~ /NAME/),($NR == 0) {
    if (NF != 6) {
        print "Badly formed input line"
        exit
    }

    print $2,$4,$6
}
 
Old 12-05-2011, 06:44 AM   #7
grob115
Member
 
Registered: Oct 2005
Posts: 542

Original Poster
Rep: Reputation: 32
Great idea with the awk, though it needs to be done in C++ as I'm learning it by trying to do different things of which this is one of them. Am thinking of reading the stuff into a vector of struct, which consists of the expected variables per set. Is this a good approach?
 
Old 12-05-2011, 10:43 AM   #8
grob115
Member
 
Registered: Oct 2005
Posts: 542

Original Poster
Rep: Reputation: 32
Hi, this is my attempt to do this, though am having a bunch of errors from the IDE in NetBeans as shown in the attachment.
Not sure why it's complaining about simple things like the if and while statements.
Also, not sure why it can't find the <iostream>, <ifstream>, or <ofstream> headers. I'm using remote build option btw and it is able to find the compilers, assemblers, and linkers on the remote Linux box.

Code:
#include <string>
#include <iostream>

using namespace std;

string name, age, sex;
string field, value;
string ifilename = "config.txt";
string lfilename = "out.log";
ifstream ifile(ifilename.c_str());
ofstream ofile(lfilename.c_str());
bool bname = false, bage = false, bsex = false;
int count = 0;

typedef struct {
  string name;
  int age;
  char sex;
} TypeStructConfig;

typedef std::vector<TypeStructConfig> VectorStructConfig;

VectorStructConfig structConfig;

if (count == 0) {
    std::cout << "h";
}

while (!ifile.eof()) {
    getline(ifile, field, '=');
    getline(ifile, value);

    switch (field) {
        case NAME:{
        structConfig(count).name = value;
        bname = true;
        break;
        }
        case AGE:{
        structConfig(count).age = value;
        bage = true;
        break;
        }
        case SEX:{
        structConfig(count).sex = value;
        bsex = true;
        break;
        }
        default:{
            ofile << field << " is an unknown configuration parameter.\n";
            exit;
        }
    }

    if (bname == false || bage == false || bsex == false) {
        ofile << "Not all required parameters are set.\n";
        exit;
    } else {
        count++;
    }
}
Attached Thumbnails
Click image for larger version

Name:	netbeans.jpg
Views:	65
Size:	196.5 KB
ID:	8558  
 
Old 12-05-2011, 11:11 AM   #9
Nylex
LQ Addict
 
Registered: Jul 2003
Location: London, UK
Distribution: Slackware
Posts: 7,464

Rep: Reputation: Disabled
I'm not sure about NetBeans, but to me it seems a few things are wrong:

Firstly, you're missing the line "#include <vector>". Also, C++ vectors are created empty, so you first need to add items to them before modifying them, e.g.

Code:
TypeStructConfig foo;
foo.name = "A N Other";
foo.age = 1;
foo.sex = 'M';
structConfig.push_back(foo);
Also, you use square brackets to access elements, so in lines like

Code:
structConfig(count).sex = value;
the round brackets are wrong. You can use the member function at() to access elements, instead of using array syntax (i.e. square brackets), e.g.

Code:
structConfig.at(count).sex = value;
I've only had a quick glance at the code, so there might be other things too.

Last edited by Nylex; 12-05-2011 at 11:25 AM.
 
Old 12-05-2011, 11:12 AM   #10
jhwilliams
Senior Member
 
Registered: Apr 2007
Location: Portland, OR
Distribution: Debian, Android, LFS
Posts: 1,168

Rep: Reputation: 211Reputation: 211Reputation: 211
I don't really know C++ that well these days, I guess. But here's a C version:

Code:
#include <string.h>
#include <stdio.h>

#define LINE_MAX 100

int main() {
    char line[LINE_MAX];
    char *key;
    char *value;

    while (EOF != scanf("%s\n", line)) {
        key = strtok(line, "=");
        value = strtok(NULL, "=");
        printf("%s=%s\n", key, value);
    }
}
 
Old 12-05-2011, 11:31 AM   #11
Cedrik
Senior Member
 
Registered: Jul 2004
Distribution: Slackware
Posts: 2,140

Rep: Reputation: 244Reputation: 244Reputation: 244
Quote:
Originally Posted by grob115 View Post
Hi, this is my attempt to do this, though am having a bunch of errors from the IDE in NetBeans as shown in the attachment.
Not sure why it's complaining about simple things like the if and while statements.
There is no main() function ?
 
1 members found this post helpful.
Old 12-05-2011, 12:05 PM   #12
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by jhwilliams View Post
I don't really know C++ that well these days, I guess. But here's a C version:

Code:
#include <string.h>
#include <stdio.h>

#define LINE_MAX 100

int main() {
    char line[LINE_MAX];
    char *key;
    char *value;

    while (EOF != scanf("%s\n", line)) {
        key = strtok(line, "=");
        value = strtok(NULL, "=");
        printf("%s=%s\n", key, value);
    }
}
'scanf' is a bad idea because of possible buffer overflows.
 
Old 12-05-2011, 12:19 PM   #13
SigTerm
Member
 
Registered: Dec 2009
Distribution: Slackware 12.2
Posts: 379

Rep: Reputation: 234Reputation: 234Reputation: 234
Quote:
Originally Posted by grob115 View Post
Hi, this is my attempt to do this,
This is not a valid C++ program. There's no main() function, and code is mixed up with global variables, and there are undeclared identifiers (NAME/AGE/SEX).
Also you don't use "typedef struct{} StructName" in C++. Make sure it compiles, fix all the errors, and try again - because until you do this, there's nothing to talk about (unless you're trying to understand compiler error). If you have trouble writing a basic C++ program, start from beginning - try any C++ book or tutorial.

Last edited by SigTerm; 12-05-2011 at 12:20 PM.
 
Old 12-06-2011, 07:55 AM   #14
grob115
Member
 
Registered: Oct 2005
Posts: 542

Original Poster
Rep: Reputation: 32
Hi, reason there wasn't a "main" function was because I was thinking of putting this into one of the cpp files for the project, and use include this from the main source file.

Anyway, if I'm writing it as a stand alone program, it'd look like the following. However, am stuck on getting the vector of struct to work correctly. I'm stuck. Can someone please advise?
Code:
test.cpp:28: error: expected initializer before ‘<’ token
test.cpp:29: error: ‘TypeVectorStructConfig’ does not name a type
test.cpp: In function ‘int main(int, char**)’:
test.cpp:40: error: ‘VectorStructConfig’ was not declared in this scope
test.cpp:43: error: ‘VectorStructConfig’ was not declared in this scope
test.cpp:46: error: ‘VectorStructConfig’ was not declared in this scope

Code:
#include <cstdlib>
#include <string>
#include <iostream>
#include <fstream>

std::string name, age, sex;
std::string field, value;
std::string ifilename = "config.txt";
std::string lfilename = "out.log";
std::ifstream ifile(ifilename.c_str());
std::ofstream ofile(lfilename.c_str());
bool bname = false, bage = false, bsex = false;
int count = 0;

struct TypeStructConfig {
  std::string name;
  int age;
  char sex;
} ;

typedef std::vector<TypeStructConfig> TypeVectorStructConfig;
TypeVectorStructConfig VectorStructConfig;

/*
 * 
 */
int main(int argc, char** argv) { 

    while (getline(ifile, field, '=')) {        
        getline(ifile, value);
        
        if (field == "NAME") {
            VectorStructConfig[count].name = value;
            bname = true; 
        } else if (field == "AGE") {
            VectorStructConfig[count].age = value;
            bage = true;
        } else if (field == "SEX") {
            VectorStructConfig[count].sex = value;
            bsex = true;
        } else {
            ofile << field << " is an unknown configuration parameter.\n";
            return 1;
        }
    }

    if (bname == false || bage == false || bsex == false) {
        ofile << "Not all required parameters are set.\n";
        return 1;
    } else {
        count++;
    }
    
    return 0;
}
 
Old 12-06-2011, 08:09 AM   #15
Nylex
LQ Addict
 
Registered: Jul 2003
Location: London, UK
Distribution: Slackware
Posts: 7,464

Rep: Reputation: Disabled
For one thing, you're missing the "vector" header, as I pointed out in my post above. Also, you still aren't adding any elements to the vector. Again, see my post above (you need to use the push_back() member function).

The following line is wrong:

Code:
VectorStructConfig[count].age = value;
value is a string, but the age member of your struct is an int. You can get from a string to an int with a stringstream:

Code:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;

int main()
{
  string s("123");
  stringstream ss;
  ss << s;
  int x;
  ss >> x;
  cout << x << endl;
  return 0;
}
Obviously, you need to be sure that what's being input is really a numeric value!

The line

Code:
VectorStructConfig[count].sex = value;
is wrong because value is a string, but the sex member is a char. You can either use string's at() member function or use array syntax to get the character:

Code:
string s("a");
cout << s.at(0) << endl; 
cout << s[0] << endl;
Edit: As SigTerm mentioned, you might want to try a C++ tutorial or book. There's a tutorial here.

Last edited by Nylex; 12-06-2011 at 08:12 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
I need to parse a text file in shell scripting shanti sree Linux - Newbie 4 10-12-2011 02:09 PM
[SOLVED] Parse Text File With Perl unsymbol Programming 1 03-05-2011 05:36 AM
[SOLVED] sed - parse text file elexx Programming 8 02-22-2011 10:19 AM
Parse multiple variable from text file with bash Goni Programming 2 07-13-2010 02:25 AM
How to parse text file to a set text column width and output to new text file? jsstevenson Programming 12 04-23-2008 02:36 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:18 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration