C++ Read File Line by Line Then Split Each Line Using the Delimiter

C++ Read file line by line then split each line using the delimiter

Try:

Note: if chr can contain more than 1 character then use a string to represent it.

std::ifstream file("plop");
std::string line;

while(std::getline(file, line))
{
std::stringstream linestream(line);
std::string data;
int val1;
int val2;

// If you have truly tab delimited data use getline() with third parameter.
// If your data is just white space separated data
// then the operator >> will do (it reads a space separated word into a string).
std::getline(linestream, data, '\t'); // read up-to the first tab (discard tab).

// Read the integers using the operator >>
linestream >> val1 >> val2;
}

Splitting text file on '=' delimiter line by line C++

As suggested by @Thomas in comment, set '=' as delimiter for first getline, and default delimiter newline for second getline. Demo.

string before_equal, after_equal;
string arr[2];
while (getline(cin, before_equal, '=') && getline(cin, after_equal))
{
stringstream ssin1(before_equal);
stringstream ssin2(after_equal);
if (ssin1.good() && ssin2.good()) {
ssin1 >> arr[0];
ssin2 >> arr[1];
}
else continue;
cout << arr[0] << ' ' << arr[1];
cout << endl;
}

how to read a text file in c and then split each line into tokens?

In your code, I can see,

int h_num = (int)temp;

and

int s_num = (int)temp;

No, that is not how you convert an aphanumeric string to int.

You need to use strtol() for this purpose.

Then,

sscanf(buff, "%s", &temp);

is wrong. temp is a char, you got to use %c for that.

My suggestion for a better approach:

  1. Read a complete line from file using fgets()
  2. tokenize the input using strtok(), using space () as delimiter, then convert the token (if not NULL) to int using strtol()
  3. continue untill the returned token is NULL

In this case, your code will be much more generic, as don't need to bother seperately about the number of ints present in each line.

Is there any easy way to read a line from a file, split the first text part into a string, then split the last number part into a float?

  • Grab the line into a string.
  • Get the position of the last separator.
  • Your text is a substring of the line until the position of the separator.
  • Your number is a substring of the line from the position of the separator. You'll need to convert it to double first (and you should check for errors).

[Demo]

#include <iostream>  // cout
#include <string> // find_last_of, getline, stod

int main()
{
std::string line{};
while (std::getline(std::cin, line))
{
auto pos{line.find_last_of(' ')};
auto text{line.substr(0, pos)};
auto number{std::stod(line.substr(pos))};
std::cout << "text = " << text << ", number = " << number << "\n";
}
}

// Outputs
//
// text = Plain Egg, number = 1.45
// text = Bacon and Egg, number = 2.45
// text = Muffin, number = 0.99
// text = French Toast, number = 1.99
// text = Fruit Basket, number = 2.49
// text = Cereal, number = 0.69
// text = Coffee, number = 0.5
// text = Tea, number = 0.75
//

A more robust solution taking into account @Dúthomhas' comments:

  • Trims the right hand side of the string before finding the last separator.
  • Catches std::stod exceptions.

This solution detects:

  • Blank lines.
  • Lines without texts.
  • Lines without numbers.
  • Incorrect number formats.

[Demo]

#include <boost/algorithm/string.hpp>
#include <fmt/core.h>
#include <iostream> // cout
#include <string> // find_last_of, getline, stod

int main()
{
std::string line{};
while (std::getline(std::cin, line))
{
try
{
boost::trim_right(line);
auto pos{line.find_last_of(' ')};
auto text{line.substr(0, pos)};
auto number{std::stod(line.substr(pos))};
std::cout << "text = " << text << ", number = " << number << "\n";
}
catch (const std::exception&)
{
std::cout << fmt::format("* Error: invalid line '{}'\n", line);
}
}
}

// Outputs:
//
// text = Plain Egg, number = 1.45
// text = Bacon and Egg, number = 2.45
// text = Muffin, number = 0.99
// text = French Toast, number = 1.99
// * Error: invalid line ''
// * Error: invalid line 'Fruit Basket'
// * Error: invalid line '0.75'
// * Error: invalid line 'Coffee blah'

reading file and split the line in c++

Your fstream should not open in app mode. That will seek the file to the end of file. Delete std::ios::app from it.

Split a text using different delimiters

As already pointed out in the comments section, nesting of strtok is not allowed, but you can use the function fgets to get the individual lines, and then use strtok to tokenize the contents of these lines.

If you want to solve the problem only with strtok and without fgets, then this is possible, too.

On POSIX (e.g. Linux) systems, you can simply use strtok_r instead of strtok, which allows nesting.

On non-POSIX, since nesting is not allowed, you will first have to perform a sequence of strtok calls to get pointers to the start of the individual lines, and you will have to remember all of these pointers. After finishing the first sequence of strtok calls, you can then use strtok to tokenize the contents of the individual lines:

Here is an example of such a non-POSIX solution:

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

#define MAX_LINES 100

int main( void )
{
char input[] =
"# 3 10\n"
"P1 16 3\n"
"P2 8 1\n"
"P3 10 2\n";

char *lines[MAX_LINES];
int num_lines;
char *p;

//perform the first sequence of strtok
p = strtok( input, "\n" );
for ( num_lines = 0; p != NULL; num_lines++ )
{
if ( num_lines == MAX_LINES )
{
fprintf( stderr, "Too many lines!\n" );
exit( EXIT_FAILURE );
}

//remember line
lines[num_lines] = p;

p = strtok( NULL, "\n" );
}

//perform additional sequence of strtok for every line
for ( int i = 0; i < num_lines; i++ )
{
p = strtok( lines[i], " " );

printf( "Line %d:\n", i + 1 );

for ( int j = 0; p != NULL ; j++ )
{
printf( "Token #%d: %s\n", j + 1, p );
p = strtok( NULL, " " );
}

printf( "\n" );
}
}

This program has the following output:

Line 1:
Token #1: #
Token #2: 3
Token #3: 10

Line 2:
Token #1: P1
Token #2: 16
Token #3: 3

Line 3:
Token #1: P2
Token #2: 8
Token #3: 1

Line 4:
Token #1: P3
Token #2: 10
Token #3: 2

How to write the individual tokens into a struct process is a completely different issue.

In order to convert the strings of the individual tokens to numbers, you can use the function strtol. Afterwards, you can write these numbers to the individual struct members.

In order to write to the name member of struct process, you can use the function strdup, if your platform already supports it. Otherwise, you will have to malloc sufficient space for the copy of the string, and then use strcpy. You could also make name point directly inside the input buffer, if that input buffer is not used for something else and the lifetime of that buffer is guaranteed to be at least as long as the lifetime of the struct process object. In that case, it is not necessary to copy the string.

read all lines in text file with separator

Using LINQ you can do:

List<string[]> list = File.ReadLines("YourFile.txt")
.Select(r => r.TrimEnd('#'))
.Select(line => line.Split(','))
.ToList();
  • File.ReadLines would read the file line by line.
  • .Select(r => r.TrimEnd('#')) would remove the # from end of the
    line
  • .Select(line => line.Split(',')) would split the line on comma and return an array of string items.
  • ToList() would give you a List<string[]> back.

You can also use TrimEnd and Split in a single Select statement like below, (it would result in the same output):

List<string[]> list = File.ReadLines("YourFile.txt")
.Select(r => r.TrimEnd('#').Split(','))
.ToList();


Related Topics



Leave a reply



Submit