I have a file of format as:
2
3 4
7 8 9
10 20 22 02
...
basically numbers in each line , separated by spaces.
I have to read from the file, extract all numbers and maintain their line number too, as I have to make a tree later. I'm doing this to take input, but getting weird outputs.
#include<cstdio>
#include<iostream>
#include<cctype>
using namespace std;
void input()
{
char c,p;
while(c=getchar()!=EOF)
{
if(c=='\n') printf("},\n{");
else if(c==' ') printf(",");
else if(c=='0')
{
p=getchar();
if(p==' ')
{
printf("%c%c,",c,p);
}
else
{
printf("%c,",p);
}
}
else if(isalpha(c))
{
printf("%c",c);
}
}
}
int main()
{
input();
}
The image shows the input and output
You are writing more C than C++.
In C++ you can use streams. Use peek() to check the next character, and >> to actually read it.
E.g.:
using namespace std;
int main(){
ifstream s("/tmp/input");
int nr;
while (!s.eof()) {
switch (s.peek()){
case '\n': s.ignore(1); cout << "},\n{"; break;
case '\r': s.ignore(1); break;
case ' ': s.ignore(1); cout << ", "; break;
default: if (s >> nr) cout << nr;
}
}
}
Use a file stream, read line by line and parse each line with a stringstream:
std::ifstream file("filename");
std::string line;
size_t line_number(1);
while ( std::getline(file, line) ) // reads whole lines until no more lines available
{
std::stringstream stream(line);
int tmp;
std::cout << "Numbers in line " << line_number << ":";
while ( stream >> tmp ) // reads integer divided by any whitespace until no more integers available
{
std::cout << " " << tmp;
}
std::cout << "\n";
++line_number;
}
You'll need to include
#include <iostream> // for std::cout
#include <string> // for std::string
#include <fstream> // for std::ifstream
#include <sstream> // for std::stringstream
Related
I've created a program that reads different text files and stores each file in its own Vector list. However, the vector list proportion of the program is not working. Provided below is the text file im currently working on as well the program itself
Text file
A:Head:1:2:15.
B:Torso:0:6:5.
C:Leg:0:4:6.
D:Arm:0:4:8.
E:Tail:0:6:2.
Main file
#include <iostream>
#include <string>
#include <conio.h>
#include <stdio.h>
#include "driver.h"
#include "implementation.cpp"
#include <fstream>
#include <vector>
using namespace std;
int main() {
readFile();
writeFile();
robotComplexity();
getch();
return 0;
}
Implementation file containing functions
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <fstream>
#include <vector>
using namespace std;
//declaration of parts variables
char partCode;
std::string partName;
int maximum;
int minimum;
int complexity;
std::vector<string> partsVector;
std::ifstream partsList("Parts.txt");
std::string outputFile = "output.txt";
std::string input;
std::string newChar;
std::stringstream convertChar;
void readFile() //function to read Builders, Customers and Parts text file
{
std::string line;
while (std::getline(partsList, line)) {
line.pop_back();//removing '.' at end of line
std::string token;
std::istringstream ss(line);
convertChar << partCode;
convertChar >> newChar;
// then read each element by delimiter
int counter = 0;//number of elements you read
while (std::getline(ss, token, ':')) {//spilt into different records
switch (counter) {//put into appropriate value-field according to element-count
case 0:
newChar = token; //convert partCode from a char to a string
break;
case 1:
partName = token;
break;
case 2: maximum = stoi(token);
break;
case 3: minimum = stoi(token);
break;
case 4: complexity = stoi(token);
break;
default:
break;
}
counter++;//increasing counter
}
partsVector.push_back(newChar);
for(string x: partsVector)
cout << x << endl;
}
}
double robotComplexity() {
double complexity;
for(int i = 1; i < partsVector.size(); i++)
/*
if(newChar == "A") {
cout << "Character: " << newChar;
} else {
cout << "Program isnt working! :(";
} */
if(complexity > 100) {
complexity = 100;
}
cout << "\nThe Robot Complexity is: " << complexity << endl;
return complexity;
}
double robotVariability() {
double variability;
cout << "\nThe Robot Variability is: " << variability << endl;
return variability;
}
void writeFile() //writes to a file output.txt the end calculations.
{
}
The code that im currently experiencing issues with is the following
while (std::getline(partsList, line)) {
line.pop_back();//removing '.' at end of line
std::string token;
std::istringstream ss(line);
convertChar << partCode;
convertChar >> newChar;
// then read each element by delimiter
int counter = 0;//number of elements you read
while (std::getline(ss, token, ':')) {//spilt into different records
switch (counter) {//put into appropriate value-field according to element-count
case 0:
newChar = token; //convert partCode from a char to a string
break;
case 1:
partName = token;
break;
case 2: maximum = stoi(token);
break;
case 3: minimum = stoi(token);
break;
case 4: complexity = stoi(token);
break;
default:
break;
}
counter++;//increasing counter
}
partsVector.push_back(newChar);
for(string x: partsVector)
cout << x << endl;
}
When this program is compiled and executed, the following is printed out to the console
A
A
B
A
B
C
A
B
C
D
A
B
C
D
E
This is clearly wrong, as it should be printing one of each letter, as required by my program specs.
A
B
C
D
E
The purpose of this is so i know the function can successfully identify Each Record. To note, this occurs with other varialbes such as partName. Ive deducted that it is an issue with how I'm adding the variables to the vector but I am unsure why. Any help would be great Thankyou.
So the problem is simply where you are printing out the partsVector, it's inside your reading loop when it should be after the reading loop. So it should be this
while (std::getline(partsList, line)) {
...
partsVector.push_back(newChar);
}
for(string x: partsVector)
cout << x << endl;
instead of this
while (std::getline(partsList, line)) {
...
partsVector.push_back(newChar);
for(string x: partsVector)
cout << x << endl;
}
Because you are printing the parts vector as you read it in, you get those repeated values displayed.
I have a text file:
1
2
3
stop
4
The code has to add each number to the previous number to get a new value and it needs to stop when it reads the "stop" in the file.
For example output would be:
1
3
5
Reading has stopped
How can I break the code for my output to be like this?
The "reading has stopped", only has to appear when there is a 'stop' in the file. otherwise the output should just be numbers.
You can read each piece of the file into a string and end if the input is "stop". If the input isn't "stop" you can convert it to an int using std::stoi
#include <string>
#include <iostream>
#include <fstream>
int main() {
std::string numberString;
std::ifstream file{ "filename.txt" };
int previousNumber = 0;
while (file >> numberString)
{
if(numberString == "stop")
{
break;
}
try {
int number = std::stoi(numberString);
std::cout << (number + previousNumber) << " ";
previousNumber = number;
} catch(...) {
std::cout << "invalid number" << std::endl;
}
}
file.close();
std::cout << "Reading has stopped" << std::endl;
}
If your text file has only one string "stop", then there's a very easy solution: you just keep reading integers until the reading fails
int main() {
ifstream ifs("test.txt");
int first = 0;
int second;
while (ifs >> second) {
cout << first + second << ' ';
first = second;
}
cout << "Reading has stopped" << endl;
return 0;
}
The problem with this solution is that if you have other strings in the text file and you want to handle them in a different way, this solution will fail.
Hope it helps.
I would like to print integer values in a file by reading it.
The code:
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while(trainfile >> temp)
cout << temp << " ";
trainfile.close();
dfg.txt: 1 2 we er rf 5
output: 1 2
The problem is that it does not print 5.
Read to a temporary string first and then use std::stoi to try to parse an integer from it, and if it succeeds, output it:
std::string temp;
while(trainfile >> temp) {
try {
std::cout << std::stoi(temp) << " ";
}
catch(const std::invalid_argument&) {
// not a valid number
}
}
while(trainfile >> temp)
cout << temp << " ";
The above sets the failbit on trainfile on encountering any character that isn't whitespace or a digit. That terminates the loop. This is one reason I tend not to use formatted I/O that can fail on a input stream. I find it better to read text as text (not numbers) and then process the string that was just read. For example, see zenith's answer.
If you insist on doing everything from the input stream, you'll need an outer loop that clears the stream's failbit. For example,
while (! std::cin.eof())
{
while (std::cin >> temp)
{
std::cout << temp << " ";
}
std::cin.clear();
std::cin.ignore();
}
Given an input file containing 1 2 we er rf 5, the above will print 1 2 5. If the input file contains 1 2 abc345def 6, the above will print 1 2 345 6. Note that zenith's approach will print 1 2 6. Whether that 345 sandwiched between abc and def counts as an integer is up to you.
I'd recommend using zenith's solution over mine.
Update:
The above interprets abc345def as representing the integer 345. Both Zenith's solution and the above interpret 345def as representing the integer 345. To me, both abc345def and 345def should be rejected as representing an integer. So should 6.1 , but there's nothing wrong with 0x abc345def. There's nice tool in the C standard library, strtol, that nicely parses integers. It also indicates what made the parse stop. For a valid integer, it should stop at the end of the input string. With that,
#include <iostream>
#include < fstream>
#include <string>
#include <cstdlib>
int main ()
{
std::ifstream trainfile("dfg.txt");
if (!trainfile)
{
std::cerr << "Cannot open file!\n";
exit(1);
}
std::string s;
while(trainfile >> s)
{
char* end;
long num = std::strtol (s.data(), &end, 0);
if (!*end)
{
std::cout << num << " ";
}
}
trainfile.close();
std::cout << "\n";
}
string temp;
if( '0' <= temp[0] && temp[0]<='9' )
cout << temp << " ";
it will work i suppose.
Here is another way you can consider-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
ifstream trainname("dfg.txt",ios::in);
string temp;
getline(trainname,temp);
stringstream str;
str<<temp;
int extract_int;
while(getline(str, temp,' '))
{
if(stringstream(temp)>>extract_int)
cout<<extract_int<<" ";
}
return 0;
}
Or according to David Hammen's answer, you can solve it the following way-
#include <iostream>
#include <sstream>
#include <fstream>
using namespace std;
int main()
{
int temp;
char* trainname;
trainname="dfg.txt";
ifstream trainfile;
trainfile.open(trainname);
if(!trainfile){
cout<<"Cannot open file!"<<'\n';
exit(1);
}
while (!trainfile.eof())
{
while (trainfile>>temp)
cout<<temp<< " ";
trainfile.clear();
trainfile.ignore();
}
return 0;
}
I am trying to read all the characters in a file into an array. Assuming all variables are declared, why are all the characters not being read into my array. When I output some of the characters in the "storeCharacters[]" array, garbage is being returned. Please help.
This is my function:
void countChars(ifstream& input, char storeCharacters[])
{
int i = 0;
while( !input.eof() )
{
input.get(storeCharacters[i]);
i++;
}
}
After the while loop try adding storeCharacters[i] = '\0' to null terminate the string.
The easy fix to your problem if you know the maximum size of your file, then just set your array to have that size and initialize it with \0.
let's say the maximum characters count in your file is 10000.
#define DEFAULT_SIZE 10000
char storeCharacters[DEFAULT_SIZE];
memset (storeCharacters,'\0',DEFAULT_SIZE) ;
The below post should be the correct way to read a file using a buffer it has memory allocation and all what you need to know :
Correct way to read a text file into a buffer in C?
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;
void getFileName(ifstream& input, ofstream& output) //gets filename
{
string fileName;
cout << "Enter the file name: ";
cin >> fileName;
input.open(fileName.c_str());
if( !input )
{
cout << "Incorrect File Path" << endl;
exit (0);
}
output.open("c:\\users\\jacob\\desktop\\thomannProj3Results.txt");
}
void countWords(ifstream& input) //counts words
{
bool notTrue = false;
string words;
int i = 0;
while( notTrue == false )
{
if( input >> words )
{
i++;
}
else if( !(input >> words) )
notTrue = true;
}
cout << "There are " << i << " words in the file." << endl;
}
void countChars(ifstream& input, char storeCharacters[], ofstream& output) // counts characters
{
int i = 0;
while( input.good() && !input.eof() )
{
input.get(storeCharacters[i]);
i++;
}
output << storeCharacters[0];
}
void sortChars() //sorts characters
{
}
void printCount() //prints characters
{
}
int main()
{
ifstream input;
ofstream output;
char storeCharacters[1000] = {0};
getFileName(input, output);
countWords(input);
countChars(input, storeCharacters, output);
return 0;
}
I am using getline to read up to end of newline but c++ getline gets me stuff till space,
I have txt file data as
address(tab char)1420 Happy Lane
When I do
getline(reader, ss, '\t') I get address in ss string.
when I do getline(reader, ss, '\n') I just get 1420.
I want full "1420 Happy Lane", How to get it ?
Thanks.
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main( int argc, char *argv[] )
{
if( argc < 2 )
{
cout << "Missing filename as first argument" << "\n";
exit(2);
}
vector<string> myvector;
string ss;
int i=0, j=0;
ifstream reader(argv[1]);
if (! reader )
{
cout << "Error opening input file : " << " " << argv[1] << '\n';
return -1;
}
while( !reader.eof())
{
if ((i+1) % 2 == 0 )
getline(reader, ss, '\n');
else
getline(reader, ss, '\t');
if (ss[0] == '#')
{
//Skip
getline(reader,ss, '\n');i=0;
continue;
}
i++;
myvector.push_back(ss);
}
reader.close();
vector<string>::iterator it;
stringstream stream;
int vecloc=1;
string tag;
string sData;
cout << "myvector contains: \n";
for ( it=myvector.begin() ; it < myvector.end(); it++ )
{
switch (vecloc)
{
case 1: stream << *it; stream >> tag; vecloc++;break;
case 2:
stream << *it; stream >> sData;
// Do job
cout << tag << " " << sData << "\n";
// Reset.
vecloc=1; break;
default : break;
}
// Clear String stream
stream.str(""); stream.clear();
}
return(0);
}
output
/home/sr/utl
cat abc.txt
hey c++ making me nuts.
/home/sr/utl
a.out abc.txt
myvector contains:
hey c++
Paste the actual code from your editor and double check that there isn't a newline (or maybe other unexpected non-printing characters) in your data file.
This works as expected here:
#include <iostream>
#include <sstream>
using namespace std;
int main()
{
stringstream reader("address\t1420 Happy Lane\n");
string ss;
getline(reader, ss, '\t');
cout << "1: " << ss << endl;
getline(reader, ss, '\n');
cout << "2: " << ss << endl;
}
Output:
1: address
2: 1420 Happy Lane
I got a split() function you can use for that. Use \t as the delimeter:
void split(std::string &string, std::vector<std::string> &tokens, const char &delim) {
std::string ea;
std::stringstream stream(string);
while(getline(stream, ea, delim))
tokens.push_back(ea);
}
You're trying to alternate between grabbing up until a \t and grabbing up until a \n. But the times that you find a '#' comment line throw off your alternation.
By far the easiest and most robust way to handle this sort of thing is to read each line first, and then re-parse the line.