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:
- Read a complete line from file using
fgets()
- tokenize the input using
strtok()
, using space () as delimiter, then convert the token (if not NULL) to
int
usingstrtol()
- 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 int
s 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 aList<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
When to Use Functors Over Lambdas
Cost of Throwing C++0X Exceptions
Clang: No Out-Of-Line Virtual Method Definitions (Pure Abstract C++ Class)
Debug Assertion Failed! Expression: _Acrt_First_Block == Header
How to Compare Two Vectors for Equality Element by Element in C++
What Is the Meaning of Template<> with Empty Angle Brackets in C++
Fastest Way to Convert String to Binary
Stepping into Qt Sources in Qt Creator (In Ubuntu Linux)
What Is a Nested Name Specifier
How to Check If a Key Is Pressed on C++
Adding Static Libcurl to Code::Blocks Ide
How to Expand an Array Dynamically in C++? {Like in Vector }
Loading a File into a Vector<Char>
Make a File Pointer Read/Write to an In-Memory Location