Read first n letters from file to a string? - c++

I'm quite new with programming, and now I'm doing an exercise where I should use a cycle to read 25 first symbols from the file, which contains a string of 25 letters (+spaces if the name is shorter than 25) and two numbers. Example:
Whirlpool machine 324 789.99
as I imagine it should look something like this:
ifstream info("Information.txt");
string str;
int a;
double b;
for(int i = 0; i < 25; i++)
{ // some kind of code to get first 25 symbols into a string.
}
info >> a >> b;
And I just can't seem to find the right code to get 25 characters straight to string. Any suggestions?

An easy way is to use read() to read given number of characters:
int length = 25; // num of chars you want to read
str.resize(length, ' '); // reserve spaces
char* begin = &*str.begin();
info.read(begin, length); // <- read it here

You can use the std::copy_n() algorithm with stream buffer iterators:
std::string str;
std::copy_n(std::istreambuf_iterator<char>(info.rdbuf()),
25, std::back_inserter(str));
An approach that you might be more comfortable with is using get() with a for() loop:
for (char c; str.size() != 25 && info.get(c); )
str += c;

Given the context, I'd read the entire line into a string, using
std::getline, and then extract the substring. Something like:
std::string line;
while ( std::getline( info, line ) ) {
std::string header = line.substr( 0, 25 );
// and later...
std::istringstream rest( line.substr( 25 ) );
int a;
double b;
rest >> a >> b;
// ...
}
In general, when reading line oriented input, read the line,
then use a std::istringstream to parse it. Or, if there are
parts you can use "as is" (as is the case here), use them as is.

Related

Separate the integers from a string

i have a program which is uncompressing text files. If the input is 4A it should print "AAAA". My problem is when i am trying to separate the integers contained in the string, because after the program reads 3 numbers it seems to be getting into an infinite loop. this is my code:
while (getline(cin, line)){
for(i = 0; i<line.length(); i++) {
char * x = &line.at(i);
if(isdigit(line.at(i))){
counter = atoi (x);
}
...............
**Do Something**
I tried to print the char x as soon as it gets a value but as i said after it reads 3 numbers it's getting into an infinite loop.
Please help
Thanks in advance.
You are using the variable i in the inner second for loop(which resets the value of i) hence the infinite loop.
Here's a version w/o hand-written loops, using regex & string view:
static const std::regex expr{ "(\\d)*[a-zA-Z]" }; // zero or more digits + letter
std::string uncompress(std::string_view const& input)
{
char what{ '\0' };
unsigned long rep{ 1 };
if (std::regex_match(input.begin(), input.end(), expr))
{
char *end = const_cast<char*>(&input.back()) - 1;
rep = 1 == input.size() ? 1 : strtoul(input.data(), &end, 10);
what = input.back();
}
return std::string(rep, what);
}
In the Demo, minor modifications allow calling this while searching your input. Input sanitization is also showcased.

Read complex numbers (a+bi) from text file in C++

i want to read an array of complex numbers (in a+bi form). There are several suggestions I found on the internet, however those methods only result the real part, while the imaginary part is always 0. And infact the real part of the next number is the imaginary of the previous number.
For example, I have an text file as follow:
2+4i
1+5i
7+6i
And here is a suggestion for reading complex data
int nRow = 3;
std::complex<int> c;
std::ifstream fin("test.txt");
std::string line;
std::vector<std::complex<int> > vec;
vec.reserve(nRow);
while (std::getline(fin, line))
{
std::stringstream stream(line);
while (stream >> c)
{
vec.push_back(c);
}
}
for (int i = 0; i < nRow; i++){
cout << vec[i].real() << "\t" << vec[i].imag() << endl;
}
while (1);
return 0;
And the output result is:
2 0
4 0
1 0
Is there a proper way to read a+bi complex numbers from text file? Or do I have to read the data as a string, and then process the string to extract and convert it back to complex numer?
Thanks !
One option is to read separately the real and imaginary part in 2 ints, and the sign into a char, then emplace_back into the complex vector, like
int re, im;
char sign;
while (stream >> re >> sign >> im)
{
vec.emplace_back(re, (sign == '-') ? -im : im);
}
Here sign is a char variable that "eats" up the sign.
FILE *fp;
char line[80];
int a, b;
if ((fp = fopen("filename", "r") != NULL)
while (fgets(line, 80, fp) != NULL) {
if (sscanf(line, "%d + %di", &a, &b) == 2)
/* do something with a and b */
else
fprintf(stderr, "Not in a+bi form");
}
Your requirement (the format of input you seek) does not correspond to the method you are using to read it. The default streaming of a complex is the real and the imaginary part separated by spaces and in brackets - the sign between is not mandatory, and the trailing i is not required.
The obvious way to parse for input you seek is to read the real part, read a character, check if the character is a signed (+ or -) and ignore spaces, then read the imaginary part. That is trivial with istreams.
int real[10] = { 0 };
int imaginary[10] = { 0 };
FILE *lpFile = fopen("filename" "rt"); // Open the file
for (int i = 0; i < 10; i++) {
fscanf(lpFile, "%d+%di", &real[i], &imaginary[i]); // Read data 10 times
}
fclose(lpFile); // Close the file
This example code will read 10 complex numbers from a file.

Converting string into int array

I have a following problem. I want to convert a string like "10 15 30" to an int array with ints 10, 15, 30. I searched in google a lot, but usually solutions included vectors (which I am not familiar with) or other more complex solutions. I found a code like this:
#include <cstdio>
void foo ( char *line ) {
int num, i = 0, len;
while ( sscanf( line, "%d%n", &num, &len) == 1 ) {
printf( "Number %d is %d; ", i, num );
line += len;
i++;
}
}
int main ( ) {
char test[] = "12 45 6 23 100";
foo( test );
return 0;
}
It works and extracts numbers from string in a way I wanted, but I don't understand part with:
line += len;
Can someone explain how it works? Why are we adding len (which is int) to the string?
Solution for C++:
#include <iostream>
#include <sstream>
#include <vector>
std::vector< int > foo ( char *c_str ) {
std::istringstream line( c_str );
std::vector< int > numbers;
for ( int n; line >> n; )
numbers.push_back( n );
return numbers;
}
int main ( ) {
char test[] = "12 45 6 23 100";
std::vector< int > numbers = foo( test );
for ( int n : numbers )
std::cout << n << ' ';
return 0;
}
Output:
12 45 6 23 100
%n specifies the number of characters accessed by sscanf in its one execution and saved it in variable len.
so line + =len; is incrementing variable line, with number of characters accessed by sscanf
line + =len; is nothing but line =line+ len;
line += len; is equivalent to line = line + len;
line is a char pointer, thus the code increases the pointer by len, so that the pointer points to the next number, every time the loop is executed. Note than len is updated by the call to sscanf().
The "string" is a pointer to a character buffer. You are performing pointer arithmetic to increment the sscanf to parse the next int characters from the buffer. So, in your example:
char test[] = "12 45 6 23 100";
say *line points to test, and has some pointer value, we don't care what the value is per-se, so let's say it is 1000. After the 1st call to sscanf, you read "12" in. That is two characters, so len should return 2. line then gets set to 1002, and is now "pointing" to the next set of characters in the buffer. sscanf reads that, and this continues until no more characters in the buffer.
Look at sscanf docs. It receive format and additional params.
In params you have "%d%n" which you explain using format table from docs.
d or u
Decimal integer
Any number of decimal digits (0-9), optionally preceded by a sign (+ or -). d is for a signed argument, and u for an unsigned.
n
Count
No input is consumed.
The number of characters read so far from stdin is stored in the pointed location.
So you read integer from string and number of chars this integer consist from.
After reading part of string you move pointer into number of read chars.
sscanf( line, "%d%n", &num, &len)
This line reads a number from line, and put the digit into num and number of characters read into len.
We need len to move pointer to unread portion of the string.
Does it make sense ?
Useful links:
scanf
sscanf

File Handling in C reading multiple chars

abort action islemi durdur(MS)
abort sequence durdurma dizisi(IBM)
I have a file.txt like above. I want to read this from the file.txt separately. Besides the file.txt I got 2 more turkce.txt and ingilizce.txt
Here is what I want to do :
I want to read from file.txt and separate the words English and Turkish. After that ingilizce.txt become like this
abort action
abort sequence
and turkce.txt like this
islemi durdur(MS)
durdurma dizisi(IBM)
Also, I have multiple columns and 5127 rows. Column numbers can changes each and every row.
Here is a pic of some part of my file.txt
http://i59.tinypic.com/33m0iu8.png
Thank you for your answers.
Update : I solved the problem. The difference between left column's starting of first letter and right column's starting of firs letter are same and it equals 37.
So I use
FILE* fp = fopen("file.txt","r");
char s[256];
fgets(s, 37 , "fp);
You don't say it explicitly, but your file has two fixed-width columns, which you want to separate.
A substring of a string str from a fixed index i to the end can be expressed with pointer arithmetic: str + i or &str[i]. Strings that are not zero-terminated (like your first column) can be printed by specifying a length with printfs precision field, e.g. printf("%.*s", len, str).
A quick and dirty way to print your two columns is:
char line[80];
int col = 36;
while (fgets(line, sizeof(line), in)) {
fprintf(en, "%.*s\n", col, line);
fprintf(tr, "%s", line + col);
printf("\n");
}
This method has some drawbacks: It will print garbage if the string is shorter than your separation width, i.e. if the right column is empty. It also prints the column padding spaces for the left column, which looks untidy. So let's write a function that splits the strings nicely, which we can call like so:
while (fgets(line, sizeof(line), in)) {
char *stren, *strtr;
split_at(line, &stren, &strtr, 36);
fprintf(en, "%s\n", stren);
fprintf(tr, "%s\n", strtr);
}
The function looks like this:
void split_at(char *line, char **left, char **right, int col)
{
char *trim = line;
char *p = line;
*left = line;
*right = line + col;
while (p < *right) {
if (*p == '\0') {
*right = p;
break;
}
if (!isspace(*p)) trim = p + 1;
p++;
}
*trim = '\0';
trim = p;
while (*p) {
if (!isspace(*p)) trim = p + 1;
p++;
}
if (trim) *trim = '\0';
}
This should work for your example data. It will also work for empty left or right columns. It will not work if there is no space between the left and right columns, i.e. when the left and right art are pasted together.
This method will also work only if the code points of the strings have the same length. You haven't said which encoding you use for your data. If you use ISO-8859-9, you will be okay. If you use UTF-8, all non ASCII-codepoints, i.e. the Turkish special characters, will be represented by more than one byte. What looks like a fixed-width column doesn't have a fixed width in its memory representation.
That said, you should be safe as long as your English text is in the left column. English text is made up of only ASCII characters unless you have fancy formatting with typographic quotation marks or some such.
There could be better solutions but here is simple one.
#include <iostream>
#include <fstream>
int main()
{
std::ifstream inFile("file.txt");
std::ofstream outFileT("turkce.txt", std::ios::app);
std::ofstream outFileE("ingilizce.txt", std::ios::app);
std::string a;
std::string b;
for (int i = 0; i < 2; i++) {
inFile >> a >> b;
outFileE << a + " " + b + "\n";
inFile >> a >> b;
outFileT << a + " " + b + "\n";
}
}
I assumed you have two lines but you can determine lines count in the file first.

How do I read a specific character in a line from a file?

I'm working with a dataset of attributes in a text file which looked something like this:
e,x,y,w,t,a,f,c,b,k,e,c,s,s,w,w,p,w,o,p,n,s,g
e,f,y,y,t,l,f,c,b,w,e,r,s,y,w,w,p,w,o,p,n,y,p
e,b,s,w,t,a,f,c,b,w,e,c,s,s,w,w,p,w,o,p,n,s,g
e,b,s,w,t,a,f,c,b,w,e,c,s,s,w,w,p,w,o,p,k,s,m
e,x,y,n,t,l,f,c,b,w,e,r,s,y,w,w,p,w,o,p,k,y,g
e,b,s,w,t,a,f,c,b,k,e,c,s,s,w,w,p,w,o,p,k,s,g
e,x,f,g,f,n,f,c,n,g,e,e,s,s,w,w,p,w,o,p,n,y,u
e,b,s,y,t,l,f,c,b,k,e,c,s,s,w,w,p,w,o,p,n,s,g
Now, I'm trying to figure out how I can easily read characters from a given column (say, the 5th letter on each line, for example). I can't figure out how to do it though. Does anyone know what I might be able to do?
Considering the set of data you're dealing with is only one character and NOT of an arbitrary size, you can deduce that each character is followed by a comma, so
1 character = 2 file spaces NOT counting the desired character
If you wanted to read the 5th line, it would be the (4*2 + 1) spot in the file. You could read the line into a string and find it in the string, or just take a single char from the file each time until you've reached the desired number.
cout << "What column would you like to read from? ";
cin >> num;
int Length = (num - 1) * 2 + 1;
char ColumnLetter;
for(int i = 0; i < Length; i++)
{
inFile >> ColumnLetter;
}
If there is no whitespaces in your data, every symbol is separated by comma, and ends of the string is one symbol "\n", you can do something like that:
#include <iostream>
#include <fstream>
using std::ifstream;
ifstream file;
const int LINE_WIDTH; //number of your chars in line (without commas)
char GetFromFile(int row, int position) //row and position indexes start from 0!
{
file.seekg(row * (LINE_WIDTH * 2) + position * 2);
return file.get();
}
int main()
{
file.open("data.txt", ios::binary);
char c = GetFromFile(10, 3);
file.close();
return 0;
}